Data types of Mat

Name Data Type Bit Size Range Other
CV_8U uchar / unsigned char 8 0 ~ 255 Default for image data
CV_8S char 8 -128 ~ 127
CV_16U ushort / unsigned short int 16 0 ~ 65535 unsigned short
CV_16S short int 16 -32768 ~ 32767 short
CV_32S int 32 -2147483648 ~ 2147483647 long
CV_32F float 32 \(1.18\times10^{-38}\) ~ \(3.40\times10^{38}\)
CV_64F double 64 \(2.23\times10^{-308}\) ~ \(1.79\times10^{308}\)

Conversion between Mat and IplImage

  1. IplImage * to Mat:

    IplImage *ipl_img;
    Mat mat_img(ipl_img);
    
  2. IplImage to Mat:

    IplImage ipl_img;
    Mat mat_img = cv::cvarrToMat(&ipl_img, true);
    
  3. Mat to IplImage:

    Mat mat_img;
    IplImage ipl_img = mat_img;
    

Access pixel intensity values of images

  1. Mat (e.g. Mat img)

    • Grayscale (8UC1)

      uchar intensity = img.at<uchar>(y, x);
      
    • Color image (BGR color ordering, the default format returned by imread)

      Vec3b intensity = img.at<Vec3b>(y, x);
      uchar blue = intensity.val[0];
      uchar green = intensity.val[1];
      uchar red = intensity.val[2];
      

      Note: the same method can be used to change pixel intensities.

  2. IplImage (e.g. IplImage* img)

    • Grayscale

      uchar intensity = CV_IMAGE_ELEM(img, uchar, h, w);
      
    • Color image

      uchar blue = CV_IMAGE_ELEM(img, uchar, y, x*3);
      uchar green = CV_IMAGE_ELEM(img, uchar, y, x*3+1);
      uchar red = CV_IMAGE_ELEM(img, uchar, y, x*3+2);
      

Content transform between Mat row/col and vector

  1. Mat row/col to Mat row/col cc: http://opencv.willowgarage.com/documentation/cpp/basic_structures.html

    // add 5-th row, multiplied by 3 to the 3rd row
    M.row(3) = M.row(3) + M.row(5)*3;
    
    // now copy 7-th column to the 1-st column
    // M.col(1) = M.col(7); // this will not work
    Mat M1 = M.col(1);
    M.col(7).copyTo(M1);
    
  2. Mat row/col to vector

    Mat data(2, 2, CV_32F);
    data.at<float>(0, 0) = 1;
    data.at<float>(0, 1) = 2;
    data.at<float>(1, 0) = 3;
    data.at<float>(1, 1) = 4;
    
    // copy second row data to p
    vector<float> p;  
    data.row(1).copyTo(p);
    
    // copy second col data to p2
    Mat data_transpose;
    transpose(data, data_transpose);
    vector<float> p2;  
    data_transpose.row(1).copyTo(p2);
    

About cv::Rect

Note that, the top and left boundary of the rectangle are inclusive, while the right and bottom boundaries are not.

  • For cv::Rect rect(x,y,w,h), its right bottom corner is rect.br() = cv::Point(x+w, y+h), not cv::Point(x+w-1, y+h-1).
  • To loop over an image ROI in OpenCV (where ROI is specified by rect ) is implemented as:

    for(int y = roi.y; y < roi.y + roi.height; y++) {
        for(int x = roi.x; x < roi.x + roi.width; x++) {
            // ...
        }
    }
    

About CvBox2D

The definition of CvBox2D in OpenCV 2.1 is as follows:

typedef struct CvBox2D
{
    CvPoint2D32f center; /* center of the box */
    CvSize2D32f size; /* box width and length */
    float angle; /* angle between the horizontal axis and the first side (i.e. length) in radians */
}
CvBox2D;

However, there are several inconsistencies when using in practice (i.e. angle), where I found that:

  1. center: no problem.
  2. size, take care of two things:
    • size is for the full size, not the half size. (Extremtly useful for ellipses respresented by CvBox2D).
    • size is consisted of width and height. Note that no perticular garantee for the size relationship amont the two (who is larger), on the other hand, it seems height will be always larger than width obtained by default (need to verify!!!)
  3. angle, several issues:

    • Type: not radians, degrees instead.
    • Meaning: not angle between the horizontal axis and the first side (i.e. length), the angle anticlockwisely from -y($\uparrow$) direction ( see the image plane in the following figure) to the first length edge instead.
    • Range: can be any size, but with cycle period of 180 (\(\pi\)), so better to first normalize to [0, 180) in practise.

    Image for showing image plane

About Sobel operator

When using the following old version:

CVAPI(void) cvSobel( const CvArr* src, CvArr* dst, int xorder, int yorder, int aperture_size CV_DEFAULT(3));

, remember that, for dst (need to be created by using cvCreateImage), only IPL_DEPTH_32F can be used, which is different from OpenCV's documentation.

For new version (together with the old version):

CV_EXPORTS_W void Sobel( InputArray src, OutputArray dst, int ddepth, int dx, int dy, int ksize=3, double scale=1, double delta=0, int borderType=BORDER_DEFAULT);

, remember that the following two versions will give the same result

  • Old version

    IplImage *xsobel, *ysobel;
    xsobel = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_32F, 1 );
    ysobel = cvCreateImage(cvSize(in->width, in->height), IPL_DEPTH_32F, 1 );
    cvSobel(img_gray, xsobel, 1, 0, 3);
    cvSobel(img_gray, ysobel, 0, 1, 3);
    
  • New version

    Mat xsobel, ysobel;
    Sobel(img_gray, xsobel, CV_32F, 1, 0, 3, 1, 0, BORDER_REFLECT);
    Sobel(img_gray, ysobel, CV_32F, 0, 1, 3, 1, 0, BORDER_REFLECT);