Time for action – understanding the value of thresholding

In this example, we will try to separate the two useful aspects of image binarization, so that we can then use them appropriately. The first thing we will do is to locate a faulty ROI of an image and then we will try to cover it using what we have already learned. For this example, we will be again using my great-grandmother's photograph. So, let's start:

  1. First, we need to load the grayscale image we have created in the previous chapter, by using imread:
    >> img = imread('graygrandma.BMP');
  2. The second step is to perform thresholding, as we have already done in the previous chapter (using the same threshold, which was 220):
    >> img_bin = (img> 220);  % Image img_bin is now binary
  3. Now, let's perform some rough patching of the image in the specific ROI that has pixels with values over 220. A way to accomplish this is to change these values to a grayer shade, for example, 100:
    >> img_patched = img;
    >> img_patched(img_bin) = 100;
  4. At this point, we have three images in our Workspace. The original one (img), the binarized one (img_bin) and the patched one (img_patched). Let's display them side-by-side to get a better understanding of what happened:
    >> subplot(1,3,1),imshow(img),title('Original Image')
    >> subplot(1,3,2),imshow(img_bin),title('Binarized Image')
    >> subplot(1,3,3),imshow(img_patched),title('Patched Image')

The resulting images will be as follows:

What just happened?

As explained earlier, this example pinpoints the usage of thresholded images called masks to alter the specific parts of the image. The first step, as always, is to load an image into MATLAB, using the imread function. We chose to use this image, because of the apparent deficiency caused by the flash of our camera. The ultimate goal is to patch up this deficiency and produce a smoother result.

The second step is to threshold the image, using a threshold value that isolates the areas with high brightness values. This was done using the threshold value as 220, as we did in the previous chapter. Typing img_bin = (img> 220) generates a binary image (mask) with pixels equal to 1 in the positions where the original image pixels were higher than 220. All other pixels will be set to 0.

The third step performs the actual masking process. First, we create a duplicate of our original image, and name it as img_patched. Then, we type in img_patched(img_bin) = 100 to replace all pixels that are equal to 1 in our mask with the value 100 in the original image. This command actually tells MATLAB to find the positions of all pixels in the mask equal to 1 and use them to set the respective pixels of the original image to 100. This could be accomplished in many alternative ways, but this is the one that depicts the actual use of a mask, taking advantage of its size being identical to the size of the original image (or else the replacement command would result in an error message).

Our fourth step is used for verification purposes, as it shows the original image, the binary mask, and the masked image side-by-side. This way, it is easier to understand the entire masking process.

Tip

An alternative and more compact way to get the same masking result in the preceding example, would be using img_patched(img > 220) = 100. This would combine the second and third step into one, but wouldn't save the mask in a new matrix.

The preceding example describes a very useful technique in its simplest form. This simple procedure has two serious flaws; one in the mask definition and one in the image masking process.

The flaw in the mask definition is the difficulty in pinpointing the specific ROI of our choice, using just the pixel values. Rarely can we isolate the region we need, by setting a specific threshold. Even in the example we saw (which is almost ideal for this simple technique), the mask derived from thresholding includes some pixels equal to 1 in other areas (for example, the frame of the picture). Also, the image masking result reveals that the area selected is a little smaller than it should be.

The flaw in the masking process is that the result is roughly patched up and just covers the area with brightness values that are closer to what would be expected. However, the ideal result would replace the bright area with something more complex than a patch of equal brightness values. This patch could be a part of an image that more closely resembles what has been destroyed by the flash.

In the rest of the chapter, we will be focusing on ways to refine the mask selection process, so that the resulting mask is more suitable to our needs. This will be accomplished using various morphological operations that will tweak our mask.