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

8 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.

  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-заметки

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 )

Connecting to %s