1. Initialization matrix:
Method 1: point-by-point assignment:
CvMat * mat = cvCreateMat (2, 2, CV_64FC1 );
CvZero (mat );
CvmSet (mat, 0, 0, 1 );
CvmSet (mat, 0, 1, 2 );
CvmSet (mat, 1, 0, 3 );
CvmSet (mat, 2, 2, 4 );
CvReleaseMat (& mat );
Method 2: connect existing arrays:
Double a [] = {1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12 };
CvMat mat = cvMat (3, 4, CV_64FC1, a); // 64FC1 for double
// CvReleaseMat is not required because the data memory allocation is performed by arrays defined by double.
2. Conversion from IplImage to cvMat
Method 1: cvGetMat:
CvMat mathdr, * mat = cvGetMat (img, & mathdr );
Method 2: cvConvert:
CvMat * mat = cvCreateMat (img-> height, img-> width, CV_64FC3 );
CvConvert (img, mat );
// # Define cvConvert (src, dst) cvConvertScale (src), (dst), 1, 0)
3. Conversion of cvArr (IplImage or cvMat) to cvMat
Method 1: cvGetMat:
Int coi = 0;
CvMat * mat = (CvMat *) arr;
If (! CV_IS_MAT (mat ))
{
Mat = cvGetMat (mat, & matstub, & coi );
If (coi! = 0) reutn; // CV_ERROR_FROM_CODE (CV_BadCOI );
}
Written as a function:
// This is just an example of function
// To support both IplImage and cvMat as an input
CVAPI (void) cvIamArr (const CvArr * arr)
{
CV_FUNCNAME ("cvIamArr ");
_ BEGIN __;
CV_ASSERT (mat = NULL );
CvMat matstub, * mat = (CvMat *) arr;
Int coi = 0;
If (! CV_IS_MAT (mat ))
{
CV_CALL (mat = cvGetMat (mat, & matstub, & coi ));
If (coi! = 0) CV_ERROR_FROM_CODE (CV_BadCOI );
}
// Process as cvMat
_ END __;
}
4. Direct image operations
Method 1: directly operate int col, row, z in an array;
Uchar B, g, r;
For (y = 0; row height; y ++)
{
For (col = 0; col width; col ++)
{
B = img-> imageData [img-> widthStep * row + col * 3]
G = img-> imageData [img-> widthStep * row + col * 3 + 1];
R = img-> imageData [img-> widthStep * row + col * 3 + 2];
}
}
Method 2: Macro operation:
Int row, col;
Uchar B, g, r;
For (row = 0; row height; row ++)
{
For (col = 0; col width; col ++)
{
B = CV_IMAGE_ELEM (img, uchar, row, col * 3 );
G = CV_IMAGE_ELEM (img, uchar, row, col * 3 + 1 );
R = CV_IMAGE_ELEM (img, uchar, row, col * 3 + 2 );
}
}
Note: cv_image_elem (IMG, uchar, row, Col * IMG-> nchannels + CH)
5. Direct cvmat operations
The direct operation of arrays is depressing because it depends on the Data Type of arrays.
For cv_32fc1 (1 channel float ):
Cvmat * m = cvcreatemat (4, 4, cv_32fc1 );
M-> data. Fl [row * m-> Cols + Col] = (float) 3.0;
For cv_64fc1 (1 channel double ):
Cvmat * m = cvcreatemat (4, 4, cv_64fc1 );
M-> data. DB [row * m-> Cols + Col] = 3.0;
Generally, for arrays of Channel 1:
Cvmat * m = cvcreatemat (4, 4, cv_64fc1 );
Cv_mat_elem (* m, double, row, col) = 3.0;
Note that the double type must be input based on the data type of the array. This macro cannot do anything about multi-channel.
For multi-channel:
Let's take a look at the definition of this macro: # define cv_mat_elem_cn (MAT, elemtype, row, col )/
(* (Elemtype *) (MAT). Data. PTR + (size_t) (MAT). Step * (ROW) + sizeof (elemtype) * (COL )))
If (cv_mat_depth (m-> type) = cv_32f)
CV_MAT_ELEM_CN (* M, float, row, col * CV_MAT_CN (M-> type) + ch) = 3.0;
If (CV_MAT_DEPTH (M-> type) = CV_64F)
CV_MAT_ELEM_CN (* M, double, row, col * CV_MAT_CN (M-> type) + ch) = 3.0;
The optimization method is as follows:
# Define CV_8U 0
# Define CV_8S 1
# Define CV_16U 2
# Define CV_16S 3
# Define CV_32S 4
# Define CV_32F 5
# Define CV_64F 6
# Define CV_USRTYPE1 7
Int elem_size = CV_ELEM_SIZE (mat-> type );
For (col = start_col; col <end_col; col ++ ){
For (row = 0; row <mat-> rows; row ++ ){
For (elem = 0; elem <elem_size; elem ++ ){
(Mat-> data. ptr + (size_t) mat-> step * row) + (elem_size * col) [elem] =
(Submat-> data. ptr + (size_t) submat-> step * row) + (elem_size * (col-start_col) [elem];
}
}
}
The following operations are recommended for multi-channel Arrays:
For (row = 0; row <mat-> rows; row ++)
{
P = mat-> data. fl + row * (mat-> step/4 );
/* Divide by 4 because a float occupies 4 bytes. If it is double, it is divided by 8. uchar is not divided */
For (COL = 0; Col <mat-> Cols; Col ++)
{
* P = (float) Row + Col;
* (P + 1) = (float) Row + Col + 1;
* (P + 2) = (float) Row + Col + 2;
P + = 3;
}
}
For two or four channels:
Cvmat * vector = cvcreatemat (1, 3, cv_32sc2 );
Cv_mat_elem (* vector, cvpoint, 0, 0) = cvpoint (100,100 );
Cvmat * vector = cvcreatemat (1, 3, cv_64fc4 );
Cv_mat_elem (* vector, cvscalar, 0, 0) = cvscalar (0, 0, 0 );
6. indirect access to cvmat
Cvmget/set is the easiest way to access the cv_32fc1 and cv_64fc1 arrays. Its access speed is almost the same as direct access speed.
Cvmset (MAT, row, Col, value );
Cvmget (MAT, row, col );
Example: print an array
Inline void cvdoublematprint (const cvmat * mat)
{
Int I, J;
For (I = 0; I <mat-> rows; I ++)
{
For (j = 0; j <mat-> Cols; j ++)
{
Printf ("% F", cvmget (MAT, I, j ));
}
Printf ("/N ");
}
}
CvGet/Set2D is a good choice for other data types, such as those with multiple channels.
CvScalar scalar = cvGet2D (mat, row, col );
CvSet2D (mat, row, col, cvScalar (r, g, B ));
Note: The data cannot be int, because cvGet2D obtains the double type in essence.
For example, print a multi-channel matrix:
Inline void cv3DoubleMatPrint (const CvMat * mat)
{
Int I, j;
For (I = 0; I <mat-> rows; I ++)
{
For (j = 0; j <mat-> cols; j ++)
{
CvScalar scal = cvGet2D (mat, I, j );
Printf ("(% f, % f, % f)", scal. val [0], scal. val [1], scal. val [2]);
}
Printf ("/N ");
}
}
7. Modify the matrix shape-cvreshape operation
Experiments show that the sequence of matrix operations is: first meet the channel, then meet the column, and finally meet the row.
Note: This is different from MATLAB. MATLAB is the sequence of rows, columns, and channels.
Here is an example:
For one channel:
// 1 channel
Cvmat * mat, mathdr;
Double data [] = {11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34 };
Cvmat * orig = & cvmat (3, 4, cv_64fc1, data );
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
Mat = cvReshape (orig, & mathdr, 1, 1); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 11 12 13 14 21 22 23 24 31 32 33 34
Mat = cvReshape (mat, & mathdr, 1, 3); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
Mat = cvReshape (orig, & mathdr, 1, 12); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 11
// 12
// 13
// 14
// 21
// 22
// 23
// 24
// 31
// 32
// 33
// 34
MAT = cvreshape (MAT, & mathdr, 1, 3); // new_ch, new_rows
Cvdoublematprint (MAT); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
MAT = cvreshape (orig, & mathdr, 1, 2); // new_ch, new_rows
Cvdoublematprint (MAT); // above
// 11 12 13 14 21 22
// 23 24 31 32 33 34
MAT = cvreshape (MAT, & mathdr, 1, 3); // new_ch, new_rows
Cvdoublematprint (MAT); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
MAT = cvreshape (orig, & mathdr, 1, 6); // new_ch, new_rows
Cvdoublematprint (MAT); // above
// 11 12
// 13 14
// 21 22
// 23 24
// 31 32
// 33 34
Mat = cvReshape (mat, & mathdr, 1, 3); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
// Use cvTranspose and cvReshape (mat, & mathdr, 1, 2) to get
// 11 23
// 12 24
// 13 31
// 14 32
// 21 33
// 22 34
// Use cvTranspose again when to recover
For three channels
// 3 channels
CvMat mathdr, * mat;
Double data [] ={ 111,112,113,121,122,123,
211,212,213,221,222,223 };
CvMat * orig = & cvMat (2, 2, CV_64FC3, data );
// (111,112,113) (121,122,123)
// (211,212,213) (221,222,223)
Mat = cvReshape (orig, & mathdr, 3, 1); // new_ch, new_rows
Cv3DoubleMatPrint (mat); // above
// (111,112,113) (121,122,123) (211,212,213) (221,222,223)
// Concatinate in column first order
Mat = cvReshape (orig, & mathdr, 1, 1); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 111 112 113 121 122 123 211 212 213 221 222 223
// Concatinate in channel first, column second, row third
Mat = cvReshape (orig, & mathdr, 1, 3); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 111 112 113 121
// 122 123 211 212
// 213 221 222 223
// Channel first, column second, row third
Mat = cvReshape (orig, & mathdr, 1, 4); // new_ch, new_rows
CvDoubleMatPrint (mat); // above
// 111 112 113
// 121 122 123
// 211 212 213
// 221 222 223
// Channel first, column second, row third
// Memorize this transform because this is useful
// Add (or do something) color channels
CvMat * mat2 = cvCreateMat (mat-> cols, mat-> rows, mat-> type );
CvTranspose (mat, mat2 );
CvDoubleMatPrint (mat2); // above
// 111 121 211 221
// 112 122 212 222
// 113 123 213 223
CvReleaseMat (& mat2 );
8. Calculate the color distance
We want to calculate the distance between each pixel of img1 and img2, expressed in dist, as defined below
IplImage * img1 = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 3 );
IplImage * img2 = cvCreateImage (cvSize (w, h), IPL_DEPTH_8U, 3 );
CvMat * dist = cvCreateMat (h, w, CV_64FC1 );
The stupid idea is: cvSplit-> cvSub-> cvMul-> cvAdd
The Code is as follows:
IplImage * img1B = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * img1G = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * img1R = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * img2B = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * img2G = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * img2R = cvCreateImage (cvGetSize (img1), img1-> depth, 1 );
IplImage * diff = cvCreateImage (cvGetSize (img1), IPL_DEPTH_64F, 1 );
CvSplit (img1, img1B, img1G, img1R );
CvSplit (img2, img2B, img2G, img2R );
Cvsub (img1b, img2b, diff );
Cvmul (diff, diff, DIST );
Cvsub (img1g, img2g, diff );
Cvmul (diff, diff, diff );
Cvadd (diff, DIST, DIST );
Cvsub (img1r, img2r, diff );
Cvmul (diff, diff, diff );
Cvadd (diff, DIST, DIST );
Cvreleaseimage (& img1b );
Cvreleaseimage (& img1g );
Cvreleaseimage (& img1r );
Cvreleaseimage (& img2b );
Cvreleaseimage (& img2g );
Cvreleaseimage (& img2r );
Cvreleaseimage (& diff );
The clever idea is:
Int d = img1-> nchannels; // D: number of colors (dimension)
Int n = img1-> width * img1-> height; // n: number of pixels
Cvmat mat1hdr, * mat1 = cvreshape (img1, & mat1hdr, 1, n); // n x D (colors)
CvMat mat2hdr, * mat2 = cvReshape (img2, & mat2hdr, 1, N); // N x D (colors)
CvMat diffhdr, * diff = cvCreateMat (N, D, CV_64FC1); // N x D, temporal buff
CvSub (mat1, mat2, diff );
CvMul (diff, diff, diff );
Dist = cvReshape (dist, & disthdr, 1, N); // nRow x nCol to N x 1
CvReduce (diff, dist, 1, CV_REDUCE_SUM); // N x D to N x 1
Dist = cvReshape (dist, & disthdr, 1, img1-> height); // Restore N x 1 to nRow x nCol
CvReleaseMat (& diff );