DragonGamer DragonGamer - 1 month ago 7
C++ Question

Manipulating pixels of a cv::MAT just doesn't take effect

The following code is just supposed to load an image, fill it with a constant value and save it again.
Of course that doesn't have a purpose yet, but still it just doesn't work.
I can read the pixel values in the loop, but all changes are without effect and saves the file as it was loaded.
Think I followed the "efficient way" here accurately: http://docs.opencv.org/2.4/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html

int main()
{
Mat im = imread("C:\\folder\\input.jpg");

int channels = im.channels();
int pixels = im.cols * channels;

if (!im.isContinuous())
{ return 0; } // Just to show that I've thought of that. It never exits here.


uchar* f = im.ptr<uchar>(0);

for (int i = 0; i < pixels; i++)
{
f[i] = (uchar)100;
}

imwrite("C:\\folder\\output.jpg", im);

return 0;
}


Normal cv functions like cvtColor() are taking effect as expected.
Are the changes through the array happening on a buffer somehow?

Huge thanks in advance!

Answer

The problem is that you are not looking at all pixels in the image. Your code only looks at im.cols*im.channels() which is a relatively small number as compared to the size of the image (im.cols*im.rows*im.channels()). When used in the for loop using the pointer, it only sets a value for couple of rows in an image ( if you look closely you will notice the saved image will have these set ).

Below is the corrected code:

int main()
{
    Mat im = imread("C:\\folder\\input.jpg");

    int channels = im.channels();
    int pixels = im.cols * im.rows * channels;

    if (!im.isContinuous())
    { return 0; } // Just to show that I've thought of that. It never exits here.


    uchar* f = im.ptr<uchar>(0);

    for (int i = 0; i < pixels; i++)
    {
        f[i] = (uchar)100;
    }

    imwrite("C:\\folder\\output.jpg", im);

    return 0;
}