Visual Media Processing Using Matlab Beginner's Guide
上QQ阅读APP看书,第一时间看更新

Time for action – isolating the red pixels in an image

In this example, we will try to isolate the red-orange tips of the fence in the previous image, using manual thresholding of all channels. The ultimate goal is to acquire a binary image with only pixels belonging in the area we want, being equal to one. Let's start by using imtool to get a better idea of what the RGB values of the pixels we want to isolate are.

  1. First, we load the image and call imtool:
    >> img = imread('my_image_color.bmp');
    >> imtool(img);

    Then, we will choose Inspect Pixel Values by clicking on the second icon from the left and placing our cursor on one of the red tips to see the RGB values of its neighbor pixels. We can repeat the process for other tips and also for getting samples from other image areas.

  2. Now that we have an idea of what the RGB values are for our ROIs, we can begin the process of thresholding. By observing the color values with the help of imtool, we can set a general thresholding rule for our ROIs, which would be something like: "we want to keep pixels with high R values and low G and B values". The implementation of this rule could be something like this:
    >> red_binary = img(:,:,1) > 150;
    >> green_binary = img(:,:,2) < 150;
    >> blue_binary = img(:,:,3) < 150;

    Now, we can mix the three binary images using the AND operator and display the result on a new figure:

    >> final_mask = red_binary & green_binary & blue_binary;
    >> figure, imshow(final_mask)
  3. We can see that, while we are on the right track, our result is not optimal yet. It needs a little tweaking of the selected thresholds and perhaps, some morphology. The wise thing to do in these situations is to write a function that takes the color thresholds as inputs and returns the thresholded binary image. This way, we will be able to test several sets of threshold values with one line of code for each, instead of typing all the commands of step 2. Let's use the editor to write a function called RGBThreshold.m:
    function [output] = RGBThreshold(input,thresholds)
    % Function that performs color image thresholding using
    % user-defined threshold values. Emphasises red areas.
    % Inputs:
    % input      - Input image
    % thresholds – 1x3 matrix with the threshold values 
    %  for the R, G and B color channels.
    % Output:   
    % output - Output image (binary)
    red_bin = input(:,:,1) > thresholds(1); % Red thresholding
    green_bin = input(:,:,2) < thresholds(2); % Green thresholding
    blue_bin = input(:,:,3) < thresholds(3); % Blue thresholding
    output = red_bin & green_bin & blue_bin; % Final image
  4. Let's now use our new function to generate and compare results for three different sets of thresholds, that is, {R,G,B} = {150,150,150}, {160,130,130}, and {180,140,140}:
    >> [output1] = RGBThreshold(img,[150 150 150]);
    >> [output2] = RGBThreshold(img,[160 130 130]);
    >> [output3] = RGBThreshold(img,[180 140 140]);
    >> subplot(1,3,1),imshow(output1),title('Using [150 150 150]')
    >> subplot(1,3,2),imshow(output2),title('Using [160 130 130]')
    >> subplot(1,3,3),imshow(output3),title('Using [180 140 140]')
  5. We can now choose the preferred result, so that we can tweak it using the morphology tools. Let's use the middle result, output2, which apparently needs dilation to expand the ROIs to the size we would want. First, we will set the pixels above the line 100 to zero, to exclude unneeded areas. Then, we can use imdilate with a structuring element like a diamond of size 5px, to see what happens (we'll show the result next to the original image):
    >> output2(1:100,:) = 0;
    >> final = imdilate(output2,strel('disk', 5));
    >> figure, subplot(1,2,1), imshow(img), title('Original Image')
    >> subplot(1,2,2), imshow(final), title('Final binary mask')

What just happened?

In this example, we combined several methods presented so far for grayscale images to generate a modified masking example for color images. We used imtool to acquire a feel of what the pixel values are for several regions of the image, including the region that we want to isolate. Then, we wrote a function to perform thresholding using user-defined threshold values for all the three color channels. With a trial-and-error process, we selected the most suitable thresholds (step 4), cleaned the areas we did not wish to include, and then dilated the binary result to acquire the final binary image (step 5).

A useful conclusion derived from this example would be that RGB images can be thresholded, but the process should really be performed in all color channels in order to optimize our result. This has to do with the fact that the RGB color space channels are highly correlated to each other, meaning that all three values are required to describe a given color. This results in the counterintuitive deduction, that we usually cannot just threshold the R channel to isolate red pixels, but would need to combine the R channel mask with the G and B channel masks to produce optimal results.