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 asstep, 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: OpenCV
Read more!