Tutorial and exercises
This practical applies morphology to grayscale images. The geometric idea remains the same, but the image is no longer treated only as object and background. It can be imagined as an intensity surface: bright regions have high values and dark regions have low values. In this context, dilation tends to take local maxima and erosion tends to take local minima.
We load the grayscale images that we will use during the practical session
plane = imread("Imagenes\airplane.tif");
cells = imread("Imagenes\bloodcells.tif");
cameraman = imread("Imagenes\cameraman.tif");
butterfly = imread("Imagenes\mariposa.jpg");
montage({plane,cells,cameraman,butterfly})
_media/figure_0.png)
Primary morphological operators
In grayscale images, dilation makes bright regions extend within the neighborhood defined by the structuring element. Erosion, on the other hand, favors low values and makes dark regions more present. The final effect depends on the size of the image structures: details smaller than the structuring element are the ones most easily modified.
Definition of the structuring element to be used
SE = strel("disk",5);
Reminder! Types of structuring elements: diamond, parameter - distance from the origin to the end of the diamond (1 for cross); disk, parameter - radius; line, parameters - length and angle; rectangle, parameters - length and height; square, parameter - side; nhood, shape defined by a matrix of 0s and 1s.
Dilation
In grayscale, dilation can be interpreted as a local maximum filter. Each pixel tends to take the highest value in its neighborhood, so bright regions grow and small dark details are reduced.
butterfly_dilate = imdilate(butterfly,SE);
montage({butterfly,butterfly_dilate})
_media/figure_1.png)
plane_dilate = imdilate(plane,SE);
montage({plane,plane_dilate})
_media/figure_2.png)
Erosion
Grayscale erosion is equivalent to looking at local minima inside the neighborhood. This visually expands dark regions and reduces small bright details. It is the dual operation of dilation.
butterfly_erode = imerode(butterfly,SE);
montage({butterfly,butterfly_erode})
_media/figure_3.png)
plane_erode = imerode(plane,SE);
montage({plane,plane_erode})
_media/figure_4.png)
Secondary operators
Opening and closing also have a clear interpretation in grayscale images. Opening removes or reduces small bright details because they do not survive the initial erosion. Closing acts in the dual way and tends to remove small dark details or narrow depressions. This makes it possible to separate structures according to their size and contrast with the surroundings.
Opening
plane_open = imopen(plane,SE);
montage({plane,plane_open})
_media/figure_5.png)
Closing
plane_close = imclose(plane,SE);
montage({plane,plane_close})
_media/figure_6.png)
Another example:
cells_open = imopen(cells,SE);
cells_close = imclose(cells,SE);
montage({cells,cells_open,cells_close})
_media/figure_7.png)
Comparison between opening and erosion, and between closing and dilation
montage({plane,plane_erode,plane_open})
_media/figure_8.png)
montage({plane,plane_dilate,plane_close})
_media/figure_9.png)
We test the effect on bright or dark elements by using a larger structuring element.
SE = strel("disk",10);
cells_open = imopen(cells,SE);
cells_close = imclose(cells,SE);
montage({cells,cells_open,cells_close})
_media/figure_10.png)
Morphological filtering
Morphological filtering is useful when the goal is to remove noise or small details without averaging the whole image. Unlike linear filters, it does not combine values with weights; it applies local minimum and maximum operations. This can preserve strong edges and main shapes better, provided that the structuring element is well chosen.
Morphological smoothing filters
cameraman_sal_pimienta = imread("Imagenes\cameraman_ruido_sal_pimienta.png");
cameraman_gaussiano = imread("Imagenes\cameraman_ruido_gaussiano.png");
montage({cameraman_gaussiano,cameraman_sal_pimienta})
_media/figure_11.png)
We define the structuring element most commonly used for this type of filter
SE1 = strel("diamond",1);
Remember! Morphological smoothing filter: Closing of the opening
cameraman_open1 = imopen(cameraman_sal_pimienta,SE1);
cameraman_close1 = imclose(cameraman_open1,SE1);
cameraman_open2 = imopen(cameraman_gaussiano,SE1);
cameraman_close2 = imclose(cameraman_open2,SE1);
montage({cameraman_sal_pimienta,cameraman_close1})
_media/figure_12.png)
montage({cameraman_gaussiano,cameraman_close2})
_media/figure_13.png)
Since there is still noise, we apply the alternating sequential filtering technique.
Alternating sequential filtering applies openings and closings with structuring elements of increasing size. The idea is to remove noise and small details at several scales, not only at one fixed size. It should be used carefully, because it can also simplify the image too much.
SE2 = strel("diamond",2);
cameraman_close1_open = imopen(cameraman_close1,SE2);
cameraman_close1_close = imclose(cameraman_close1_open,SE2);
montage({cameraman_sal_pimienta,cameraman_close1,cameraman_close1_close})
_media/figure_14.png)
Morphological enhancement filters or morphological gradient
The morphological gradient measures the difference between a dilated image and an eroded image. When there is a strong intensity transition inside the neighborhood, this difference is large. For this reason, the morphological gradient highlights contours and edges, but it does so from a morphological perspective, based on the shape and size of the structuring element.
We define the structuring element most commonly used in these cases
SE3 = strel("square",3);
First, the internal morphological gradient
plane_realce_i = plane - imerode(plane,SE3);
Then, the external morphological gradient
plane_realce_e = imdilate(plane,SE3) - plane;
And finally, the internal-external morphological gradient
The internal gradient highlights the inner side of the contour because it compares the image with its erosion. The external gradient highlights the outer side because it compares the dilation with the original image. The internal-external gradient combines both effects and produces a thicker edge.
plane_realce = imdilate(plane,SE3)-imerode(plane,SE3);
montage({plane,plane_realce_i,plane_realce_e,plane_realce})
_media/figure_15.png)
Another example
cells_realce_i = cells-imerode(cells,SE3);
cells_realce_e = imdilate(cells,SE3)-cells;
cells_realce = imdilate(cells,SE3)-imerode(cells,SE3);
montage({cells,cells_realce_i,cells_realce_e,cells_realce})
_media/figure_16.png)
The negative image is taken for better visualization
cells_realce_i_neg = 255 - cells_realce_i;
cells_realce_e_neg = 255 - cells_realce_e;
cells_realce_neg = 255 - cells_realce;
montage({cells,cells_realce_i_neg,cells_realce_e_neg,cells_realce_neg})
_media/figure_17.png)
Top-Hat and Bottom-Hat transforms
Top-Hat and Bottom-Hat transforms compare the original image with a simplified version obtained by opening or closing. Top-Hat highlights bright details that are smaller than the structuring element. Bottom-Hat highlights small dark details. These transformations are very useful when local structures must be detected on a slowly varying background.
cells = imread("Imagenes\cells_internet.jpg");
cells = rgb2gray(cells);
montage(cells)
_media/figure_18.png)
The Top-Hat transform is calculated
Top-Hat is computed by subtracting the opening from the original image. Since opening removes small bright details, the subtraction leaves precisely those details as the highlighted response.
SE = strel("disk",30);
cells_top_hat = imtophat(cells,SE);
montage({cells,cells_top_hat})
_media/figure_19.png)
The Bottom-Hat transform is calculated
Bottom-Hat is computed by comparing the closing with the original image. Since closing fills small dark details, the difference highlights these local dark elements.
cells_bot_hat = imbothat(cells,SE);
montage({cells,cells_bot_hat})
_media/figure_20.png)
With a clear application: binarization for the subsequent labeling of connected components
This example shows an important idea in computer vision: segmentation is often not applied directly to the original image. First, the relevant information is enhanced and variations that may confuse the threshold are reduced. Then binarization and connected-component labeling become more reliable.
cells_bin = imbinarize(cells);
cells_top_hat_bin = imbinarize(cells_top_hat);
cells_bot_hat_bin = imbinarize(cells_bot_hat);
montage({cells_bin,cells_top_hat_bin,cells_bot_hat_bin})
_media/figure_21.png)