~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.markdown

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Smoothing Images {#tutorial_gausian_median_blur_bilateral_filter}
 
2
================
 
3
 
 
4
Goal
 
5
----
 
6
 
 
7
In this tutorial you will learn how to apply diverse linear filters to smooth images using OpenCV
 
8
functions such as:
 
9
 
 
10
-   @ref cv::blur
 
11
-   @ref cv::GaussianBlur
 
12
-   @ref cv::medianBlur
 
13
-   @ref cv::bilateralFilter
 
14
 
 
15
Theory
 
16
------
 
17
 
 
18
@note The explanation below belongs to the book [Computer Vision: Algorithms and
 
19
Applications](http://szeliski.org/Book/) by Richard Szeliski and to *LearningOpenCV* .. container::
 
20
enumeratevisibleitemswithsquare
 
21
 
 
22
-   *Smoothing*, also called *blurring*, is a simple and frequently used image processing
 
23
    operation.
 
24
-   There are many reasons for smoothing. In this tutorial we will focus on smoothing in order to
 
25
    reduce noise (other uses will be seen in the following tutorials).
 
26
-   To perform a smoothing operation we will apply a *filter* to our image. The most common type
 
27
    of filters are *linear*, in which an output pixel's value (i.e. \f$g(i,j)\f$) is determined as a
 
28
    weighted sum of input pixel values (i.e. \f$f(i+k,j+l)\f$) :
 
29
 
 
30
    \f[g(i,j) = \sum_{k,l} f(i+k, j+l) h(k,l)\f]
 
31
 
 
32
    \f$h(k,l)\f$ is called the *kernel*, which is nothing more than the coefficients of the filter.
 
33
 
 
34
    It helps to visualize a *filter* as a window of coefficients sliding across the image.
 
35
 
 
36
-   There are many kind of filters, here we will mention the most used:
 
37
 
 
38
### Normalized Box Filter
 
39
 
 
40
-   This filter is the simplest of all! Each output pixel is the *mean* of its kernel neighbors (
 
41
    all of them contribute with equal weights)
 
42
-   The kernel is below:
 
43
 
 
44
    \f[K = \dfrac{1}{K_{width} \cdot K_{height}} \begin{bmatrix}
 
45
        1 & 1 & 1 & ... & 1 \\
 
46
        1 & 1 & 1 & ... & 1 \\
 
47
        . & . & . & ... & 1 \\
 
48
        . & . & . & ... & 1 \\
 
49
        1 & 1 & 1 & ... & 1
 
50
       \end{bmatrix}\f]
 
51
 
 
52
### Gaussian Filter
 
53
 
 
54
-   Probably the most useful filter (although not the fastest). Gaussian filtering is done by
 
55
    convolving each point in the input array with a *Gaussian kernel* and then summing them all to
 
56
    produce the output array.
 
57
-   Just to make the picture clearer, remember how a 1D Gaussian kernel look like?
 
58
 
 
59
    ![](images/Smoothing_Tutorial_theory_gaussian_0.jpg)
 
60
 
 
61
    Assuming that an image is 1D, you can notice that the pixel located in the middle would have the
 
62
    biggest weight. The weight of its neighbors decreases as the spatial distance between them and
 
63
    the center pixel increases.
 
64
 
 
65
    @note
 
66
    Remember that a 2D Gaussian can be represented as :
 
67
    \f[G_{0}(x, y) = A  e^{ \dfrac{ -(x - \mu_{x})^{2} }{ 2\sigma^{2}_{x} } +  \dfrac{ -(y - \mu_{y})^{2} }{ 2\sigma^{2}_{y} } }\f]
 
68
    where \f$\mu\f$ is the mean (the peak) and \f$\sigma\f$ represents the variance (per each of the
 
69
    variables \f$x\f$ and \f$y\f$)
 
70
 
 
71
### Median Filter
 
72
 
 
73
The median filter run through each element of the signal (in this case the image) and replace each
 
74
pixel with the **median** of its neighboring pixels (located in a square neighborhood around the
 
75
evaluated pixel).
 
76
 
 
77
### Bilateral Filter
 
78
 
 
79
-   So far, we have explained some filters which main goal is to *smooth* an input image. However,
 
80
    sometimes the filters do not only dissolve the noise, but also smooth away the *edges*. To avoid
 
81
    this (at certain extent at least), we can use a bilateral filter.
 
82
-   In an analogous way as the Gaussian filter, the bilateral filter also considers the neighboring
 
83
    pixels with weights assigned to each of them. These weights have two components, the first of
 
84
    which is the same weighting used by the Gaussian filter. The second component takes into account
 
85
    the difference in intensity between the neighboring pixels and the evaluated one.
 
86
-   For a more detailed explanation you can check [this
 
87
    link](http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/MANDUCHI1/Bilateral_Filtering.html)
 
88
 
 
89
Code
 
90
----
 
91
 
 
92
-   **What does this program do?**
 
93
    -   Loads an image
 
94
    -   Applies 4 different kinds of filters (explained in Theory) and show the filtered images
 
95
        sequentially
 
96
-   **Downloadable code**: Click
 
97
    [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp)
 
98
-   **Code at glance:**
 
99
@code{.cpp}
 
100
#include "opencv2/imgproc.hpp"
 
101
#include "opencv2/highgui.hpp"
 
102
 
 
103
using namespace std;
 
104
using namespace cv;
 
105
 
 
106
/// Global Variables
 
107
int DELAY_CAPTION = 1500;
 
108
int DELAY_BLUR = 100;
 
109
int MAX_KERNEL_LENGTH = 31;
 
110
 
 
111
Mat src; Mat dst;
 
112
char window_name[] = "Filter Demo 1";
 
113
 
 
114
/// Function headers
 
115
int display_caption( char* caption );
 
116
int display_dst( int delay );
 
117
 
 
118
/*
 
119
 * function main
 
120
 */
 
121
 int main( int argc, char** argv )
 
122
 {
 
123
   namedWindow( window_name, WINDOW_AUTOSIZE );
 
124
 
 
125
   /// Load the source image
 
126
   src = imread( "../images/lena.jpg", 1 );
 
127
 
 
128
   if( display_caption( "Original Image" ) != 0 ) { return 0; }
 
129
 
 
130
   dst = src.clone();
 
131
   if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
 
132
 
 
133
   /// Applying Homogeneous blur
 
134
   if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
 
135
 
 
136
   for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
137
       { blur( src, dst, Size( i, i ), Point(-1,-1) );
 
138
         if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
139
 
 
140
    /// Applying Gaussian blur
 
141
    if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
 
142
 
 
143
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
144
        { GaussianBlur( src, dst, Size( i, i ), 0, 0 );
 
145
          if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
146
 
 
147
     /// Applying Median blur
 
148
 if( display_caption( "Median Blur" ) != 0 ) { return 0; }
 
149
 
 
150
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
151
         { medianBlur ( src, dst, i );
 
152
           if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
153
 
 
154
 /// Applying Bilateral Filter
 
155
 if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
 
156
 
 
157
 for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
158
         { bilateralFilter ( src, dst, i, i*2, i/2 );
 
159
           if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
160
 
 
161
 /// Wait until user press a key
 
162
 display_caption( "End: Press a key!" );
 
163
 
 
164
 waitKey(0);
 
165
 return 0;
 
166
 }
 
167
 
 
168
 int display_caption( char* caption )
 
169
 {
 
170
   dst = Mat::zeros( src.size(), src.type() );
 
171
   putText( dst, caption,
 
172
            Point( src.cols/4, src.rows/2),
 
173
            FONT_HERSHEY_COMPLEX, 1, Scalar(255, 255, 255) );
 
174
 
 
175
   imshow( window_name, dst );
 
176
   int c = waitKey( DELAY_CAPTION );
 
177
   if( c >= 0 ) { return -1; }
 
178
   return 0;
 
179
  }
 
180
 
 
181
  int display_dst( int delay )
 
182
  {
 
183
    imshow( window_name, dst );
 
184
    int c = waitKey ( delay );
 
185
    if( c >= 0 ) { return -1; }
 
186
    return 0;
 
187
  }
 
188
@endcode
 
189
 
 
190
Explanation
 
191
-----------
 
192
 
 
193
-#  Let's check the OpenCV functions that involve only the smoothing procedure, since the rest is
 
194
    already known by now.
 
195
-#  **Normalized Block Filter:**
 
196
 
 
197
    OpenCV offers the function @ref cv::blur to perform smoothing with this filter.
 
198
    @code{.cpp}
 
199
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
200
        { blur( src, dst, Size( i, i ), Point(-1,-1) );
 
201
          if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
202
    @endcode
 
203
    We specify 4 arguments (more details, check the Reference):
 
204
 
 
205
    -   *src*: Source image
 
206
    -   *dst*: Destination image
 
207
    -   *Size( w,h )*: Defines the size of the kernel to be used ( of width *w* pixels and height
 
208
        *h* pixels)
 
209
    -   *Point(-1, -1)*: Indicates where the anchor point (the pixel evaluated) is located with
 
210
        respect to the neighborhood. If there is a negative value, then the center of the kernel is
 
211
        considered the anchor point.
 
212
 
 
213
-#  **Gaussian Filter:**
 
214
 
 
215
    It is performed by the function @ref cv::GaussianBlur :
 
216
    @code{.cpp}
 
217
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
218
        { GaussianBlur( src, dst, Size( i, i ), 0, 0 );
 
219
          if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
220
    @endcode
 
221
    Here we use 4 arguments (more details, check the OpenCV reference):
 
222
 
 
223
    -   *src*: Source image
 
224
    -   *dst*: Destination image
 
225
    -   *Size(w, h)*: The size of the kernel to be used (the neighbors to be considered). \f$w\f$ and
 
226
        \f$h\f$ have to be odd and positive numbers otherwise thi size will be calculated using the
 
227
        \f$\sigma_{x}\f$ and \f$\sigma_{y}\f$ arguments.
 
228
    -   \f$\sigma_{x}\f$: The standard deviation in x. Writing \f$0\f$ implies that \f$\sigma_{x}\f$ is
 
229
        calculated using kernel size.
 
230
    -   \f$\sigma_{y}\f$: The standard deviation in y. Writing \f$0\f$ implies that \f$\sigma_{y}\f$ is
 
231
        calculated using kernel size.
 
232
 
 
233
-#  **Median Filter:**
 
234
 
 
235
    This filter is provided by the @ref cv::medianBlur function:
 
236
    @code{.cpp}
 
237
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
238
        { medianBlur ( src, dst, i );
 
239
          if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
240
    @endcode
 
241
    We use three arguments:
 
242
 
 
243
    -   *src*: Source image
 
244
    -   *dst*: Destination image, must be the same type as *src*
 
245
    -   *i*: Size of the kernel (only one because we use a square window). Must be odd.
 
246
 
 
247
-#  **Bilateral Filter**
 
248
 
 
249
    Provided by OpenCV function @ref cv::bilateralFilter
 
250
    @code{.cpp}
 
251
    for ( int i = 1; i < MAX_KERNEL_LENGTH; i = i + 2 )
 
252
        { bilateralFilter ( src, dst, i, i*2, i/2 );
 
253
          if( display_dst( DELAY_BLUR ) != 0 ) { return 0; } }
 
254
    @endcode
 
255
    We use 5 arguments:
 
256
 
 
257
    -   *src*: Source image
 
258
    -   *dst*: Destination image
 
259
    -   *d*: The diameter of each pixel neighborhood.
 
260
    -   \f$\sigma_{Color}\f$: Standard deviation in the color space.
 
261
    -   \f$\sigma_{Space}\f$: Standard deviation in the coordinate space (in pixel terms)
 
262
 
 
263
Results
 
264
-------
 
265
 
 
266
-   The code opens an image (in this case *lena.jpg*) and display it under the effects of the 4
 
267
    filters explained.
 
268
-   Here is a snapshot of the image smoothed using *medianBlur*:
 
269
 
 
270
    ![](images/Smoothing_Tutorial_Result_Median_Filter.jpg)