Introduction to Mat, CvMat and IplImage in opencv and the conversion between the three

Common data containers related to image operations in OpenCV are Mat, cvMat and IplImage. These three types can represent and display images. The difference is: the Mat type focuses on calculation, and the mathematics is higher. OpenCV optimizes the calculation of the Mat type; the CvMat and IplImage types focus more on the "image", and opencv focuses on the "image". Image operations (zoom, single-channel extraction, image threshold operations, etc.) have been optimized. Before opencv2.0, opencv was completely implemented in C, but the relationship between the IplImage type and the CvMat type is similar to the inheritance relationship in object-oriented. In fact, there is a more abstract base class on top of CvMat-CvArr, which is common in source code.

1. It is clearly stated in the opencv document that CvMat is obsolete (CvMat is now obsolete, consider using Mat instead) is not recommended;
2. Derivation relationship: CvArr -> CvMat -> IplImage
3. A set of things for Mat is imread, imshow, etc., different from CvArr and its subclasses cvLoadImage(), cvShowImage()...

1. Mat type: Matrix type, Matrix.
In openCV, Mat is a multi-dimensional dense data array. It can be used to process common multi-dimensional data such as vectors and matrices, images, histograms, etc.
Mat has 3 important methods:
1. Mat mat = imread(const String* filename); read image
2. imshow(const string frameName, InputArray mat); display image
3. imwrite (const string& filename, InputArray img);
Compared with the CvMat and IplImage types, the Mat type for storing images has stronger matrix operation capabilities and supports common matrix operations. In computationally intensive applications, converting the CvMat and IplImage types to the Mat type will greatly reduce the computational time.
Two, CvMat type: image type

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;
#ifdef __cplusplus
    union
    {
        int rows;
        int height;
    };
    union
    {
        int cols;
        int width;
    };
#else
    int rows;
    int cols;
#endif
}
CvMat;


In openCV, there is no vector data structure. At any time, but when we want to represent a vector, we can use matrix data to represent it. However, the CvMat type is more abstract than the vector concept we learned in the linear algebra course. For example, the element data type of CvMat is not limited to the basic data type. For example, the following creates a two-dimensional data matrix: CvMat* cvCreatMat(int rows, int cols, int type);
type can be any predefined data type, such as RGB or other multi-channel data. In this way, a colorful image can be represented on a CvMat matrix.
3. IplImage: Image type.
In terms of the type relationship, we can say that the IplImage type inherits from the CvMat type. Of course, it also includes other variables to parse it into image data, which is defined as follows:


typedef struct _IplImage  
    {  
        int nSize; /* IplImage size*/  
        int ID; /* Version(=0)*/  
        int nChannels; /* Most OPENCV functions support 1, 2, 3 or 4 channels*/  
        int alphaChannel; / * Ignored by OpenCV*/  
        int depth; /* Pixel bit depth: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U, 
                               IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported by  
        char channel*/*/  
        Char ]; /* Same as above*/  
        int dataOrder; /* 0-interleaved color channels, 1-separate color channels. 
                               cvCreateImage can only create interleaved images */  
        int origin; /* 0-top-left structure, 
                               1-bottom-left structure (Windows bitmaps style) */  
        int align; /* image line arrangement (4 or 8). OpenCV ignores it and uses widthStep instead of */  
        int width; /* image width in pixels*/  
        int height; /* The number of high pixels of the image*/  
        struct _IplROI *roi;/* The region of interest of the image. When the value is not empty, only the region will be processed */  
        struct _IplImage *maskROI; /* NULL must be set in OpenCV */  
        void * imageId; /* Same as above*/  
        struct _IplTileInfo *tileInfo; /* Same as above*/  
        int imageSize; /* Image data size (in interleaved format imageSize=image->height*image->widthStep), unit byte*/  
        char *imageData; /* Point to the image data to be arranged*/  
        int widthStep; /* The size of the image line to be arranged, in bytes*/  
        int BorderMode[4]; /* Border end mode, ignored by OpenCV*/  
        int BorderConst[4]; /* Same as above*/  
        char *imageDataOrigin; /* The pointer points to a different image data structure (not necessarily arranged), which is prepared to correct the image memory allocation */  
    }  
    IplImage;  
two of the dataOrder Value: The interleaved color channel is the color data arrangement will be the staggered arrangement of BGRBGR... Separate color channels are stored in several color planes when there are several color channels. roi is the IplROI structure, which contains the xOffset, yOffset, height, width, coi member variables, where xOffset, yOffset are the x, y coordinates, and coi represents the channel of interest (channel of interest), and only when it is not 0 effective. Access to the data elements in the image is divided into indirect storage and direct storage. When the image element is a floating point type, (uchar *) is changed to (float *): 
Supplement: IplImage is derived from CvMat, and CvMat is derived from CvArr, ie CvArr -> CvMat -> IplImage

            CvArr is used as the parameter of the function, no matter what CvMat or IplImage is passed in, it is processed internally by CvMat.

The small difference when creating CvMat and IplImage:

1. When building a matrix, the first parameter is the number of rows and the second parameter is the number of columns.

CvMat* cvCreateMat( int rows, int cols, int type );

2. When creating an image, the first parameter of CvSize is the width, which is the number of columns; the second parameter is the height, which is the number of rows. This is the opposite of the CvMat matrix.

IplImage* cvCreateImage(CvSize size, int depth, int channels );

CvSize cvSize( int width, int height );

In addition, each line of the internal buffer of IplImage is aligned by 4 bytes, CvMat does not have this restriction

Four, mutual conversion
4.1IplImage -> Mat

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* srcImg = cvLoadImage("F:\\IM_VIDEO\\kobe.jpg");
    Mat m = cvarrToMat(srcImg, true);
    namedWindow("kobe image", CV_WINDOW_AUTOSIZE);
    imshow("kobe image", m);
    waitKey(0);
    return 0;
}


operation result:

4.2 Mat -> IplImage:

 

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    Mat m = imread("F:\\IM_VIDEO\\kobe.jpg");
    IplImage* transIplimage = cvCloneImage(&(IplImage)m);
    cvShowImage("kobe image", transIplimage);
    waitKey(0);
    cvReleaseImage(&transIplimage);
    return 0;
}


The running result is the same as above.
5. Pixel acquisition method
5.1 The pixel acquisition method of Mat method can be found at: http://blog.csdn.net/piaoxuezhong/article/details/54236227

5.2 Pixel acquisition of IplImage method

Direct access:
The two more important elements for us are: char *imageData and widthStep. imageData stores image pixel data, and widStep is similar to step in CvMat, which represents the length of row data in bytes.
An m*n single-channel byte image, its imageData is arranged as follows:


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
    uchar* tmp = new uchar[img->width*img->height*img->nChannels];
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            *tmp = ((uchar *)(img->imageData + i*img->widthStep))[j];
        }
    }
    cout << "第1行第1列的图像灰度值: " << (float)tmp[0]<< endl;
    cvShowImage("kobe image", img);
    waitKey(0);
    cvReleaseImage(&img);
    return 0;
}


Pointer acquisition method:


#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
using namespace std;
using namespace cv;
int main()
{
    IplImage* img = cvCreateImage(cvSize(640, 480), IPL_DEPTH_8U, 1);
    //uchar* tmp = new uchar[img->width*img->height*img->nChannels];
    uchar* data = (uchar *)img->imageData;
    int step = img->widthStep / sizeof(uchar);
    uchar* tmp = data;
    for (int i = 0; i < img->height; i++)
    {
        for (int j = 0; j < img->width; j++)
        {
            *tmp = data[i*step + j];
        }
    }
    cout << "第1行第1列的图像灰度值: " << (float)tmp[0] << endl;
    cvShowImage("kobe image", img);
    waitKey(0);
    cvReleaseImage(&img);
    return 0;
}


 

Guess you like

Origin blog.csdn.net/yangdashi888/article/details/104522460