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

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/doc/tutorials/imgproc/imgtrans/filter_2d/filter_2d.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
Making your own linear filters! {#tutorial_filter_2d}
 
2
===============================
 
3
 
 
4
Goal
 
5
----
 
6
 
 
7
In this tutorial you will learn how to:
 
8
 
 
9
-   Use the OpenCV function @ref cv::filter2D to create your own linear filters.
 
10
 
 
11
Theory
 
12
------
 
13
 
 
14
@note The explanation below belongs to the book **Learning OpenCV** by Bradski and Kaehler.
 
15
 
 
16
### Convolution
 
17
 
 
18
In a very general sense, convolution is an operation between every part of an image and an operator
 
19
(kernel).
 
20
 
 
21
### What is a kernel?
 
22
 
 
23
A kernel is essentially a fixed size array of numerical coefficeints along with an *anchor point* in
 
24
that array, which is tipically located at the center.
 
25
 
 
26
![](images/filter_2d_tutorial_kernel_theory.png)
 
27
 
 
28
### How does convolution with a kernel work?
 
29
 
 
30
Assume you want to know the resulting value of a particular location in the image. The value of the
 
31
convolution is calculated in the following way:
 
32
 
 
33
-#  Place the kernel anchor on top of a determined pixel, with the rest of the kernel overlaying the
 
34
    corresponding local pixels in the image.
 
35
-#  Multiply the kernel coefficients by the corresponding image pixel values and sum the result.
 
36
-#  Place the result to the location of the *anchor* in the input image.
 
37
-#  Repeat the process for all pixels by scanning the kernel over the entire image.
 
38
 
 
39
Expressing the procedure above in the form of an equation we would have:
 
40
 
 
41
\f[H(x,y) = \sum_{i=0}^{M_{i} - 1} \sum_{j=0}^{M_{j}-1} I(x+i - a_{i}, y + j - a_{j})K(i,j)\f]
 
42
 
 
43
Fortunately, OpenCV provides you with the function @ref cv::filter2D so you do not have to code all
 
44
these operations.
 
45
 
 
46
Code
 
47
----
 
48
 
 
49
-#  **What does this program do?**
 
50
    -   Loads an image
 
51
    -   Performs a *normalized box filter*. For instance, for a kernel of size \f$size = 3\f$, the
 
52
        kernel would be:
 
53
 
 
54
        \f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix}
 
55
        1 & 1 & 1  \\
 
56
        1 & 1 & 1  \\
 
57
        1 & 1 & 1
 
58
        \end{bmatrix}\f]
 
59
 
 
60
        The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11.
 
61
 
 
62
    -   The filter output (with each kernel) will be shown during 500 milliseconds
 
63
 
 
64
-#  The tutorial code's is shown lines below. You can also download it from
 
65
    [here](https://github.com/Itseez/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp)
 
66
@code{.cpp}
 
67
#include "opencv2/imgproc.hpp"
 
68
#include "opencv2/highgui.hpp"
 
69
#include <stdlib.h>
 
70
#include <stdio.h>
 
71
 
 
72
using namespace cv;
 
73
 
 
74
/* @function main */
 
75
int main ( int argc, char** argv )
 
76
{
 
77
  /// Declare variables
 
78
  Mat src, dst;
 
79
 
 
80
  Mat kernel;
 
81
  Point anchor;
 
82
  double delta;
 
83
  int ddepth;
 
84
  int kernel_size;
 
85
  char* window_name = "filter2D Demo";
 
86
 
 
87
  int c;
 
88
 
 
89
  /// Load an image
 
90
  src = imread( argv[1] );
 
91
 
 
92
  if( !src.data )
 
93
  { return -1; }
 
94
 
 
95
  /// Create window
 
96
  namedWindow( window_name, WINDOW_AUTOSIZE );
 
97
 
 
98
  /// Initialize arguments for the filter
 
99
  anchor = Point( -1, -1 );
 
100
  delta = 0;
 
101
  ddepth = -1;
 
102
 
 
103
  /// Loop - Will filter the image with different kernel sizes each 0.5 seconds
 
104
  int ind = 0;
 
105
  while( true )
 
106
    {
 
107
      c = waitKey(500);
 
108
      /// Press 'ESC' to exit the program
 
109
      if( (char)c == 27 )
 
110
        { break; }
 
111
 
 
112
      /// Update kernel size for a normalized box filter
 
113
      kernel_size = 3 + 2*( ind%5 );
 
114
      kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
 
115
 
 
116
      /// Apply filter
 
117
      filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
 
118
      imshow( window_name, dst );
 
119
      ind++;
 
120
    }
 
121
 
 
122
  return 0;
 
123
}
 
124
@endcode
 
125
Explanation
 
126
-----------
 
127
 
 
128
-#  Load an image
 
129
    @code{.cpp}
 
130
    src = imread( argv[1] );
 
131
 
 
132
    if( !src.data )
 
133
      { return -1; }
 
134
    @endcode
 
135
-#  Create a window to display the result
 
136
    @code{.cpp}
 
137
    namedWindow( window_name, WINDOW_AUTOSIZE );
 
138
    @endcode
 
139
-#  Initialize the arguments for the linear filter
 
140
    @code{.cpp}
 
141
    anchor = Point( -1, -1 );
 
142
    delta = 0;
 
143
    ddepth = -1;
 
144
    @endcode
 
145
-#  Perform an infinite loop updating the kernel size and applying our linear filter to the input
 
146
    image. Let's analyze that more in detail:
 
147
-#  First we define the kernel our filter is going to use. Here it is:
 
148
    @code{.cpp}
 
149
    kernel_size = 3 + 2*( ind%5 );
 
150
    kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
 
151
    @endcode
 
152
    The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$. The second
 
153
    line actually builds the kernel by setting its value to a matrix filled with \f$1's\f$ and
 
154
    normalizing it by dividing it between the number of elements.
 
155
 
 
156
-#  After setting the kernel, we can generate the filter by using the function @ref cv::filter2D :
 
157
    @code{.cpp}
 
158
    filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
 
159
    @endcode
 
160
    The arguments denote:
 
161
 
 
162
    -#  *src*: Source image
 
163
    -#  *dst*: Destination image
 
164
    -#  *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
 
165
        the same as the source.
 
166
    -#  *kernel*: The kernel to be scanned through the image
 
167
    -#  *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
 
168
        indicates the center by default.
 
169
    -#  *delta*: A value to be added to each pixel during the convolution. By default it is \f$0\f$
 
170
    -#  *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
 
171
 
 
172
-#  Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be
 
173
    updated in the range indicated.
 
174
 
 
175
Results
 
176
-------
 
177
 
 
178
-#  After compiling the code above, you can execute it giving as argument the path of an image. The
 
179
    result should be a window that shows an image blurred by a normalized filter. Each 0.5 seconds
 
180
    the kernel size should change, as can be seen in the series of snapshots below:
 
181
 
 
182
    ![](images/filter_2d_tutorial_result.jpg)