Saturday, September 26, 2009

OpenCV -- 4: operations of Matrix

Usually, OpenCV is used for computer vision applications. The friends who are familiar with computer vision must know how important is the linear algebra for computer vision, specially the matrix operations. As we know, by C++ programming, the assit about matrix calculation is always scarce. We are able to use array or vector data types to handle the matrix operation but at any rate it is not a efficient and intuitive method. But luckily with OpenCV library we are in the position to do the most of matrix calculations like adding matrix, getting the dimension or size of a matrix and so on. Here is a short introduction of some relevant matrix operations in OpenCV. Today I will give an example of how to calculata a SVD(singular value decomposision) of a matrix.


In linear algebra, SVD operation is used very commonly, like to achieve the pseudoinverse of a matrix, solving homogeneous linear operations and so forth. Before I have mentioned how to achieve a real rotation matrix with the help of SVD. And as I know lots of 3D pose estimation algorithms are based on the SVD calculations. Without the help of OpenCV library if we just implement it in C++ by ourselves it could be a large work. But just apply the function cvSVD(), everything will be solved. Here the example is about how to modify a matrix into a rotation matirx. The theory is descibed in the previous article(link above), and the C++ codes are written as follows:


#include "cv.h"
#include <stdio.h>
void main()
{
CvMat* mat = cvCreateMat(3,3,CV_32FC1);
cvZero(mat);

CV_MAT_ELEM( *mat, float, 0, 0 ) = 0.23839f;
CV_MAT_ELEM( *mat, float, 0, 1 ) = 0.957069f;
CV_MAT_ELEM( *mat, float, 0, 2 ) = 0.16489f;
CV_MAT_ELEM( *mat, float, 1, 0 ) = -0.101391f;
CV_MAT_ELEM( *mat, float, 1, 1 ) = 0.934907f;
CV_MAT_ELEM( *mat, float, 1, 2 ) = 0.340102f;
CV_MAT_ELEM( *mat, float, 2, 0 ) = 0.171344f;
CV_MAT_ELEM( *mat, float, 2, 1 ) = -0.0977953f;
CV_MAT_ELEM( *mat, float, 2, 2 ) = 0.31991f;

CvMat* U = cvCreateMat(3,3,CV_32FC1);
CvMat* D = cvCreateMat(3,3,CV_32FC1);
CvMat* V = cvCreateMat(3,3,CV_32FC1);
CvMat* Result = cvCreateMat(3,3,CV_32FC1);
cvSVD(mat, D, U, V, CV_SVD_V_T); // A = U D V^T
cvMatMul(U,V,Result);

float element1 = CV_MAT_ELEM(*Result,float,0,0);
printf("%f\n",element1);
float element2 = CV_MAT_ELEM(*Result,float,0,1);
printf("%f\n",element2);
float element3 = CV_MAT_ELEM(*Result,float,0,2);
printf("%f\n",element3);
float element4 = CV_MAT_ELEM(*Result,float,1,0);
printf("%f\n",element4);
float element5 = CV_MAT_ELEM(*Result,float,1,1);
printf("%f\n",element5);
float element6 = CV_MAT_ELEM(*Result,float,1,2);
printf("%f\n",element6);
float element7 = CV_MAT_ELEM(*Result,float,2,0);
printf("%f\n",element7);
float element8 = CV_MAT_ELEM(*Result,float,2,1);
printf("%f\n",element8);
float element9 = CV_MAT_ELEM(*Result,float,2,2);
printf("%f\n",element9);
}

Here in the codes there are several things which should be paid more attention:
cvMat* cvCreateMat(int rows, int cols, int type) is used to create a new two-dimensional matrix whereat the cvMat is a structure of a matrix data type, whose definition is carried out as follows:

typedef struct CvMat
{
int type;
int step;

/* for internal use only */
int* refcount;
int hdr_refcount;

union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data;

Actually it is just one of the ways to create a matrix, but applied commenly. The way to access a data in the matrix is also various, here I used the easy method with CV_MAT_ELEM() macro. This macro takes the matrix, the type of element to be retrieved, and the row and column numbers and then returns the element. cvSDV() is of course used to apply the SVD operation with the mark CV_SVD_V_T implied the output v is actually the transpose of v. Finally with the cvMatMul() for the multiplication of U and V the rotation matrix Result is obtained. The code is available here.

0 comments: