Skip to content

Commit a6f5e1f

Browse files
committed
Tutorial Filter2D
1 parent 0851528 commit a6f5e1f

File tree

5 files changed

+297
-87
lines changed

5 files changed

+297
-87
lines changed
Lines changed: 112 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
Making your own linear filters! {#tutorial_filter_2d}
22
===============================
33

4+
@prev_tutorial{tutorial_threshold_inRange}
5+
@next_tutorial{tutorial_copyMakeBorder}
6+
47
Goal
58
----
69

710
In this tutorial you will learn how to:
811

9-
- Use the OpenCV function @ref cv::filter2D to create your own linear filters.
12+
- Use the OpenCV function **filter2D()** to create your own linear filters.
1013

1114
Theory
1215
------
@@ -40,61 +43,127 @@ Expressing the procedure above in the form of an equation we would have:
4043

4144
\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]
4245

43-
Fortunately, OpenCV provides you with the function @ref cv::filter2D so you do not have to code all
46+
Fortunately, OpenCV provides you with the function **filter2D()** so you do not have to code all
4447
these operations.
4548

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

54-
\f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix}
55-
1 & 1 & 1 \\
54+
\f[K = \dfrac{1}{3 \cdot 3} \begin{bmatrix}
55+
1 & 1 & 1 \\
5656
1 & 1 & 1 \\
5757
1 & 1 & 1
58-
\end{bmatrix}\f]
58+
\end{bmatrix}\f]
59+
60+
The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11.
5961

60-
The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11.
62+
- The filter output (with each kernel) will be shown during 500 milliseconds
6163

62-
- The filter output (with each kernel) will be shown during 500 milliseconds
64+
Code
65+
----
6366

64-
-# The tutorial code's is shown lines below. You can also download it from
65-
[here](https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp)
66-
@include cpp/tutorial_code/ImgTrans/filter2D_demo.cpp
67+
The tutorial code's is shown in the lines below.
68+
69+
@add_toggle_cpp
70+
You can also download it from
71+
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp)
72+
@include cpp/tutorial_code/ImgTrans/filter2D_demo.cpp
73+
@end_toggle
74+
75+
@add_toggle_java
76+
You can also download it from
77+
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java)
78+
@include java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java
79+
@end_toggle
80+
81+
@add_toggle_python
82+
You can also download it from
83+
[here](https://raw.githubusercontent.com/opencv/opencv/master/samples/python/tutorial_code/ImgTrans/Filter2D/filter2D.py)
84+
@include python/tutorial_code/ImgTrans/Filter2D/filter2D.py
85+
@end_toggle
6786

6887
Explanation
6988
-----------
7089

71-
-# Load an image
72-
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load
73-
-# Initialize the arguments for the linear filter
74-
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments
75-
-# Perform an infinite loop updating the kernel size and applying our linear filter to the input
76-
image. Let's analyze that more in detail:
77-
-# First we define the kernel our filter is going to use. Here it is:
78-
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel
79-
The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$. The second
80-
line actually builds the kernel by setting its value to a matrix filled with \f$1's\f$ and
81-
normalizing it by dividing it between the number of elements.
82-
83-
-# After setting the kernel, we can generate the filter by using the function @ref cv::filter2D :
84-
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter
85-
The arguments denote:
86-
87-
-# *src*: Source image
88-
-# *dst*: Destination image
89-
-# *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
90+
#### Load an image
91+
92+
@add_toggle_cpp
93+
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp load
94+
@end_toggle
95+
96+
@add_toggle_java
97+
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java load
98+
@end_toggle
99+
100+
@add_toggle_python
101+
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py load
102+
@end_toggle
103+
104+
#### Initialize the arguments
105+
106+
@add_toggle_cpp
107+
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp init_arguments
108+
@end_toggle
109+
110+
@add_toggle_java
111+
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java init_arguments
112+
@end_toggle
113+
114+
@add_toggle_python
115+
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py init_arguments
116+
@end_toggle
117+
118+
##### Loop
119+
120+
Perform an infinite loop updating the kernel size and applying our linear filter to the input
121+
image. Let's analyze that more in detail:
122+
123+
- First we define the kernel our filter is going to use. Here it is:
124+
125+
@add_toggle_cpp
126+
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp update_kernel
127+
@end_toggle
128+
129+
@add_toggle_java
130+
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java update_kernel
131+
@end_toggle
132+
133+
@add_toggle_python
134+
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py update_kernel
135+
@end_toggle
136+
137+
The first line is to update the *kernel_size* to odd values in the range: \f$[3,11]\f$.
138+
The second line actually builds the kernel by setting its value to a matrix filled with
139+
\f$1's\f$ and normalizing it by dividing it between the number of elements.
140+
141+
- After setting the kernel, we can generate the filter by using the function **filter2D()** :
142+
143+
@add_toggle_cpp
144+
@snippet cpp/tutorial_code/ImgTrans/filter2D_demo.cpp apply_filter
145+
@end_toggle
146+
147+
@add_toggle_java
148+
@snippet java/tutorial_code/ImgTrans/Filter2D/Filter2D_Demo.java apply_filter
149+
@end_toggle
150+
151+
@add_toggle_python
152+
@snippet python/tutorial_code/ImgTrans/Filter2D/filter2D.py apply_filter
153+
@end_toggle
154+
155+
- The arguments denote:
156+
- *src*: Source image
157+
- *dst*: Destination image
158+
- *ddepth*: The depth of *dst*. A negative value (such as \f$-1\f$) indicates that the depth is
90159
the same as the source.
91-
-# *kernel*: The kernel to be scanned through the image
92-
-# *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
93-
indicates the center by default.
94-
-# *delta*: A value to be added to each pixel during the correlation. By default it is \f$0\f$
95-
-# *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
160+
- *kernel*: The kernel to be scanned through the image
161+
- *anchor*: The position of the anchor relative to its kernel. The location *Point(-1, -1)*
162+
indicates the center by default.
163+
- *delta*: A value to be added to each pixel during the correlation. By default it is \f$0\f$
164+
- *BORDER_DEFAULT*: We let this value by default (more details in the following tutorial)
96165

97-
-# Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be
166+
- Our program will effectuate a *while* loop, each 500 ms the kernel size of our filter will be
98167
updated in the range indicated.
99168

100169
Results
@@ -104,4 +173,4 @@ Results
104173
result should be a window that shows an image blurred by a normalized filter. Each 0.5 seconds
105174
the kernel size should change, as can be seen in the series of snapshots below:
106175

107-
![](images/filter_2d_tutorial_result.jpg)
176+
![](images/filter_2d_tutorial_result.jpg)

doc/tutorials/imgproc/table_of_content_imgproc.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ In this section you will learn about the image processing (manipulation) functio
7777

7878
- @subpage tutorial_filter_2d
7979

80+
*Languages:* C++, Java, Python
81+
8082
*Compatibility:* \> OpenCV 2.0
8183

8284
*Author:* Ana Huamán

samples/cpp/tutorial_code/ImgTrans/filter2D_demo.cpp

Lines changed: 48 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -15,56 +15,60 @@ using namespace cv;
1515
*/
1616
int main ( int argc, char** argv )
1717
{
18-
/// Declare variables
19-
Mat src, dst;
18+
// Declare variables
19+
Mat src, dst;
2020

21-
Mat kernel;
22-
Point anchor;
23-
double delta;
24-
int ddepth;
25-
int kernel_size;
26-
const char* window_name = "filter2D Demo";
21+
Mat kernel;
22+
Point anchor;
23+
double delta;
24+
int ddepth;
25+
int kernel_size;
26+
const char* window_name = "filter2D Demo";
2727

28-
//![load]
29-
String imageName("../data/lena.jpg"); // by default
30-
if (argc > 1)
31-
{
32-
imageName = argv[1];
33-
}
34-
src = imread( imageName, IMREAD_COLOR ); // Load an image
28+
//![load]
29+
const char* imageName = argc >=2 ? argv[1] : "../data/lena.jpg";
3530

36-
if( src.empty() )
37-
{ return -1; }
38-
//![load]
31+
// Loads an image
32+
src = imread( imageName, IMREAD_COLOR ); // Load an image
3933

40-
//![init_arguments]
41-
/// Initialize arguments for the filter
42-
anchor = Point( -1, -1 );
43-
delta = 0;
44-
ddepth = -1;
45-
//![init_arguments]
34+
if( src.empty() )
35+
{
36+
printf(" Error opening image\n");
37+
printf(" Program Arguments: [image_name -- default ../data/lena.jpg] \n");
38+
return -1;
39+
}
40+
//![load]
4641

47-
/// Loop - Will filter the image with different kernel sizes each 0.5 seconds
48-
int ind = 0;
49-
for(;;)
50-
{
51-
char c = (char)waitKey(500);
52-
/// Press 'ESC' to exit the program
53-
if( c == 27 )
54-
{ break; }
42+
//![init_arguments]
43+
// Initialize arguments for the filter
44+
anchor = Point( -1, -1 );
45+
delta = 0;
46+
ddepth = -1;
47+
//![init_arguments]
5548

56-
//![update_kernel]
57-
/// Update kernel size for a normalized box filter
58-
kernel_size = 3 + 2*( ind%5 );
59-
kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
60-
//![update_kernel]
49+
// Loop - Will filter the image with different kernel sizes each 0.5 seconds
50+
int ind = 0;
51+
for(;;)
52+
{
53+
//![update_kernel]
54+
// Update kernel size for a normalized box filter
55+
kernel_size = 3 + 2*( ind%5 );
56+
kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
57+
//![update_kernel]
6158

62-
//![apply_filter]
63-
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
64-
//![apply_filter]
65-
imshow( window_name, dst );
66-
ind++;
67-
}
59+
//![apply_filter]
60+
// Apply filter
61+
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
62+
//![apply_filter]
63+
imshow( window_name, dst );
6864

69-
return 0;
65+
char c = (char)waitKey(500);
66+
// Press 'ESC' to exit the program
67+
if( c == 27 )
68+
{ break; }
69+
70+
ind++;
71+
}
72+
73+
return 0;
7074
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* @file Filter2D_demo.java
3+
* @brief Sample code that shows how to implement your own linear filters by using filter2D function
4+
*/
5+
6+
import org.opencv.core.*;
7+
import org.opencv.core.Point;
8+
import org.opencv.highgui.HighGui;
9+
import org.opencv.imgcodecs.Imgcodecs;
10+
import org.opencv.imgproc.Imgproc;
11+
12+
class Filter2D_DemoRun {
13+
14+
public void run(String[] args) {
15+
// Declare variables
16+
Mat src, dst = new Mat();
17+
18+
Mat kernel = new Mat();
19+
Point anchor;
20+
double delta;
21+
int ddepth;
22+
int kernel_size;
23+
String window_name = "filter2D Demo";
24+
25+
//! [load]
26+
String imageName = ((args.length > 0) ? args[0] : "../data/lena.jpg");
27+
28+
// Load an image
29+
src = Imgcodecs.imread(imageName, Imgcodecs.IMREAD_COLOR);
30+
31+
// Check if image is loaded fine
32+
if( src.empty() ) {
33+
System.out.println("Error opening image!");
34+
System.out.println("Program Arguments: [image_name -- default ../data/lena.jpg] \n");
35+
System.exit(-1);
36+
}
37+
//! [load]
38+
39+
//! [init_arguments]
40+
// Initialize arguments for the filter
41+
anchor = new Point( -1, -1);
42+
delta = 0.0;
43+
ddepth = -1;
44+
//! [init_arguments]
45+
46+
// Loop - Will filter the image with different kernel sizes each 0.5 seconds
47+
int ind = 0;
48+
while( true )
49+
{
50+
//! [update_kernel]
51+
// Update kernel size for a normalized box filter
52+
kernel_size = 3 + 2*( ind%5 );
53+
Mat ones = Mat.ones( kernel_size, kernel_size, CvType.CV_32F );
54+
Core.multiply(ones, new Scalar(1/(double)(kernel_size*kernel_size)), kernel);
55+
//! [update_kernel]
56+
57+
//! [apply_filter]
58+
// Apply filter
59+
Imgproc.filter2D(src, dst, ddepth , kernel, anchor, delta, Core.BORDER_DEFAULT );
60+
//! [apply_filter]
61+
HighGui.imshow( window_name, dst );
62+
63+
int c = HighGui.waitKey(500);
64+
// Press 'ESC' to exit the program
65+
if( c == 27 )
66+
{ break; }
67+
68+
ind++;
69+
}
70+
71+
System.exit(0);
72+
}
73+
}
74+
75+
public class Filter2D_Demo {
76+
public static void main(String[] args) {
77+
// Load the native library.
78+
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
79+
new Filter2D_DemoRun().run(args);
80+
}
81+
}

0 commit comments

Comments
 (0)