norman's blog

Notes of an amnesiac.
Never stop thinking.
Find an aesthetic description.

Thursday, June 4, 2009

CvArr, CvMat and IplImage

Step, Width and Height

Both IplImage and CvMat have the above three elements, which make them compatible. For CvMat, the three element are named as step, cols and rows; while for IplImage, they are denoted as widthStep, width and height
The step element in the matrix array is the length in bytes of a row in the matrix. In that structure, cols or width alone is not enough to move between matrix rows because, for machine efficiency, matrix or image allocation is done to the nearest four-byte boundary. Thus for instance, a matrix of width three bytes would be allocated four bytes with the last one ignored. When using cvCreateMat() and cvCreateImage() to creates the header and allocates data of IplImage and CvMat, the cvCreateImage will align each row on four-byte boundaries while cvCreateMat align rows to minimal possible steps.
Codes for creating a CvMat object according to four-byte alignment rule manually:
CvMat* mat = cvCreateMatHeader(rows, cols, type);
mat->step = 4 * (mat->cols * CV_ELEM_SIZE1(mat->type) * CV_MAT_CN(mat->type) / 4 + 1);//critical
cvCreateData(mat);

Transform between IplImage and CvMat

cvGetMat and cvGetImage are used to perform transformation between IplImage and CvMat, in which there is no new memory allocated for block data. The new object just points to the data block of original object, inheriting the setup of alignment(including width, height and step).

To transform from IplImage to CvMat, Use function:

CvMat* cvGetMat( const CvArr* arr, CvMat* mat, int* coi = 0, int allowND );
The function cvGetMat returns matrix header for the input array that can be matrix - CvMat*, image - IplImage* or multi-dimensional dense array - CvMatND* (latter case is allowed only if allowND != 0) .
In the case of matrix the function simply returns the input pointer.
In the case of IplImage* or CvMatND* it initializes mat structure with parameters of the current image ROI and returns pointer to this temporary structure.
Usage:
CvMat stub, *dst_mat;
dst_mat = cvGetMat(src_img, &stub, 0, 0);

To transform from CvMat to IplImage, Use function:

IplImage* cvGetImage( const CvArr* arr, IplImage* image_header );  
The function cvGetImage returns image header for the input array that can be matrix - CvMat*, or image - IplImage*.
In the case of image the function simply returns the input pointer.
In the case of CvMat* it initializes image_header structure with parameters of the input matrix.
Usage:
IplImage stub, *dst_img;
dst_img = cvGetImage(src_mat, &stub);
Note that if we transform IplImage to CvMat and then transform CvMat back to IplImage, we can get different headers if the ROI is set, and thus some IPL functions that calculate image stride from its width and align may fail on the resultant image.
These two functions are error prone due to the directly pointing to the original data block and the different default alignment rules of CvMat and IplImage. A practical way to avoid conflicts is to align CvMat manually.

Labels:

6 Comments:

Blogger Unknown said...

Can anyone help me with conversion of CvImgae <-> CvMat objects?

cvReshape won't do, as in openCV the images data is not continuous due to their data storage conventions (it is stored with "holes" in the data storage )

cvGetImage is not working for me either as the created object (dst_img on this page) can not be released - header or data alike. In debug mode it is evident that the output image depth is -2147483616 which does not make any sense.

Can anyone help me by mail with the so need conversion of data among images and matrices other than accessing and copying element by element in nested loops?
Thanks,
Amitai
amitai@isec-technologies.com

November 10, 2009 at 9:16 AM  
Blogger Unknown said...

I found one function in OpenCV 2.2 which may be used to convert IplImage to CvMat and vice-versa. The function is:
void cvConvertImage( const CvArr* src, CvArr* dst, int flags=0 );

Hope it is useful,
Ankur
ankurnigam18@gmail.com

April 21, 2011 at 11:19 PM  
Blogger Matt Montag said...

Thanks for this post. I do not like the uncomfortable place between OpenCV 1.0 and 2.0.

September 28, 2011 at 1:28 PM  
Anonymous Anonymous said...

Is there anyway to convert a cvMat to cvArr

April 3, 2012 at 10:33 PM  
Blogger Unknown said...

Is it possible to construct an IplImage from 8bpp monochrome data? I have stripped the data from a file and wish to construct an actual image; I have the rows and columns data and the length of the data. I have successfully regenerated the image using BAE Systems's SOCET GXP so I know the data itself has been extracted correctly.

January 2, 2013 at 12:49 AM  
Blogger Everton Ferreira dos Santos said...

Thank you a lot!! I finally found a way to convert an cv::Math to IplImage!

January 23, 2013 at 6:13 AM  

Post a Comment

Subscribe to Post Comments [Atom]

<< Home