Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV replacing specific pixel values with another value

I want to detect a specific pixel value (let's say 128 in a unsigned 8 bit 1-channel image) in a cv::Mat image and replace the value of all the pixels with that specific value with another value (replacing each 128 with 120). Is there any efficient way of doing this? Or should I do the search and assertion operations pixel by pixel?

I started coding but could not completed. Here is the part of my code:

cv::Mat source; 
unsigned oldValue = 128;
unsigned newValue = 120;

cv::Mat temp = (source == oldValue);
like image 935
elmass Avatar asked Sep 02 '15 08:09

elmass


People also ask

What is Vec3b?

Vec3b is the abbreviation for "vector with 3 byte entries" Here those byte entries are unsigned char values to represent values between 0 .. 255. Each byte typically represents the intensity of a single color channel, so on default, Vec3b is a single RGB (or better BGR) pixel.

What is pixel in OpenCV?

You also learned about pixels, the building blocks of an image, along with the image coordinate system OpenCV uses. Unlike the coordinate system you studied in basic algebra, where the origin, denoted as (0, 0), is at the bottom-left, the origin for images is actually located at the top-left of the image.


2 Answers

You can use setTo, using a mask:

Mat src;
// ... src is somehow initialized

int oldValue = 128;
int newValue = 120;

src.setTo(newValue, src == oldValue); 
like image 88
Miki Avatar answered Oct 14 '22 04:10

Miki


not sure whether it is more efficient than .setTo , but you could use a look-up-table (especially if you have multiple values you want to replace and you have to replace the same values in multiple images (e.g. in each image of a video stream)).

int main()
{
    cv::Mat input = cv::imread("../inputData/Lenna.png");
    cv::Mat gray;
    cv::cvtColor(input,gray,CV_BGR2GRAY);

    // prepare this once:
    cv::Mat lookUpTable(1, 256, CV_8U);
    uchar* p = lookUpTable.data;
    for( int i = 0; i < 256; ++i)
    {
        p[i] = i;
    }

    // your modifications
    p[128] = 120;


    // now you can use LUT efficiently
    cv::Mat result;
    cv::LUT(gray, lookUpTable, result);


    cv::imshow("result", result);
    cv::imwrite("../outputData/LUT.png", result);
    cv::waitKey(0);

    return 0;
}

According to http://docs.opencv.org/doc/tutorials/core/how_to_scan_images/how_to_scan_images.html#the-core-function this is very efficient in special scenarios.

like image 37
Micka Avatar answered Oct 14 '22 03:10

Micka