Set every pixel of a Mat to a certain value, if it´s lower than a value?
Asked Answered
G

2

6

Im trying to do the following in OpenCV. How can I set every pixel of a Mat to a certain value, if it´s lower than a value?

So I want to do something like the threshold, but not quite, as I don't want to touch pixels above the given threshold.

For example: Set every pixel to 50 which is smaller than 50.

Any ideas?

Gilliangilliard answered 20/5, 2016 at 9:15 Comment(3)
Did you try something ?Adsorbent
C++, Matlab, Python or Java ?Adsorbent
In C++, i tried set to, but actually I do not really know how i use such a certain mask :/Gilliangilliard
T
13

Regarding your particular request:

set to 50 all pixels < 50

using matrix expressions and setTo is straightforward:

Mat m = ...
m.setTo(50, m < 50);

In OpenCV, you compute can compute thresholds using cv::threshold, or comparison Matrix Expression.

As you're probably already doing, you can set to 255 all values > th with:

double th = 100.0;
Mat m = ...
Mat thresh;
threshold(m, thresh, th, 255, THRESH_BINARY);

or:

double th = 100.0;
Mat m = ...
Mat thresh = m > th;

For the other way around, i.e. set to 255 all values < th, you can do like:

double th = 100.0;
Mat m = ...
Mat thresh;
threshold(m, thresh, th, 255, THRESH_BINARY_INV); // <-- using INVerted threshold

or:

double th = 100.0;
Mat m = ...
Mat thresh = m <= th; // <-- using less-or-equal comparison 

//Mat thresh = m < th; // Will also work, but result will be different from the "threshold" version

Please note that while threshold will produce a result matrix of the same type of the input, the matrix expression will always produce a CV_8U result.

Trevatrevah answered 20/5, 2016 at 11:14 Comment(0)
O
0

Since I discovered the LUT function in OpenCV, I've been trying to use it wherever I can. And this looks like a good opportunity.

I assume you're working on a matrix of type CV_8U and using OpenCV in a C++ program (it should be easily portable to Python otherwise).

You first have to define a lookUpTable like this:

cv::Mat lookUpTable(256,1,CV_8U);
for(int i = 0; i < 256; i++) {
    if(i < 50)
        lookUpTable.at<uchar>(i,0) = 50;
    else
        lookUpTable.at<uchar>(i,0) = i;
}

This means that every value in the matrix below fifty will be brought to 50.

Then, the only thing left to do is this:

cv::Mat image;  # your original image
cv::Mat thresholdedImage;
cv::LUT(image, lookUpTable, thresholdedImage);

And here you go.

There may be more efficient solutions, or maybe I'm doing something unnecessarily complicated but I find it elegant.

Owensby answered 20/5, 2016 at 9:38 Comment(4)
I´m using CV_32F. So actually I can not acess it via uchar because most of my pixels are float, right?Gilliangilliard
Oh yes. Then my solution is really not adapted for you, I'm afraid. You can still try to use OpenCv threshold function on 1.0 - originalImage with adapted thresholdsOwensby
Actually I can not use the OpenCV threshold function, because there I can not check for smaller than. Or do i think wrong?Gilliangilliard
You can use threshold to bring smaller values to zero. which is not exactly what you want. However, checking for greater values on 1.0 - originalImage is the same as checking for smaller on originalImageOwensby

© 2022 - 2024 — McMap. All rights reserved.