File: opening_closing_hats.rst

package info (click to toggle)
opencv 2.4.9.1%2Bdfsg-1%2Bdeb8u1
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 126,800 kB
  • ctags: 62,729
  • sloc: xml: 509,055; cpp: 490,794; lisp: 23,208; python: 21,174; java: 19,317; ansic: 1,038; sh: 128; makefile: 72
file content (281 lines) | stat: -rw-r--r-- 8,361 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
.. _Morphology_2:

More Morphology Transformations
*********************************

Goal
=====

In this tutorial you will learn how to:

.. container:: enumeratevisibleitemswithsquare

   * Use the OpenCV function :morphology_ex:`morphologyEx <>` to apply Morphological Transformation such as:

     + Opening
     + Closing
     + Morphological Gradient
     + Top Hat
     + Black Hat

Theory
=======

.. note::
   The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.

In the previous tutorial we covered two basic Morphology operations:

.. container:: enumeratevisibleitemswithsquare

   * Erosion
   * Dilation.

Based on these two we can effectuate more sophisticated transformations to our images. Here we discuss briefly 05 operations offered by OpenCV:

Opening
---------

* It is obtained by the erosion of an image followed by a dilation.

  .. math::

     dst = open( src, element) = dilate( erode( src, element ) )

* Useful for removing small objects (it is assumed that the objects are bright on a dark foreground)

* 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.

  .. image:: images/Morphology_2_Tutorial_Theory_Opening.png
     :alt: Opening
     :align: center

Closing
---------

* It is obtained by the dilation of an image followed by an erosion.

  .. math::

     dst = close( src, element ) = erode( dilate( src, element ) )

* Useful to remove small holes (dark regions).

  .. image:: images/Morphology_2_Tutorial_Theory_Closing.png
     :alt: Closing example
     :align: center


Morphological Gradient
------------------------

* It is the difference between the dilation and the erosion of an image.

  .. math::

     dst = morph_{grad}( src, element ) = dilate( src, element ) - erode( src, element )

* It is useful for finding the outline of an object as can be seen below:

  .. image:: images/Morphology_2_Tutorial_Theory_Gradient.png
     :alt: Gradient
     :align: center


Top Hat
---------

* It is the difference between an input image and its opening.

  .. math::

     dst = tophat( src, element ) = src - open( src, element )

  .. image:: images/Morphology_2_Tutorial_Theory_TopHat.png
     :alt: Top Hat
     :align: center

Black Hat
----------

* It is the difference between the closing and its input image

  .. math::

     dst = blackhat( src, element ) = close( src, element ) - src

  .. image:: images/Morphology_2_Tutorial_Theory_BlackHat.png
     :alt: Black Hat
     :align: center

Code
======

This tutorial code's is shown lines below. You can also download it from `here <https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Morphology_2.cpp>`_

.. code-block:: cpp

   #include "opencv2/imgproc/imgproc.hpp"
   #include "opencv2/highgui/highgui.hpp"
   #include <stdlib.h>
   #include <stdio.h>

   using namespace cv;

   /// Global variables
   Mat src, dst;

   int morph_elem = 0;
   int morph_size = 0;
   int morph_operator = 0;
   int const max_operator = 4;
   int const max_elem = 2;
   int const max_kernel_size = 21;

   char* window_name = "Morphology Transformations Demo";

   /** Function Headers */
   void Morphology_Operations( int, void* );

   /** @function main */
   int main( int argc, char** argv )
   {
     /// Load an image
     src = imread( argv[1] );

     if( !src.data )
     { return -1; }

    /// Create window
    namedWindow( window_name, CV_WINDOW_AUTOSIZE );

    /// Create Trackbar to select Morphology operation
    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 );

    /// Create Trackbar to select kernel type
    createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
                    &morph_elem, max_elem,
                    Morphology_Operations );

    /// Create Trackbar to choose kernel size
    createTrackbar( "Kernel size:\n 2n +1", window_name,
                    &morph_size, max_kernel_size,
                    Morphology_Operations );

    /// Default start
    Morphology_Operations( 0, 0 );

    waitKey(0);
    return 0;
    }

    /**
     * @function Morphology_Operations
     */
   void Morphology_Operations( int, void* )
   {
     // Since MORPH_X : 2,3,4,5 and 6
     int operation = morph_operator + 2;

     Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );

     /// Apply the specified morphology operation
     morphologyEx( src, dst, operation, element );
     imshow( window_name, dst );
     }


Explanation
=============

#. Let's check the general structure of the program:

   * Load an image

   * Create a window to display results of the Morphological operations

   * Create 03 Trackbars for the user to enter parameters:

     * The first trackbar **"Operator"** returns the kind of morphology operation to use (**morph_operator**).

       .. code-block:: cpp

          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 );



     * The second trackbar **"Element"** returns **morph_elem**, which indicates what kind of structure our kernel is:

       .. code-block:: cpp

          createTrackbar( "Element:\n 0: Rect - 1: Cross - 2: Ellipse", window_name,
                          &morph_elem, max_elem,
                          Morphology_Operations );

     * The final trackbar **"Kernel Size"** returns the size of the kernel to be used (**morph_size**)

       .. code-block:: cpp

          createTrackbar( "Kernel size:\n 2n +1", window_name,
                          &morph_size, max_kernel_size,
                          Morphology_Operations );


   * 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.

     .. code-block:: cpp

        /**
         * @function Morphology_Operations
         */
       void Morphology_Operations( int, void* )
       {
         // Since MORPH_X : 2,3,4,5 and 6
         int operation = morph_operator + 2;

         Mat element = getStructuringElement( morph_elem, Size( 2*morph_size + 1, 2*morph_size+1 ), Point( morph_size, morph_size ) );

         /// Apply the specified morphology operation
         morphologyEx( src, dst, operation, element );
         imshow( window_name, dst );
        }


     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):

     * **src** : Source (input) image
     * **dst**: Output image
     * **operation**: The kind of morphology transformation to be performed. Note that we have 5 alternatives:

       + *Opening*: MORPH_OPEN : 2
       + *Closing*: MORPH_CLOSE: 3
       + *Gradient*: MORPH_GRADIENT: 4
       + *Top Hat*: MORPH_TOPHAT: 5
       + *Black Hat*: MORPH_BLACKHAT: 6

       As you can see the values range from <2-6>, that is why we add (+2) to the values entered by the Trackbar:

       ..  code-block:: cpp

           int operation = morph_operator + 2;

     * **element**: The kernel to be used. We use the function :get_structuring_element:`getStructuringElement <>` to define our own structure.



Results
========

* 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.png**:

  .. image:: images/Morphology_2_Tutorial_Original_Image.jpg
     :alt: Morphology 2: Original image
     :align: center

* 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.

  .. image:: images/Morphology_2_Tutorial_Cover.jpg
     :alt: Morphology 2: Result sample
     :align: center