How to apply a different b/w threshold to each row of the image?

Hi,
I would convert an image from grayscale to black-and-white using the im2bw function, and I need to apply a different threshold to each row of the image. Which is the most efficient way to do this? Is there a way to avoid the "for" cycle?
Thank you very much.

2 Comments

Hello, do you still have the code of for and loop?
Roman, it would be something like
[rows, columns, numberOfColorChannels] = size(theImage);
binaryImage = false(rows, columns);
for row = 1 : rows
% Get the threshold for this row - however you do it (I don't know).
thisThreshold = whatever;
% Now threshold/binarize the image for this row only.
binaryImage(row, :) = theImage(row, :) > thisThreshold;
end

Sign in to comment.

 Accepted Answer

Depending on the input type of your image, you may be able to just do a simple thresholding operation (as below), otherwise you'll have to delve a little deeper into image processing.
asdf=imread('example.tif');
figure,imshow(asdf)
zxcv=rgb2gray(asdf);
figure,imshow(zxcv)
thresh=[50*ones(325,1);150*ones(325,1)]; %here you set the threshold for each row
threshMatrix=repmat(thresh,1,600);
BW=zxcv>threshMatrix;
figure,imshow(BW)

2 Comments

Thank you very much for your answer, it may be a good way. I'll compare this with the for loop.
You're right. The execution time with your solution is about 1.6 seconds, instead using im2bw and the for loop it is about 5.1 seconds. Very good idea, thank you again.

Sign in to comment.

More Answers (1)

No, you'll have to use a for loop. It's not a problem though. It will be very fast. No need to worry about for loops that are only a few thousand iterations.
Why do you need a different threshold for each row anyway?
You might be able to use a different function. There are new binarization functions. See Steve's blog:

7 Comments

Ok, I'll use a for loop with im2bw. Thank you for your answer and also for the new functions, I didn't know them. I'll consider also these functions.
I need a different threshold for each row because I'm dealing with an object detection problem. Considering the y direction, my pictures have a variable brightness. Consequently, the object that I'm looking for could appear in a light or a dark region. So, to differentiate the threshold may help to improve the precision of the detection.
I don't see why you would need a for loop. You obviously start with a column vector of threshold values. Simply repmat your column vector with the number of columns of the image, and compare the image to that matrix, as per Andrew Bliss' answer.
@ Image Analyst: you're right, also the for loop is an acceptable solution. However, in my case the one proposed by Andrew Bliss seems to be better. Thank you for answering, kind regards.
@ Guillaume: excuse me, I didn't explain very well. I mean that only if I have to use im2bw, I'll use the for loop. Thank you.
When you assumed that you needed a new threshold at each row and said that your current approach was to do it row by row, the most logical assumption (at least to me) was that the threshold depended on the image data in that row. Doesn't that seem reasonable? You mentioned using im2bw() but that determines a global threshold based on the whole image if you just pass it the whole image, and that was unacceptable to you. Indicating that using im2bw to do the automatic threshold was an acceptable threshold determination method but that you needed it to give different thresholds based on each row was a strong indication that you needed to pass each row to im2bw() and did not know the thresholds in advance.
Note that Andrew's answer assumes that somehow you know the threshold in advance for each row. If you do, then use his answer. If you need to determine the threshold on a row-by-row basis then you'll need to use my answer since you would need to get the row of image data to examine it.
Since you accepted Andrews answer you must know the thresholds in advance, so tell me how you got thresholds in advance that were different for each row? Do the thresholds not depend on the image data?
All you said is correct. I mentioned im2bw because before your answer it was the only function I knew to convert from grayscale to binary. I usually perform it manually setting the threshold, instead of using graythresh. But I just need the most efficient way, also without using im2bw. As you said, I know the thresholds in advance.
The mine is a very targeted issue, so I need to manually set proper thresholds. These depend on the image data, but not directly. To get them, I investigated several past cases. I saw that, if average intensity of pixels around the object is "x" (in my case, it can be assumed as mean(I,2) value), a good threshold could be a value around "y".
I collected all "x-y" couples and interpolate them using polyfit, and I use the resulting polynomial to get the y values (thresholds) I need.
OK. I have a nice manual/interactive thresholding utility in my File Exchange if you're interested: http://www.mathworks.com/matlabcentral/fileexchange/29372-thresholding-an-image

Sign in to comment.

Asked:

Nut
on 13 Jun 2016

Commented:

on 22 Jan 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!