Goal
In this tutorial you will learn how to:
- Use the OpenCV function filter2D() to create your own linear filters.
- 使用OpenCV函数filter2D()创建自己的线性滤波器
Theory
- Note
The explanation below belongs to the book Learning OpenCV by Bradski and Kaehler.
- 理论来源于《Learning OpenCV》这本书
Correlation
In a very general sense, correlation is an operation between every part of an image and an operator (kernel).
correlation 是图像的每一部分与核的操作。
What is a kernel?
A kernel is essentially a fixed size array of numerical coefficients along with an anchor point in that array, which is typically located at the center.
内核本质上是一个固定大小的数值系数矩阵,并且其锚点通常位于矩阵的中心。
How does correlation with a kernel work?
Assume you want to know the resulting value of a particular location in the image. The value of the correlation is calculated in the following way:
- Place the kernel anchor on top of a determined pixel, with the rest of the kernel overlaying the corresponding local pixels in the image.(top 不应该是中心吗???)
- Multiply the kernel coefficients by the corresponding image pixel values and sum the result.(相乘,最后求和)
- Place the result to the location of the anchor in the input image.(给图像中与锚点对应的元素)
- Repeat the process for all pixels by scanning the kernel over the entire image.(内核与图像的其他部分重复上述计算)
Expressing the procedure above in the form of an equation we would have:
Fortunately, OpenCV provides you with the function filter2D() so you do not have to code all these operations.
What does this program do?
- Loads an image(加载图像)
-
Performs a normalized box filter. For instance, for a kernel of size size=3, the kernel would be:
K=13⋅3⎡⎣⎢111111111⎤⎦⎥
The program will perform the filter operation with kernels of sizes 3, 5, 7, 9 and 11.(归一化运算)
- The filter output (with each kernel) will be shown during 500 milliseconds(输出结果将在500毫秒显示)
Code
#include "opencv2/imgproc.hpp"#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
using namespace cv;
int main ( int argc, char** argv )
{
// Declare variables
Mat src, dst;
Mat kernel;
Point anchor;
double delta;
int ddepth;
int kernel_size;
const char* window_name = "filter2D Demo";
const char* imageName = argc >=2 ? argv[1] : "lena.jpg";
// Loads an image
src = imread( imageName, IMREAD_COLOR ); // Load an image
if( src.empty() )
{
printf(" Error opening image\n"); //竟然可以用,没有C标准的头文件
printf(" Program Arguments: [image_name -- default lena.jpg] \n"); //竟然可以用,没有C标准的头文件
return -1;
}
// Initialize arguments for the filter
anchor = Point( -1, -1 ); //就是中心
delta = 0;
ddepth = -1;
// Loop - Will filter the image with different kernel sizes each 0.5 seconds
int ind = 0;
for(;;)
{
// Update kernel size for a normalized box filter
kernel_size = 3 + 2*( ind%5 );
kernel = Mat::ones( kernel_size, kernel_size, CV_32F )/ (float)(kernel_size*kernel_size);
// Apply filter
filter2D(src, dst, ddepth , kernel, anchor, delta, BORDER_DEFAULT );
//输入,输出,深度(-1表示于src相同),内核,锚点相对于内核的位置,加到每个像素上的值,边界
imshow( window_name, dst );
char c = (char)waitKey(500);
// Press 'ESC' to exit the program
if( c == 27 )
{ break; }
ind++;
}
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
project( DisplayImage )
find_package( OpenCV REQUIRED )
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable( DisplayImage main.cpp )
target_link_libraries( DisplayImage ${OpenCV_LIBS} )
install(TARGETS DisplayImage RUNTIME DESTINATION bin)
Results
结果是一个渐变的过程,同时没500ms,内核的大小也会变化一次。