Search code examples
c++opencvpixelmat

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!


Solution

  • 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;
    }