自定义线性滤波
线性滤波就是卷积,实际上的作用就是降噪。
-
卷积概念
- 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。
- Kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)
-
卷积如何工作?
- 把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理。
- 数学表达如下:
H
(
x
,
y
)
=
∑
i
=
0
M
i
−
1
∑
j
=
0
M
j
−
1
I
(
x
+
i
−
a
i
,
y
+
j
−
a
j
)
K
(
i
,
j
)
H(x, y)=\sum_{i=0}^{M_{i}-1} \sum_{j=0}^{M_{j}-1} I\left(x+i-a_{i}, y+j-a_{j}\right) K(i, j)
H(x,y)=∑i=0Mi−1∑j=0Mj−1I(x+i−ai,y+j−aj)K(i,j)
Sum = 8x1+6x1+6x1+2x1+8x1+6x1+2x1+2x1+8x1
New pixel = sum / (m*n)
-
常见算子
-
Robert算子
-
Sobel算子
-
拉普拉斯算子
-
-
自定义卷积模糊
- filter2D函数
filter2D( Mat src, //输入图像 Mat dst, // 模糊图像 int depth, // 图像深度32/8 Mat kernel, // 卷积核/模板 Point anchor, // 锚点位置 double delta // 计算出来的像素+delta ) 其中 kernel是可以自定义的卷积核
知道卷积、傅里叶变换,这样就具备了图像处理的基础知识。
完整代码:
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/types_c.h>
using namespace std;
using namespace cv;
#ifndef P16
#define P16 16
#endif
int main() {
std::string path = "../fei.JPG";
cv::Mat img = cv::imread(path, 5);
string str_input = "input image";
string str_output = "output image";
if(img.empty())
{
std::cout << "open file failed" << std::endl;
return -1;
}
#if P16 //自定义线性卷积
imshow("input", img);
Mat dest_x,dest_y;
//Robert X方向
Mat kernel_x = (Mat_<int>(2,2) << 1,0,0,-1);
filter2D(img,dest_x,-1,kernel_x,Point(-1,-1),0.0);
imshow("Robert X", dest_x);
//Robert Y方向
Mat kernel_y = (Mat_<int>(2,2) << 0,1,-1,0);
filter2D(img,dest_y,-1,kernel_y,Point(-1,-1),0.0);
imshow("Robert Y", dest_y);
int ksize;
Mat kernel;
int c = 0;
int index = 1;
while(true)
{
c = waitKey(500);
if((char)c == 27)
{
break;
}
ksize = 3 + 2 *(index %5);
kernel = Mat::ones(Size(ksize,ksize),CV_32F)/(float)(ksize*ksize);
filter2D(img,dest_x,-1,kernel,Point(-1,-1),0);
imshow("result",dest_x);
index ++;
}
#endif
cv::waitKey(0);
cv::destroyAllWindows();
return 0;
}