c++ and opencv get and set pixel color to Mat

C++OpencvImage ProcessingPixelMat

C++ Problem Overview


I'm trying to set a new color value to some pixel into a cv::Mat image my code is below:

    Mat image = img;
    for(int y=0;y<img.rows;y++)
    {
        for(int x=0;x<img.cols;x++)
        {
        Vec3b color = image.at<Vec3b>(Point(x,y));
        if(color[0] > 150 && color[1] > 150 && color[2] > 150)
        {
        	color[0] = 0;
        	color[1] = 0;
        	color[2] = 0;
        	cout << "Pixel >200 :" << x << "," << y << endl;
        }
        else
        {
        	color.val[0] = 255;
        	color.val[1] = 255;
        	color.val[2] = 255;
        }
    }
    imwrite("../images/imgopti"+to_string(i)+".tiff",image);

It seems to get the good pixel in output (with cout) however in the output image (with imwrite) the pixel concerned aren't modified. I have already tried using color.val[0].. I still can't figure out why the pixel colors in the output image dont change. thanks

C++ Solutions


Solution 1 - C++

You did everything except copying the new pixel value back to the image.

This line takes a copy of the pixel into a local variable:

Vec3b color = image.at<Vec3b>(Point(x,y));

So, after changing color as you require, just set it back like this:

image.at<Vec3b>(Point(x,y)) = color;

So, in full, something like this:

Mat image = img;
for(int y=0;y<img.rows;y++)
{
    for(int x=0;x<img.cols;x++)
    {
        // get pixel
        Vec3b & color = image.at<Vec3b>(y,x);

        // ... do something to the color ....
        color[0] = 13;
        color[1] = 13;
        color[2] = 13;

        // set pixel
        //image.at<Vec3b>(Point(x,y)) = color;
        //if you copy value
    }
}

Solution 2 - C++

just use a reference:

Vec3b & color = image.at<Vec3b>(y,x);
color[2] = 13;

Solution 3 - C++

I would not use .at for performance reasons.

Define a struct:

//#pragma pack(push, 2) //not useful (see comments below)
struct BGR {
   	uchar blue;
    uchar green;
   	uchar red;	};

And then use it like this on your cv::Mat image:

BGR& bgr = image.ptr<BGR>(y)[x];

image.ptr(y) gives you a pointer to the scanline y. And iterate through the pixels with loops of x and y

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestiongrllView Question on Stackoverflow
Solution 1 - C++Roger RowlandView Answer on Stackoverflow
Solution 2 - C++berakView Answer on Stackoverflow
Solution 3 - C++FlockeView Answer on Stackoverflow