5

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?

Community
  • 1
  • 1
J.J
  • 99
  • 1
  • 4

2 Answers2

12

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.

Miki
  • 40,887
  • 13
  • 123
  • 202
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.

Sunreef
  • 4,452
  • 21
  • 33
  • I´m using CV_32F. So actually I can not acess it via uchar because most of my pixels are float, right? – J.J May 20 '16 at 09:55
  • 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 thresholds – Sunreef May 20 '16 at 10:02
  • Actually I can not use the OpenCV threshold function, because there I can not check for smaller than. Or do i think wrong? – J.J May 20 '16 at 10:22
  • 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 `originalImage` – Sunreef May 20 '16 at 11:09