OpenCV-C++ 自定义线性滤波
这一节主要介绍卷积的概念,以及常见的算子,在最后简单介绍自定义卷积核,并利用filter2D
这个API执行图像模糊
卷积概念
- 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作;
- kernel本质上一个固定大小的矩阵数组,其中心点称为锚点;
\[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)
\]
卷积核也被称为算子;
下面的算子可以获取图像的边缘信息;不同的算子边缘方向信息不同;
自定义卷积模糊
实际上就是自定义卷积核;
完整程序如下:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(){
// 读取图像
Mat src = imread("/home/chen/dataset/lena.jpg");
if (src.empty()){
cout << "could not load image." << endl;
return -1;
}
namedWindow("src", WINDOW_AUTOSIZE);
imshow("src", src);
// Robert算子
Mat kernelRobert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
Mat dstRobert_x;
filter2D(src, dstRobert_x, -1, kernelRobert_x, Point(-1, -1), 0.0);
namedWindow("dstRobert_x", WINDOW_AUTOSIZE);
imshow("dstRobert_x", dstRobert_x);
Mat kernelRobert_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);
Mat dstRobert_y;
filter2D(src, dstRobert_y, -1, kernelRobert_y, Point(-1, -1), 0.0);
namedWindow("dstRobert_y", WINDOW_AUTOSIZE);
imshow("dstRobert_y", dstRobert_y);
// Sobel算子
Mat kernelSobel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
Mat dstSobel_x;
filter2D(src, dstSobel_x, -1, kernelSobel_x, Point(-1, -1), 0.0);
namedWindow("dstSobel_x", WINDOW_AUTOSIZE);
imshow("dstSobel_x", dstSobel_x);
Mat kernelSobel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
Mat dstSobel_y;
filter2D(src, dstSobel_y, -1, kernelSobel_y, Point(-1, -1), 0.0);
namedWindow("dstSobel_y", WINDOW_AUTOSIZE);
imshow("dstSobel_y", dstSobel_y);
// 拉普拉斯算子
Mat kernelLa = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
Mat dstLa;
filter2D(src, dstLa, -1, kernelLa, Point(-1, -1), 0.0);
namedWindow("dstLa", WINDOW_AUTOSIZE);
imshow("dstLa", dstLa);
// 自定义卷积核
int c = 0;
int ksize = 0;
int index = 0;
Mat dst;
namedWindow("dst", WINDOW_AUTOSIZE);
while(true){
c = waitKey(500);
if ((char)c == 27){
break;
}
ksize = 4 + (index % 5)*2 + 1;
Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize*ksize);
filter2D(src, dst, -1, kernel, Point(-1, -1), 0.0);
imshow("dst", dst);
index++;
}
waitKey(0);
return 0;
}