Contents
1. Initialization matrix:. 1
2. Conversion from iplimage to cvmat. 1
3. Conversion of cvarr (iplimage or cvmat) to cvmat 1
4. Direct image operations 2
5. Direct cvmat operations. 3
6. indirect access to cvmat 4
7. Modify the matrix shape-cvreshape operation. 5
8. Calculate the color distance. 7
Usage and examples of cvmat in opencv Learning
Contents
1. Initialization matrix:. 1
2. Conversion from iplimage to cvmat. 1
3. Conversion of cvarr (iplimage or cvmat) to cvmat 1
4. Direct image operations 2
5. Direct cvmat operations. 3
6. indirect access to cvmat 4
7. Modify the matrix shape-cvreshape operation. 5
8. Calculate the color distance. 7
Cvmat is a basic function of opencv. Beginners should master and be proficient in application. However, I think that the way to study computer science is to constantly sum up and refine it. At the same time, we need to do a lot of practical work, such as coding, so that we can have a deep understanding and experience, so as to guide yourself to a higher level.
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:
Doublea [] = {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 justan 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 macro definition: # definecv_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
Intelem_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 );
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 voidcvdoublematprint (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 voidcv3doublematprint (const cvmat * mat)
{
Int I, J;
For (I = 0; I <mat-> rows; I ++)
{
For (j = 0; j <mat-> Cols; j ++)
{
Cvscalarscal = 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 tonrow x ncol
Cvreleasemat (& diff );
# Pragmacomment (Lib, "cxcore. lib ")
# Include "cv. H"
# Include <stdio. h>
Int main ()
{
Cvmat * MAT = cvcreatemat (3, 3, cv_32fc1 );
Cvzero (MAT); // sets the Matrix to 0.
// Assign values to Matrix Elements
Cv_mat_elem (* mat, float, 0, 0) = 1.f;
Cv_mat_elem (* mat, float, 0, 1) = 2.f;
Cv_mat_elem (* mat, float, 0, 2) = 3.f;
Cv_mat_elem (* mat, float, 1, 0) = 4.f;
Cv_mat_elem (* mat, float, 1, 1) = 5.f;
Cv_mat_elem (* mat, float, 1, 2) = 6.f;
Cv_mat_elem (* mat, float, 2, 0) = 7.f;
Cv_mat_elem (* mat, float, 2, 1) = 8.f;
Cv_mat_elem (* mat, float, 2, 2) = 9.f;
// Obtain the value of the matrix element ()
Float * P = (float *) cvptr2d (MAT, 0, 2 );
Printf ("% F \ n", * P );
Return 0;
}