3 More Morphology Transformations
4 *********************************
9 In this tutorial you will learn how to:
11 * Use the OpenCV function :morphology_ex:`morphologyEx <>` to apply Morphological Transformation such as:
15 * Morphological Gradient
23 The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
25 In the previous tutorial we covered two basic Morphology operations:
31 Based on these two we can effectuate more sophisticated transformations to our images. Here we discuss briefly 05 operations offered by OpenCV:
36 * It is obtained by the erosion of an image followed by a dilation.
40 dst = open( src, element) = dilate( erode( src, element ) )
42 * Useful for removing small objects (it is assumed that the objects are bright on a dark foreground)
44 * For instance, check out the example below. The image at the left is the original and the image at the right is the result after applying the opening transformation. We can observe that the small spaces in the corners of the letter tend to dissapear.
46 .. image:: images/Morphology_2_Tutorial_Theory_Opening.png
54 * It is obtained by the dilation of an image followed by an erosion.
58 dst = close( src, element ) = erode( dilate( src, element ) )
60 * Useful to remove small holes (dark regions).
62 .. image:: images/Morphology_2_Tutorial_Theory_Closing.png
68 Morphological Gradient
69 ------------------------
71 * It is the difference between the dilation and the erosion of an image.
75 dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )
77 * It is useful for finding the outline of an object as can be seen below:
79 .. image:: images/Morphology_2_Tutorial_Theory_Gradient.png
88 * It is the difference between an input image and its opening.
92 dst = tophat( src, element ) = src - open( src, element )
94 .. image:: images/Morphology_2_Tutorial_Theory_TopHat.png
102 * It is the difference between the closing and its input image
106 dst = blackhat( src, element ) = close( src, element ) - src
108 .. image:: images/Morphology_2_Tutorial_Theory_BlackHat.png
116 This tutorial code's is shown lines below. You can also download it from `here <https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp>`_
120 #include "opencv2/imgproc/imgproc.hpp"
121 #include "opencv2/highgui/highgui.hpp"
132 int morph_operator = 0;
133 int const max_operator = 4;
134 int const max_elem = 2;
135 int const max_kernel_size = 21;
137 char* window_name = "Morphology Transformations Demo";
139 /** Function Headers */
140 void Morphology_Operations( int, void* );
142 /** @function main */
143 int main( int argc, char** argv )
146 src = imread( argv[1] );
152 namedWindow( window_name, CV_WINDOW_AUTOSIZE );
154 /// Create Trackbar to select Morphology operation
155 createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat", window_name, &morph_operator, max_operator, Morphology_Operations );
157 /// Create Trackbar to select kernel type
158 createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
159 &morph_elem, max_elem,
160 Morphology_Operations );
162 /// Create Trackbar to choose kernel size
163 createTrackbar( "Kernel size:\n 2n +1", window_name,
164 &morph_size, max_kernel_size,
165 Morphology_Operations );
168 Morphology_Operations( 0, 0 );
175 * @function Morphology_Operations
177 void Morphology_Operations( int, void* )
179 // Since MORPH_X : 2,3,4,5 and 6
180 int operation = morph_operator + 2;
182 Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
184 /// Apply the specified morphology operation
185 morphologyEx( src, dst, operation, element );
186 imshow( window_name, dst );
193 #. Let's check the general structure of the program:
197 * Create a window to display results of the Morphological operations
199 * Create 03 Trackbars for the user to enter parameters:
201 * The first trackbar **"Operator"** returns the kind of morphology operation to use (**morph_operator**).
205 createTrackbar("Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat",
206 window_name, &morph_operator, max_operator,
207 Morphology_Operations );
211 * The second trackbar **"Element"** returns **morph_elem**, which indicates what kind of structure our kernel is:
215 createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
216 &morph_elem, max_elem,
217 Morphology_Operations );
219 * The final trackbar **"Kernel Size"** returns the size of the kernel to be used (**morph_size**)
223 createTrackbar( "Kernel size:\n 2n +1", window_name,
224 &morph_size, max_kernel_size,
225 Morphology_Operations );
228 * Every time we move any slider, the user's function **Morphology_Operations** will be called to effectuate a new morphology operation and it will update the output image based on the current trackbar values.
233 * @function Morphology_Operations
235 void Morphology_Operations( int, void* )
237 // Since MORPH_X : 2,3,4,5 and 6
238 int operation = morph_operator + 2;
240 Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );
242 /// Apply the specified morphology operation
243 morphologyEx( src, dst, operation, element );
244 imshow( window_name, dst );
248 We can observe that the key function to perform the morphology transformations is :morphology_ex:`morphologyEx <>`. In this example we use four arguments (leaving the rest as defaults):
250 * **src** : Source (input) image
251 * **dst**: Output image
252 * **operation**: The kind of morphology transformation to be performed. Note that we have 5 alternatives:
254 * *Opening*: MORPH_OPEN : 2
255 * *Closing*: MORPH_CLOSE: 3
256 * *Gradient*: MORPH_GRADIENT: 4
257 * *Top Hat*: MORPH_TOPHAT: 5
258 * *Black Hat*: MORPH_BLACKHAT: 6
260 As you can see the values range from <2-6>, that is why we add (+2) to the values entered by the Trackbar:
264 int operation = morph_operator + 2;
266 * **element**: The kernel to be used. We use the function :get_structuring_element:`getStructuringElement <>` to define our own structure.
273 * After compiling the code above we can execute it giving an image path as an argument. For this tutorial we use as input the image: **baboon.jpg**:
275 .. image:: images/Morphology_2_Tutorial_Original_Image.jpg
277 :alt: Morphology 2: Original image
280 * And here are two snapshots of the display window. The first picture shows the output after using the operator **Opening** with a cross kernel. The second picture (right side, shows the result of using a **Blackhat** operator with an ellipse kernel.
282 .. image:: images/Morphology_2_Tutorial_Cover.png
284 :alt: Morphology 2: Result sample