【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)

仅自学做笔记用,后续有错误会更改

参考文章:http://t.zoukankan.com/whw1314-p-12007928.html

理论

  1. 卷积的概念:
    【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第1张图片

  2. 在图像上使用卷积的目的:模糊图像, 提取边缘轮廓, 图像锐化等

  3. 卷积如何工作:
    【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第2张图片
    下边给出一个均值滤波(卷积的一种)的图例:
    【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第3张图片
    【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第4张图片

  4. 常见的卷积算子(kernel, 核), 这些算子在边缘提取中都经常用到
    【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第5张图片

  • 注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_(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_(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_(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_(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_(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两个方向提取)边缘提取效果:

拉普拉斯算子边缘提取效果:
【OpenCV学习】第14课:边缘检测与自定义线性滤波(卷积, Rebert算子, Sobel算子, 拉普拉斯算子)_第6张图片
自定义卷积模糊效果:


你可能感兴趣的:(OpenCV学习,opencv,学习,计算机视觉)