@prev_tutorial{tutorial_gausian_median_blur_bilateral_filter} @next_tutorial{tutorial_opening_closing_hats}
| | | | -: | :- | | Original author | Ana Huamán | | Compatibility | OpenCV >= 3.0 |
In this tutorial you will learn how to:
@note The explanation below belongs to the book Learning OpenCV by Bradski and Kaehler.
We will explain dilation and erosion briefly, using the following image as an example:
The dilatation operation is: \f$\texttt{dst} (x,y) = \max _{(x',y'): \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f$
Take the above image as an example. Applying dilation we can get:
The bright area of the letter dilates around the black regions of the background.
Analagously to the example for dilation, we can apply the erosion operator to the original image (shown above). You can see in the result below that the bright areas of the image get thinner, whereas the dark zones gets bigger.
@add_toggle_cpp This tutorial's code is shown below. You can also download it here @include samples/cpp/tutorial_code/ImgProc/Morphology_1.cpp @end_toggle
@add_toggle_java This tutorial's code is shown below. You can also download it here @include samples/java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java @end_toggle
@add_toggle_python This tutorial's code is shown below. You can also download it here @include samples/python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py @end_toggle
@add_toggle_cpp Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in previous sections). Let's check the general structure of the C++ program:
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp main
-# Load an image (can be BGR or grayscale) -# Create two windows (one for dilation output, the other for erosion) -# Create a set of two Trackbars for each operation:
- The first trackbar "Element" returns either **erosion_elem** or **dilation_elem**
- The second trackbar "Kernel size" return **erosion_size** or **dilation_size** for the
corresponding operation.
-# Call once erosion and dilation to show the initial image.
Every time we move any slider, the user's function Erosion or Dilation will be called and it will update the output image based on the current trackbar values.
Let's analyze these two functions:
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp erosion
The function that performs the erosion operation is @ref cv::erode . As we can see, it receives three arguments:
element: This is the kernel we will use to perform the operation. If we do not
specify, the default is a simple 3x3
matrix. Otherwise, we can specify its
shape. For this, we need to use the function cv::getStructuringElement :
@snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp kernel
We can choose any of three shapes for our kernel:
Then, we just have to specify the size of our kernel and the anchor point. If not specified, it is assumed to be in the center.
That is all. We are ready to perform the erosion of our image.
The code is below. As you can see, it is completely similar to the snippet of code for erosion. Here we also have the option of defining our kernel, its anchor point and the size of the operator to be used. @snippet cpp/tutorial_code/ImgProc/Morphology_1.cpp dilation @end_toggle
@add_toggle_java Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in previous sections). Let's check however the general structure of the java class. There are 4 main parts in the java class:
addComponentsToPane
method, which fills out the windowupdate
method, which determines what happens when the user changes any valuemain
method, which is the entry point of the programIn this tutorial we will focus on the addComponentsToPane
and update
methods. However, for completion the
steps followed in the constructor are:
-# Load an image (can be BGR or grayscale)
-# Create a window
-# Add various control components with addComponentsToPane
-# show the window
The components were added by the following method:
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java components
In short we
-# create a panel for the sliders -# create a combo box for the element types -# create a slider for the kernel size -# create a combo box for the morphology function to use (erosion or dilation)
The action and state changed listeners added call at the end the update
method which updates
the image based on the current slider values. So every time we move any slider, the update
method is triggered.
To update the image we used the following implementation:
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java update
In other words we
-# get the structuring element the user chose
-# execute the erosion or dilation function based on doErosion
-# reload the image with the morphology applied
-# repaint the frame
Let's analyze the erode
and dilate
methods:
@snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java erosion
The function that performs the erosion operation is @ref cv::erode . As we can see, it receives three arguments:
element: This is the kernel we will use to perform the operation. For specifying the shape, we need to use the function cv::getStructuringElement : @snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java kernel
We can choose any of three shapes for our kernel:
Together with the shape we specify the size of our kernel and the anchor point. If the anchor point is not specified, it is assumed to be in the center.
That is all. We are ready to perform the erosion of our image.
The code is below. As you can see, it is completely similar to the snippet of code for erosion. Here we also have the option of defining our kernel, its anchor point and the size of the operator to be used. @snippet java/tutorial_code/ImgProc/erosion_dilatation/MorphologyDemo1.java dilation @end_toggle
@add_toggle_python Most of the material shown here is trivial (if you have any doubt, please refer to the tutorials in previous sections). Let's check the general structure of the python script:
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py main
-# Load an image (can be BGR or grayscale) -# Create two windows (one for erosion output, the other for dilation) with a set of trackbars each
- The first trackbar "Element" returns the value for the morphological type that will be mapped
(1 = rectangle, 2 = cross, 3 = ellipse)
- The second trackbar "Kernel size" returns the size of the element for the
corresponding operation
-# Call once erosion and dilation to show the initial image
Every time we move any slider, the user's function erosion or dilation will be called and it will update the output image based on the current trackbar values.
Let's analyze these two functions:
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py erosion
The function that performs the erosion operation is @ref cv::erode . As we can see, it receives two arguments and returns the processed image:
element: The kernel we will use to perform the operation. We can specify its shape by using the function cv::getStructuringElement : @snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py kernel
We can choose any of three shapes for our kernel:
Then, we just have to specify the size of our kernel and the anchor point. If the anchor point not specified, it is assumed to be in the center.
That is all. We are ready to perform the erosion of our image.
The code is below. As you can see, it is completely similar to the snippet of code for erosion. Here we also have the option of defining our kernel, its anchor point and the size of the operator to be used.
@snippet python/tutorial_code/imgProc/erosion_dilatation/morphology_1.py dilation @end_toggle
@note Additionally, there are further parameters that allow you to perform multiple erosions/dilations (iterations) at once and also set the border type and value. However, We haven't used those in this simple tutorial. You can check out the reference for more details.
Compile the code above and execute it (or run the script if using python) with an image as argument. If you do not provide an image as argument the default sample image (LinuxLogo.jpg) will be used.
For instance, using this image:
We get the results below. Varying the indices in the Trackbars give different output images, naturally. Try them out! You can even try to add a third Trackbar to control the number of iterations.
(depending on the programming language the output might vary a little or be only 1 window)