1
Smoothing Images {#tutorial_gausian_median_blur_bilateral_filter}
7
In this tutorial you will learn how to apply diverse linear filters to smooth images using OpenCV
11
- @ref cv::GaussianBlur
13
- @ref cv::bilateralFilter
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
22
- *Smoothing*, also called *blurring*, is a simple and frequently used image processing
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$) :
30
\f[g(i,j) = \sum_{k,l} f(i+k, j+l) h(k,l)\f]
32
\f$h(k,l)\f$ is called the *kernel*, which is nothing more than the coefficients of the filter.
34
It helps to visualize a *filter* as a window of coefficients sliding across the image.
36
- There are many kind of filters, here we will mention the most used:
38
### Normalized Box Filter
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:
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 \\
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?
59
![](images/Smoothing_Tutorial_theory_gaussian_0.jpg)
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.
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$)
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
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)
92
- **What does this program do?**
94
- Applies 4 different kinds of filters (explained in Theory) and show the filtered images
96
- **Downloadable code**: Click
97
[here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgProc/Smoothing.cpp)
100
#include "opencv2/imgproc.hpp"
101
#include "opencv2/highgui.hpp"
107
int DELAY_CAPTION = 1500;
108
int DELAY_BLUR = 100;
109
int MAX_KERNEL_LENGTH = 31;
112
char window_name[] = "Filter Demo 1";
115
int display_caption( char* caption );
116
int display_dst( int delay );
121
int main( int argc, char** argv )
123
namedWindow( window_name, WINDOW_AUTOSIZE );
125
/// Load the source image
126
src = imread( "../images/lena.jpg", 1 );
128
if( display_caption( "Original Image" ) != 0 ) { return 0; }
131
if( display_dst( DELAY_CAPTION ) != 0 ) { return 0; }
133
/// Applying Homogeneous blur
134
if( display_caption( "Homogeneous Blur" ) != 0 ) { return 0; }
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; } }
140
/// Applying Gaussian blur
141
if( display_caption( "Gaussian Blur" ) != 0 ) { return 0; }
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; } }
147
/// Applying Median blur
148
if( display_caption( "Median Blur" ) != 0 ) { return 0; }
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; } }
154
/// Applying Bilateral Filter
155
if( display_caption( "Bilateral Blur" ) != 0 ) { return 0; }
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; } }
161
/// Wait until user press a key
162
display_caption( "End: Press a key!" );
168
int display_caption( char* caption )
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) );
175
imshow( window_name, dst );
176
int c = waitKey( DELAY_CAPTION );
177
if( c >= 0 ) { return -1; }
181
int display_dst( int delay )
183
imshow( window_name, dst );
184
int c = waitKey ( delay );
185
if( c >= 0 ) { return -1; }
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:**
197
OpenCV offers the function @ref cv::blur to perform smoothing with this filter.
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; } }
203
We specify 4 arguments (more details, check the Reference):
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
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.
213
-# **Gaussian Filter:**
215
It is performed by the function @ref cv::GaussianBlur :
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; } }
221
Here we use 4 arguments (more details, check the OpenCV reference):
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.
233
-# **Median Filter:**
235
This filter is provided by the @ref cv::medianBlur function:
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; } }
241
We use three arguments:
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.
247
-# **Bilateral Filter**
249
Provided by OpenCV function @ref cv::bilateralFilter
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; } }
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)
266
- The code opens an image (in this case *lena.jpg*) and display it under the effects of the 4
268
- Here is a snapshot of the image smoothed using *medianBlur*:
270
![](images/Smoothing_Tutorial_Result_Median_Filter.jpg)