Mat equivalent to ipImage->imageData[]

I have old C-API code using lpImage arrays. I am in the process of converting it from OCV 2.4 C-API to OCV 3.4 CPP-API using Mat or UMat where appropriate. Almost all of the conversion so far has been tedious but pretty much straight forward…except for this: (the cImage is an lpImage) This part of the code is legacy that I did not write so even in C-API I an not 100% sure what is going on here.

val += ((unsigned char)cImage->imageData[right] > (unsigned char)cImage->imageData[center]) ? 1 : 0;

I have converted the lpImage from cImage to a Mat mCImage. What would be the equivalent for an lpImage->imageData[] for the mCImage Mat?

Any help or point in the right direction would be appreciated.

Ed

wild guess:
there are more lines like that, checking different neighour positions against a center value ?
and each comparison adds a bit (1,2,4,8,16,…) to val?
(like in a “lbp” or “census” feature ?)

the calculations for right and center are important. do show them.

the expression above merely tests if the value at one location is greater than the value at another location, and counts how many locations satisfy this (there’s a loop, right?). the ternary operator is superfluous.

Yes, this is part of a loop and you are right that each line adds 1,2,4,8,16,etc.

The “center”, “down” etc have all been defined a Points that are listed in a table as in:

center = PointToIndexTable[x][y];

So I need to duplicate this for Mats. What is the Mat equivalent to lpImage->imageData{}?

Would it be `Mat.get(int row, int col)? I might try that.

Any idea other than that?

note: I mistook .get() for .at<>()

stick with the Mat::get<>() method. working with row and column coordinates is a lot better than manual index calculations. make sure to give the correct type, e.g. cv::Vec3b for CV_8UC3, or just uint8_t if CV_8U/CV_8UC1

sort of, but in java :wink:

correct c++ access would be either:

img.at<uchar>(y,x);

or, using a “typed Mat”:

Mat_<uchar> img = ...
img(y,x); // most elegant, imo

or even:

uchar *ptr = img.ptr<uchar>(0); // ptr to 1st element
...
ptr[y*w+x] = ...

however, you probably should avoid slow & error-prone per-pixel code in favour of nicely optimized vector functions, using “shifted ROIs”:

so, instead of:

    Mat_<uchar> fI(z.size());
    Mat_<uchar> img(z);
    const int m=1;
    for ( int r=m; r<z.rows-m; r++ )
    {
        for ( int c=m; c<z.cols-m; c++ )
        {
            uchar v = 0;
            uchar cen = img(r,c);
            v |= (img(r-1,c  ) > cen) << 0;
            v |= (img(r-1,c+1) > cen) << 1;
            v |= (img(r  ,c+1) > cen) << 2;
            v |= (img(r+1,c+1) > cen) << 3;
            v |= (img(r+1,c  ) > cen) << 4;
            v |= (img(r+1,c-1) > cen) << 5;
            v |= (img(r  ,c-1) > cen) << 6;
            v |= (img(r-1,c-1) > cen) << 7;
            fI(r,c) = v;
        }
    }

do:

#define SHIFTED_MATS_3x3 \
        int M = I.rows; \
        int N = I.cols; \
        Mat I7 = I(Range(1,M-2), Range(1,N-2));\
        Mat I6 = I(Range(1,M-2), Range(2,N-1));\
        Mat I5 = I(Range(1,M-2), Range(3,N  ));\
        Mat I4 = I(Range(2,M-1), Range(3,N  ));\
        Mat I3 = I(Range(3,M  ), Range(3,N  ));\
        Mat I2 = I(Range(3,M  ), Range(2,N-1));\
        Mat I1 = I(Range(3,M  ), Range(1,N-2));\
        Mat I0 = I(Range(2,M-1), Range(1,N-2));\
        Mat Ic = I(Range(2,M-1), Range(2,N-1));\


        SHIFTED_MATS_3x3;

        Mat fI = ((I7>Ic)&128) |
             ((I6>Ic)&64)  |
             ((I5>Ic)&32)  |
             ((I4>Ic)&16)  |
             ((I3>Ic)&8)   |
             ((I2>Ic)&4)   |
             ((I1>Ic)&2)   |
             ((I0>Ic)&1);

(~3 times faster on my box !)

1 Like

Berak, Fantastic. I was jumping around in Google and saw the get() and didn’t realize that was Java. I knew the at() already and just never put 2 and 2 together. This is great. I really appreciate it. I was completely stumped when I saw this imageData[] code. Thanks again.

I might not get to try this out until Monday but I will let you know…

Berak, PS… That worked. Since my Mat was already established I went with the simple

img.at<uchar>(y,x);

Later on, when everything is running smoothly, I will revisit this to tweek it per your suggestions. Thanks again. Nice way to go into the weekend :wink:

Ed

1 Like