jeffrico el exotico
jeffrico el exotico

Reputation: 315

OpenCV integral image pixel access error

I have been pounding my head on the wall for about a week, because I've been unable to access the pixel values of an integral image correctly. I have deleted a previous post as this is meant to be a more concrete example of my problem.

I have pinpointed the exact problem, i.e. at least discovered some method to the madness

For debug purposes I'm not outputting all pixels, just rows of 5:

The code is clean and simple (but by all means comments are welcome)

int main(){
    Mat src = imread("test.png");
    imshow("SOURCE", src);
    cvtColor(src, src, CV_BGR2GRAY);
    GpuMat gpu_src, gpu_ii;
    gpu_src.upload(src);
    integral(gpu_src, gpu_ii);
    Mat cpu_ii;
    gpu_ii.download(cpu_ii);
    imshow("Just for fun", cpu_ii);
    for (int j = 0; j < 8; j++) {
        for (int i = 0; i < 8; i++) {
            //Center Value: Pixel value at (i,j)
            int center_val = (int)cpu_ii.data[(i * cpu_ii.step) + (j * cpu_ii.elemSize())];
            cout << center_val << endl;
        }
        cout << "next line" << endl;
    }

}

Now, the first row prints 0 0 0 ..., perfect The second row: 160 64 224 128 32 192 96

Clearly these results are wrong. More specifically: The results which are expected for the second value should be 320, which incidentally is approx 320-255. The results show clearly that the value starts over from 0 as soon as the result of the sum is over 255.. How can I eliminate this problem?

Kind Regards,

Upvotes: 0

Views: 2223

Answers (2)

Sam
Sam

Reputation: 20058

The pixel values are correct, but the way to access is wrong.

You can use the at operator:

cout << cpu_ii.at<int>(j, i) << endl;

or , by pointer, using an integer pointer. img.data returns a char*, and if not cast to int, you are accessing the wrong memory position:

int* data = (int*)cpu_ii.data;

int center_val = data[(i * cpu_ii.step) + (j * cpu_ii.elemSize())];
cout << center_val << endl;

Upvotes: 1

L&#233;o
L&#233;o

Reputation: 88

It seems you are having an overflow because the destination image of your integral has only one channel with one byte. You should try to use a GpuMap constructor that receives the type (constants like CV_32UC1) as an argument.

http://fossies.org/dox/OpenCV-2.3.1a/classcv_1_1gpu_1_1GpuMat.html

Right now I don't have a computer with openCV installed to test this, so I might be wrong.

Upvotes: 0

Related Questions