仅自学做笔记用,后续有错误会更改
参考文章:http://t.zoukankan.com/whw1314-p-12007928.html
理论
-
卷积的概念:
-
在图像上使用卷积的目的:模糊图像, 提取边缘轮廓, 图像锐化等
-
卷积如何工作:
下边给出一个均值滤波(卷积的一种)的图例:
-
常见的卷积算子(kernel, 核), 这些算子在边缘提取中都经常用到
- 注1:拉普拉斯算子(0, -1, 0, -1, 4, -1, 0, -1, 0)是边缘提取,锐化算子(0, -1, 0, -1, 5, -1, 0, -1, 0)是边缘锐化,两个算子很相似, 但是结果相差极大
- 注2:Sobel算子的边缘提取效果比较强烈
相关API
filter2D( src, dst, depth, kernel, anchor, detal, borderType )
- src: 原图像
- dst: 目标图像
- depth: 目标图像深度,填-1就是程序自动识别图像深度
- kernel:卷积的核
- anchor:核的锚点,指示内核中过滤点的相对位置, 锚应位于内核中, 默认值(-1,-1)表示锚位于内核中心
- detal:在将它们存储在dst中之前,将可选值添加到已过滤的像素中, 就是个偏移量
- boderType:像素外推法,参见BorderTypes
代码示例
using namespace cv;
int main(int argc, char** argv){
Mat src,dst;
int ksize = 0;
src = imread(...);
if( !src.data ){
return -1;
}
char INPUT_WIN[] = "input image";
namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
imshow(INPUT_WIN, src);
// 边缘提取:Rebert X方向
Mat rebert_x_Image;
Mat rebert_x = (Mat_<int>(2,2) << 1, 0, 0, -1);
filter2D(src, rebert_x_Image, -1, rebert_x, Point(-1, -1), 0.0);
// 边缘提取:Rebert Y方向
Mat rebert_y_Image;
Mat rebert_y = (Mat_<int>(2,2) << 0, 1, -1, 0);
filter2D(src, rebert_y_Image, -1, rebert_y, Point(-1, -1), 0.0);
imshow("Rebert X",rebert_x_Image);
imshow("Rebert Y",rebert_y_Image);
//边缘提取:Sobel X方向
Mat sobel_x_Image;
Mat sobel_x = (Mat_<int>(3,3) << -1, 0, 1, -2, 0 ,2, -1, 0, 1);
filter2D(src, sobel_x_Image, -1, sobel_x , Point(-1, -1), 0.0);
//边缘提取:Sobel Y方向
Mat sobel_y_Image;
Mat sobel_y = (Mat_<int>(3,3) << -1, -2, -1, 0, 0 ,0, 1, 2, 1);
filter2D(src, sobel_y_Image, -1, sobel_y , Point(-1, -1), 0.0);
imshow("Sobel X",sobel_x_Image);
imshow("Sobel Y",sobel_y_Image);
//边缘提取:拉普拉斯算子
Mat laplacian_Image;
Mat laplaian_kernel = (Mat_<int>(3,3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
filter2D(src, laplacian_Image, -1, laplaian_kernel, Point(-1, -1), 0.0);
imshow("Laplacian",laplacian_Image);
// 自定义卷积模糊, 以下代码实现每隔半秒就变换模糊程度,一直重复循环的过程
int c = 0;
int index = 0 ;
while(true){
c = waitKey(500);
if( (char)c == 27){ //这里的27是ESC键
break;
}
ksize = 4 + (index % 5) * 2 + 1;
//Mat::ones()创建一个全是1的核, 后边再除以的ksize*ksize, 意思就是:假如ksize为5, 那么生成的核里面全都是1/5*5
Mat custom_kernel = Mat::ones(Size(ksize,ksize), CV_32F) / (float)(ksize * ksize);
filter2D(src, dst, -1, custom_kernel , Point(-1, -1));
index++;
imshow("custom image", dst);
}
waitKey(0);
return 0;
}
效果截图:
Rebert算子(分别X丶Y两个方向提取)边缘提取效果:
Sobel算子(分别X丶Y两个方向提取)边缘提取效果:
拉普拉斯算子边缘提取效果:
自定义卷积模糊效果: