11- OpenCV:自定义线性滤波(卷积,卷积边缘)_opencv 自定义卷积模板

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

— 卷积是图像处理中一个操作,是kernel在图像的每个像素上的操作。

— Kernel本质上一个固定大小的矩阵数组,其中心点称为锚点(anchor point)

(2)卷积操作可以理解为在图像上滑动一个小的核,并将核的每个元素与对应位置的图像像素值相乘,然后将所有乘积结果相加得到输出图像的对应像素值。这个过程可以简单地表示为:

output(x, y) = sum(kernel(i, j) * input(x+i, y+j))

其中,output(x, y)是输出图像的像素值,kernel(i, j)是核的元素值,input(x+i, y+j)是输入图像的像素值。

(3)卷积操作在图像处理中有多种应用,其中最常见的是图像滤波。通过选择不同的核,可以实现不同的滤波效果,例如平滑滤波、边缘检测等。卷积操作还可以用于图像特征提取,例如使用卷积神经网络(CNN)进行图像分类、目标检测等任务。

在OpenCV中,可以使用cv::filter2D函数来进行卷积操作。该函数接受输入图像、核以及输出图像作为参数,并将卷积结果存储在输出图像中。

2、卷积如何工作

把kernel放到像素数组之上,求锚点周围覆盖的像素乘积之和(包括锚点),用来替换锚点覆盖下像素点值称为卷积处理。数学表达如下

公式讲解:

K(i,j):卷积核的大小

I里面的参数就是窗口的半径

两个方向X、Y方向上的求和

例子:从左到右,从上到下进行计算

Sum = 8x1+6x1+6x1+2x1+8x1+6x1+2x1+2x1+8x1

New pixel = sum / (m*n)

3、常见算子(卷积核 Kenel)

(1)Robert算子:又称“梯度算子”

(2)Sobel算子:中间2*2,更大,比Robert算子的差异更大,效果可能更明显了

(3)拉普拉斯算子

4、自定义卷积模糊

(1)filter2D方法

filter2D (

Mat src, //输入图像

Mat dst, // 模糊图像

int depth, // 图像深度32/8,不知道的就默认-1,系统也默认和src的深度一样

Mat kernel, // 卷积核/模板

Point anchor = Point(-1,-1) , // 锚点位置,3、5、7、9,或者默认自动寻找中心位置

double delta = 0 // 计算出来的像素+delta

)

其中 kernel是可以自定义的卷积核

5、代码演示
#include <opencv2/opencv.hpp>
#include <iostream>
#include <math.h>

using namespace cv;
int main(int argc, char** argv)
{
	Mat src, dst;
	int ksize = 0;

	src = imread("test.jpg");
	if (!src.data)
	{
		printf("could not load image...\n");
		return -1;
	}

	char INPUT_WIN[] = "input image";
	char OUTPUT_WIN[] = "Custom Blur Filter Result";
	namedWindow(INPUT_WIN, CV_WINDOW_AUTOSIZE);
	namedWindow(OUTPUT_WIN, CV_WINDOW_AUTOSIZE);

	imshow(INPUT_WIN, src);

	// Robert 算子 X 方向
	//Mat Robert_x = (Mat_<int>(2, 2) << 1, 0, 0, -1);
	//Mat mat_Robert_x;
	//filter2D(src, mat_Robert_x, -1, Robert_x);
	//imshow("Robert x", mat_Robert_x);

	 Robert 算子 Y 方向
	//Mat Robert_y = (Mat_<int>(2, 2) << 0, 1, -1, 0);
	//Mat mat_Robert_y;
	//filter2D(src, mat_Robert_y, -1, Robert_y);
	//imshow("Robert y", mat_Robert_y);

	// Sobel X 方向
	Mat kernel_x = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
	filter2D(src, dst, -1, kernel_x, Point(-1, -1), 0.0);
	imshow("Sobel X", dst);

	// Sobel Y 方向
	Mat yimg;
	Mat kernel_y = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
	filter2D(src, yimg, -1, kernel_y, Point(-1, -1), 0.0);
	imshow("Sobel Y", yimg);


	// 拉普拉斯算子
	//Mat kernel_y = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
	//filter2D(src, dst, -1, kernel_y, Point(-1, -1), 0.0);
	//imshow("拉普拉斯", dst);
	
	waitKey(0);

    // 自定义卷积模糊
	//int c = 0;
	//int index = 0;
	//while (true)null
	//{
	//	c = waitKey(500);
	//	if ((char)c == 27) // ESC
	//	{ 
	//		break;
	//	}
	//	ksize = 5 + (index % 8) * 2;
	//	Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F) / (float)(ksize * ksize);
	//	filter2D(src, dst, -1, kernel, Point(-1, -1));
	//	index++;
	//	imshow(OUTPUT_WIN, dst);
	//}

	return 0;
}

效果展示:

(1)Robert算子,在X与Y方向上呈现出差异性

(2)Sobel算子:相对与Robert算子,差异会明显一些

(3)拉普拉斯算子:碎发也没看到了

二、卷积边缘
1、卷积边缘问题

卷积边缘问题:图像卷积的时候边界像素,不能被卷积操作。

原因:在于边界像素没有完全跟kernel重叠,所以当3x3滤波时候有1个像素的边缘没有被处理,5x5滤波的时候有2个像素的边缘没有被处理。

2、处理边缘

在卷积开始之前增加边缘像素,填充的像素值为0或者RGB黑色,比如3x3在 四周各填充1个像素的边缘,这样就确保图像的边缘被处理,在卷积处理之 后再去掉这些边缘。

openCV中默认的处理方法是: BORDER_DEFAULT,此外 常用的还有如下几种:

  • BORDER_CONSTANT – 填充边缘用指定像素值

  • BORDER_REPLICATE – 填充边缘像素用已知的边缘像素值

  • BORDER_WRAP – 用另外一边的像素来补偿填充

3、相关的API说明

给图像添加边缘API:copyMakeBorder

copyMakeBorder(

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

[外链图片转存中…(img-75OgSEcN-1715518212180)]
[外链图片转存中…(img-8KZm6VUJ-1715518212181)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 20
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值