Get data from Mat / cv::Mat in OpenCV


I have been working on George Nebehay’s OpenTLD version to port it to python and it has given me a good amount of exposure to C++ and OpenCV with C++. I must confess that I never thought C++ would be so amazing. Despite of C++ being an intermediate-level language, I think it’s better than Python. The usage of pointers and robustness/run-time speed are plus point of C++ over Python. Python may be a very high level language and easy to understand, I don’t think it can be compared to C++ yet.

So, moving on to OpenCV. After getting a good amount of exposure to OpenCV C++, I would like to add a series of blog posts which would be based on my basic OpenCV knowledge. I have already written couple of posts about beginning OpenCV.

Today, I found this question on stackoverflow http://stackoverflow.com/questions/11166760/how-to-improve-sorting-pixels-in-cvmat/11167045 . The guy was asking about how to access image pixels and sort them quickly. He was using cvGetReal2D. So, the problem here is cvGetReal2D is very slow and I found that out when I was making filters in Python OpenCV. Those filters are used to add or remove noise from the image and to make image sharp or smooth. So, back to accessing pixel values from the image in OpenCV. Few points you should always remember.

  • cvGetReal2D is slow
  • IplImage is old. Stop using IplImage. Use cv::Mat (for C) or Mat (for C++)
  • Install OpenCV 2.3.1 or higher. I would suggest OpenCV 2.4
  • If you are using Visual Studio on Windows, please stop. Too much linking problems. Dual boot with a good Linux distro and install OpenCV.

I wandered off again. Back to getting pixel values from Mat.

Load Image as Mat and get it’s data pointer.

    Mat img = imread("filename.jpg",CV_LOAD_IMAGE_COLOR);
    unsigned char *input = (unsigned char*)(img.data);

Mat.data gives a pointer which refers to the original data matrix. In this data matrix, all the pixel values are stored in 1D array. i.e. b1,g1,r1,b2,g2,r2,…
Images in OpenCV are always stored in the format of BGR.

Getting Pixel Values:
Let’s assume we have an image of size 512×512 pixels. Pixel in first row and first column will have some value (b00, g00, r00) and pixel in nth row and mth column will have value (bnm, gnm ,rnm).


    int i,j,r,g,b;
    for(int i = 0;i < img.rows ;i++){
			for(int j = 0;j < img.cols ;j++){
                b = input[img.step * j + i ] ;
                g = input[img.step * j + i + 1];
                r = input[img.step * j + i + 2];
            }
        }

To get pixel values of nth row and mth cloumn,
b = input[img.step * m + n ]
g = input[img.step * m + n + 1]
r = input[img.step * m + n + 2]

So, to sum it all

#include<opencv2/highgui/highgui.hpp>
#include<stdio.h>
using namespace cv;
using namespace std;
int main()
{
    Mat img = imread("/home/jay/Pictures/python.jpg",CV_LOAD_IMAGE_COLOR);
    unsigned char *input = (unsigned char*)(img.data);
    int i,j,r,g,b;
    for(int i = 0;i < img.rows;i++){
	for(int j = 0;j < img.cols;j++){
            b = input[img.step * j + i ] ;
            g = input[img.step * j + i + 1];
            r = input[img.step * j + i + 2];
            }
        }
    return 0;
}

For detailed information about Mat data access – Read this.

P.S. I’m thinking of buying a domain.

About these ads

11 thoughts on “Get data from Mat / cv::Mat in OpenCV

  1. There are actually even faster methods. You could actually use a Mat iterator to access the pixel values. Check out some of the examples in the samples provided.

    • How is that a faster method ?
      Here I’m accessing values using a pointer. I think the iterator does the same thing.
      Anyway, thanks for that. I’ll check that out.

  2. Just to chime in on the above two comments, I don’t think there will be a noticeable difference between accessing with an iterator vs directly accessing using a pointer. The iterator is essentially a wrapper for accessing the pointer and does the same thing behind the scenes.

  3. It looks like you’re missing a step size in your offset computations.
    b = input[img.cols * j * step + i * step ] ;
    g = input[img.cols * j * step + i * step + 1];
    r = input[img.cols * j * step + i * step + 2];

    for bgra frames this is 4, likely the same for bgr frames (aka gaps).
    you can access it with Mat.step()

    • Hey,
      I think you have misunderstood the mat.step here. Here(http://docs.opencv.org/modules/core/doc/basic_structures.html?highlight=step#bool%20Mat::isContinuous%28%29%20const) it seems that mat.step is not the step size actually, but the total size of a row(in bytes). It also says here that -

      step – Number of bytes each matrix row occupies. The value should include the padding bytes at the end of each row, if any. If the parameter is missing (set to AUTO_STEP ), no padding is assumed and the actual step is calculated as cols*elemSize() . See Mat::elemSize()

      And I tried that and got a segmentation fault(it was obvious). Here I am accessing the values directly through an unsigned pointer structure. Mat.data gives a pointer to an array(matrix) where all the b, g, r values of all the pixels are stored.

      Cheers,
      Jay

  4. Pingback: Accessing cv::Mat with C++ primitive types « Hyon Lim

  5. Pingback: как cv::Mat заполнить массивом из unsigned char | Мои IT-заметки

  6. Its giving an exception at the first line of your loop. ‘b = input[img.step * j + i ] ;’ The exception thrown is ‘: Access violation reading location 0×01121850.’

  7. I think using MatIterator_ is better still, because nested for loop will not be necessary, and there is no chance of overflow, and the method needs not be altered depending on the type of image. For example, if you have a 16bit greyscale image, replacing unsigned int with float in this code will not work and will surely throw segmentation fault.

  8. Hello..
    I am new to opencv/c++ programming. Actually I am trying to learn programming concepts …I am trying to write a code which will take RGB image and convert it into grayscale (average method)…can someone please help me in finding the error in my code???
    This will really help
    void Conversion(Mat& output , const Mat& input)
    {
    int rows = input.rows;
    int cols = input.cols;
    double R,G,B;

    for(int i=0; i<rows; i++)
    {
    for(int j=0; j<cols; j++)
    {
    int index = j+i*cols;
    int outindex = 3*index;
    R = double(input.data[index]);
    G = double(input.data[index+1]);
    B = double(input.data[index+2]);

    float temp = (input.data[index]+input.data[index+1]+input.data[index+2])/3.0;
    output.data[outindex]= temp; //assuming one byte output format

    }
    }}
    void Conversion(Mat& output , const Mat& input);
    int main()
    {
    Mat myImage= imread("C:\\Users\\Visual Studio 2010\\Projects\\Pictures\\RGBImage.jpg");
    unsigned char*imp= (unsigned char*)(myImage.data);
    Mat Gray_Image (myImage.rows, myImage.cols, CV_8UC1);
    if(!myImage.data)
    printf("Image did not load properly\n"); //1-1- if image has no data show an error message
    else
    {
    Conversion(Gray_Image, myImage);
    }

    imshow("Input_Image", myImage);
    imshow("CPU_IMAGE", Gray_Image);
    cvWaitKey(0);
    return 0;

    Thank you

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s