Thresholding an image
Now that you have learned two different ways to work with image pixels, we will present another useful and common tool found in image processing software, which is thresholding. Image thresholding can be defined as the process of creating binary images by setting pixels with values above a certain threshold to 1 and the rest to 0. It is usually used for separating the foreground from the background of an image. As we did for the previous examples, we will show three different ways to implement image thresholding in MATLAB; using for
loops, a special way of indexing, and using a ready-made thresholding MATLAB function.
Image thresholding using for loops
The classic programming way to implement grayscale image thresholding is by using two nested for
loops in a similar fashion to the one used in the previous sections. More specifically, the following script can be used to threshold my_image.bmp
:
img = imread('my_image.bmp'); % Read image subplot (1,2,1) % Open a figure for 2 images imshow(img) % Show original image title ('Original image') % Add title threshold = 150; % Set threshold level for pos_r = 1:size(img,1) % For all rows for pos_c = 1:size(img,2) % For all columns if img(pos_r,pos_c) > threshold % Check pixel value img(pos_r,pos_c) = 255; % Set pixels above 150 to 255 else img(pos_r,pos_c) = 0; % Set pixels below 150 to 0 end % End if end % End columns for loop end % End rows for loop img = logical(img); % Convert img to binary subplot (1,2,2) % Make second image spot active imshow(img) % Show thresholded image title ('Thresholded image') % Add title
If we save this script with the name ThresholdingUsingLoops.m
and execute it through the command line, we will get the following result:
Even though we have managed to accomplish our goal in a straight-forward manner, the method we used was very generic and does not take advantage of all the special powers of MATLAB. So, let's take a look at two alternative ways to perform thresholding.
Image thresholding using indexing
We have already mentioned that one of the great advantages of using MATLAB for matrix manipulation is indexing. Some examples of indexing have already been given, but they don't seem to be helpful for thresholding tasks. Therefore, we have to explore alternative indexing methods to perform such tasks. An interesting approach is to define the pixels we want to access using a condition instead of a predefined range of indices. This method is called logical indexing and it chooses those pixels that correspond to nonzero values in the array generated by our condition. You can find more information about logical indexing at http://www.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html.
Assuming we want to perform the same task as in the previous section, the equivalent logical indexing code replacing the two nested for loops
, will be just two lines:
img = imread('my_image.bmp'); % Read image subplot (1,2,1) % Open a figure for 2 images imshow(img) % Show original image title ('Original image') % Add title threshold = 150; % Set threshold level img(img > threshold) = 255; % Set pixels above 150 to 255 img(img <= threshold) = 0; % Set pixels below 150 to 0 img = logical(img); % Convert img to binary subplot (1,2,2) % Make second image spot active imshow(img) % Show thresholded image title ('Thresholded image') % Add title
Saving this script as ThresholdingUsingIndexing.m
and executing it through the command line, yields the following result:
This example reveals the power of logical indexing in MATLAB. The two highlighted lines have performed the same actions as the for
loops they replaced. The first one chose the indices of pixels in our image that exceeded 150
and replaced the values of the pixels at those indices with 255
. The second one followed the same rationale, choosing indices of pixels with values less than or equal to 150
and replaced them with zeros. Note that thresholding using indexing method pinpoints indices in all dimensions; the same command would be used for a one-dimensional matrix and an N-dimensional matrix.
Image thresholding using im2bw
Now that you know how to programmatically threshold an image, let's see the ready-made function to perform the same thing. It is called im2bw
and we can find more about it using the help
command. Typing help im2bw
in the command line will give you all the details you need to use this function. In this context, we have to make some minor adjustments in our approach.
As you may have noticed already, after the thresholding process of the previous two methods, we also performed a conversion of the result to logical form. This was done in order to follow the convention of thresholding that is the pixel values of the result should be binary (either 0
or 1
). In our case, the original image was 8 bit integer, so we used the minimum and maximum values (0
, 255
). To convert the result to binary, the logical command was used.
When using the im2bw
function, we should bear in mind that it is designed to work with threshold values between 0
and 1
. This means, that we either have to convert our image to have pixel values in that range, or convert the threshold. The second is more practical, so we will divide the threshold value (150
in our case) by the maximum brightness level of the image (255
in the uint8
case). Since we have compacted our code to a big extent, we can now load the image, threshold it, and display the final result in just four lines in the Command Window:
>> img = imread('my_image.bmp'); >> subplot(1,2,1), imshow(img), title('Original Image') >> img = im2bw(img,150/255); >> subplot(1,2,2), imshow(img), title('Thresholded Image')
Note that in the last part of code we gave more than one command in a single line. Since this is not a formal program, but a command-line script to perform some actions, such a style is permitted. Whenever you use this style of scripting, remember that the multiple commands should be separated by either commas (when we don't care if the output of each function gets printed on screen, or the functions don't produce an output), or semicolons when we don't want outputs to be printed on screen. Of course, you can also write these lines of code in a script and execute it through the command line, as we did before.
Image thresholding using an automatic threshold
Till here we have performed all our thresholding tasks using a predefined manual threshold (in our example, 150
). Sometimes, a better threshold choice can be acquired by automatic techniques, such as the one proposed by Otsu, which chooses the threshold to minimize the intra-class variance of the black and white pixels (Otsu, N., A Threshold Selection Method from Gray-Level Histograms, IEEE Transactions on Systems, Man, and Cybernetics, Vol. 9, No. 1, 1979, pp. 62-66). This method is used in the function graythresh
. The automatic threshold value estimated by graythresh
can then be used instead of a manual value in one of the processes described previously. Let's see how this can be accomplished using im2bw
:
>> img = imread('my_image.bmp') >> subplot(1,2,1), imshow(img), title('Original Image'') >> thresh = graythresh(img); >> img = im2bw(img,thresh); >> subplot(1,2,2), imshow(img), title('Thresholded Image')
As we can see from the result, the automatically defined threshold value produces a very different result than the one produced by setting the threshold to 150
. This means that we should always choose our threshold carefully depending on what the final goal is. If we want to see what the automatically selected threshold was, in range –
to 1
and in range 0
to 255
, we can type the following commands:
>> thresh >> thresh*255
The result will be as follows:
>> thresh thresh = 0.3882 >> thresh*255 ans = 99
Choosing graythresh
works well when the image we want to threshold is bimodal. To better understand the meaning of this word, we should discuss histograms.