数字图像是一个二维的离散信号,对数字图像做卷积操作其实就是利用卷积核(卷积模板)在图像上滑动,将图像点上的像素灰度值与对应的卷积核上的数值相乘,然后将所有相乘后的值相加作为卷积核中间像素对应的图像上像素的灰度值,并最终滑动完所有图像的过程。
这张图可以清晰的表征出整个卷积过程中一次相乘后相加的结果:该图片选用3*3的卷积核,卷积核内共有九个数值,所以图片右上角公式中一共有九行,而每一行都是图像像素值与卷积核上数值相乘,最终结果-8代替了原图像中对应位置处的1。这样沿着图片一步长为1滑动,每一个滑动后都一次相乘再相加的工作,我们就可以得到最终的输出结果。除此之外,卷积核的选择有一些规则: 1)卷积核的大小一般是奇数,这样的话它是按照中间的像素点中心对称的,所以卷积核一般都是3x3,5x5或者7x7。有中心了,也有了半径的称呼,例如5x5大小的核的半径就是2。 2)卷积核所有的元素之和一般要等于1,这是为了原始图像的能量(亮度)守恒。其实也有卷积核元素相加不为1的情况,下面就会说到。 3)如果滤波器矩阵所有元素之和大于1,那么滤波后的图像就会比原图像更亮,反之,如果小于1,那么得到的图像就会变暗。如果和为0,图像不会变黑,但也会非常暗。 4)对于滤波后的结构,可能会出现负数或者大于255的数值。对这种情况,我们将他们直接截断到0和255之间即可。对于负数,也可以取绝对值。
参考博客(理解图像卷积操作的意义,里面也罗列了一些常用的卷积核):https://blog.csdn.net/chaipp0607/article/details/72236892
1.边界补充问题上面的图片说明了图像的卷积操作,但是他也反映出一个问题,如上图,原始图片尺寸为7*7,卷积核的大小为3*3,当卷积核沿着图片滑动后只能滑动出一个5*5的图片出来,这就造成了卷积后的图片和卷积前的图片尺寸不一致,这显然不是我们想要的结果,所以为了避免这种情况,需要先对原始图片做边界填充处理。在上面的情况中,我们需要先把原始图像填充为9*9的尺寸。 常用的区域填充方法有,边界复制、镜像填充、快填充等。
以filter2D默认的BORDER_DEFAULT(等效于BORDER_REFLECT_101)为例,文档描述为(gfedcb|abcdefgh|gfedcba),也就是说这是镜像填充的,画个示意图(圈起来的为原本的数据,外部为卷积计算用的补充边界):
参考博客:https://blog.csdn.net/qq_32846595/article/details/79057040
2.filter2D的使用filter2D将图像与卷积核做卷积,函数原型如下:
void cv::filter2D(
InputArray src, //源图像Mat对象
OutputArray dst, //目标图像Mat对象
int ddepth, //目标图像的深度,一般填-1即可,表示源图像与目标图像深度相同。
InputArray kernel, //卷积核,一个单通道浮点型矩阵。如果想在图像不同的通道使用不同的kernel,可以先使用split()函数将图像通道事先分开。
Point anchor = Point(-1, -1), //内核的基准点,其默认值为(-1,-1)说明位于kernel的中心位置。基准点即kernel中与进行处理的像素点重合的点
double delta = 0, //在储存目标图像前可选的添加到像素的值,默认值为0,不填就是默认值。
int borderType = BORDER_DEFAULT //边界填充的类型,默认值是BORDER_DEFAULT,文档说明为gfedcb|abcdefgh|gfedcba镜像填充的。
)
我们先用一个3*3的数据矩阵和一个3*3的卷积核来测试下他的计算过程:
//一个3*3的Mat图像
Mat src_mat = (Mat_(3, 3)
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?