Pixel multiplication gives different result

asked 2017-07-12 01:27:27 -0500

In detail I read a image in c++ and multiplied its pixel of 3 channel BGR value with 255, It gives me resultant image as negative image. In this case, if you are multiplying a pixel value with 255, it should be saturated to white have to give [255, 255, 255]. But negative image have different values. The following code is,

uchar *p;
for (int i = 0; i < nRows; i++){
    p = image.ptr<uchar>(i);
    for (int j = 0; j < nCols; j++){
        p[j] =  table[p[j]] * 255;
        //cout << (int)p[j] * 255 <<" ";
    }
}

image description

So I test a user-defined Mat with one pixel value of 3 channel BGR value with 255, producing result of [255, 255, 255].

Mat sample = Mat(1, 1, CV_8UC3);
uchar *l;
l = sample.data;
for (int i = 0; i < sample.rows * sample.cols; i++){
    cout << sample * 255;
    cout << sample;
}
edit retag flag offensive close merge delete

Comments

well, the proper way to invert the colors would be: Scalar::all(255) - image not by multiplying.

your test code is broken (you never initialize the Mat's values, so the result is arbitrary)

please explain the relevance of the table in the 1st snippet, and why you use uchar* for what is obviously a Vec3b (BGR) image.

berak gravatar imageberak ( 2017-07-12 01:51:19 -0500 )edit

First thing i am not trying to inverse the image. I am new to openCV, So in a intention to workout the tutorials, I trying to multiply a pixel by a value to break down the problem (from the tutorials for masking http://docs.opencv.org/2.4/doc/tutori...). Then i got inverse image of input image. Next thing table is just reducing the image value or like round up. I use uchar* to access image array continuously like just shown in the tutorials.

Debian LeoPragi gravatar imageDebian LeoPragi ( 2017-07-12 02:08:12 -0500 )edit

as a general advice - please stay away from per-pixel loops, and use high-level, optimized algorithms instead.

and that tutorial is a bit unlucky, it has nothing to with masks, and in the end, you should indeed use filter2D, not try your own convolution.

berak gravatar imageberak ( 2017-07-12 02:39:35 -0500 )edit

Okay berak! Thanks...But i just wanted to know. For a intuition Multiplying every pixels with 255 must give a white image right?

Debian LeoPragi gravatar imageDebian LeoPragi ( 2017-07-12 03:20:25 -0500 )edit

well, almost. any pixel with 0 value will stay unchanged.

in your test code, it should be:

Mat sample = Mat(1, 1, CV_8UC3, Scalar(15,16,17)); // at least put some value into it
berak gravatar imageberak ( 2017-07-12 03:37:32 -0500 )edit

Done what you have said. Now I noticed that after multiplication values exceeds 255. So saturation must take place. According to algorithm I(x,y)= min (max (round (r), 0), 255) in this page [http://docs.opencv.org/2.4/modules/co...] resultant value should be 255. So white image have to come. Still we have negative image here. Why?

In algorithm round is just going to give the same number right?

Debian LeoPragi gravatar imageDebian LeoPragi ( 2017-07-12 04:16:52 -0500 )edit

You use unsigned char which ranges from 0 to 255 and write the uchar value back into the uchar matrix... When you multiply eg.: 255 * 255 weired stuff gonna happen since the value exceeds 255. Just write the value to eg.: a CV_16UC1 Matrix and it should work.

Ice_T02 gravatar imageIce_T02 ( 2017-07-12 04:34:20 -0500 )edit

I assumed that, to create a image(Mat object) with CV_16UC1 type that you have specified and assigned the manipulated old Mat matrix value to new image Mat matrix value. Still not working. However if value exceed 255 than i must saturate to 255, producing a image of white.

Debian LeoPragi gravatar imageDebian LeoPragi ( 2017-07-12 05:16:28 -0500 )edit