OpenCV 图像卷积:cv.filter2D() 函数详解

您所在的位置:网站首页 python中delta函数 OpenCV 图像卷积:cv.filter2D() 函数详解

OpenCV 图像卷积:cv.filter2D() 函数详解

2023-07-22 07:02| 来源: 网络整理| 查看: 265

API

照例,我们搬一下官网的 API:

C++ void cv::filter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernel, Point anchor=Point(-1, -1), double delta=0, int borderType=BORDER_DEFAULT ) Python dst=cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) 函数详解

这个函数一般是用于图像的卷积,但 OpenCV 文档里说这个函数不完全等于图像卷积。这一点说实话我看到的时候也震惊到了,我一直是拿它当卷积来用的。但是仔细考虑后,我认为这一点完全是定义上的差异,日常用的图像卷积定义和这个函数的功能实际上是一致的。

HelloWorld

直接上手做往往能给人最直观的感受。因此,最开始这里我要放一个使用这个函数的最小化程序,可以称之为该函数的 hello world 程序。这个程序跑通了,就可以很方便地尝试其他参数的作用了。

# HelloWrold Program of cv.filter2D # by Aling on 2021/1/18 import numpy as np import cv2 as cv def main(): img = cv.imread("你想读的图片") # 定义卷积核 kernel = np.ones((10, 10)) / 100 # 执行滤波 avg_filtered = cv.filter2D(img, -1, kernel) # 显示图片 cv.imshow("Average filtered", avg_filtered) cv.waitKey(0) cv.destroyAllWindows() if __name__ == "__main__": main()

这个程序读取一张图片,并将其通过10 x 10 的卷积核作均值滤波并显示结果。

滤波效果

参数详解

同样的,这里把各个参数打一张表:

参数类型是否必须指定(默认值)具体含义srcnumpy.ndarray是原图像ddepthint是目标图像深度(指数据类型)kernelnumpy.ndarray是卷积核anchortuple否(卷积核中心)卷积锚点delta是数据类就行否(0)偏移量,卷积结果要加上这个数字borderTypeint(实际上是 enum 类)否(cv.BORDER_DEFALUT)边缘类型 src

这个参数没什么好说的,就是原图像。它可以是任何色彩模式,这就意味着如果你把原本送到这个函数里的图片从黑白变成了彩色(单通道变成了 3 通道),你并不需要更改其他参数。本身,对多通道的图像,卷积就是以通道为单位进行的。

ddepth

这个参数有点费解了。大部分情况下不需要管它是干嘛的,直接把它设成 -1 就没有任何问题。

参数名 ddepth ,英文是 desired depth,即期望深度。什么意思呢?我们来看它的可能取值表(来自这里):

输入深度(src.depth())期望深度(ddepth)CV_8U-1/CV_16S/CV_32F/CV_64FCV_16U/CV_16S-1/CV_32F/CV_64FCV_32F-1/CV_32F/CV_64FCV_64F-1/CV_64F

这个表里的一大串 CV 打头的符号到底是什么意思呢?实际上这些符号的末尾字母对应了数据类型:

U == Unsigned int # 无符号整型 S == Signed int # 有符号整型 F == Float # 浮点型

中间的数字很显然代表了数据类型所占用的空间(bit)。所以,所谓深度,其实指的是数据类型。

那就好说了,你会发现这里其实是规定了输出数据的类型,包括每个通道的每个像素占用多少空间。输出数据的类型必须根据上面的表格中输入对应的类型指定。这里 -1 表示输出类型和输入相同。

不过,值得注意的是,似乎有些数据类型无法通过 cv2.imshow 正常显示,可以用 matplotlib.pyplot.imshow 来代替。

但是,还是注意,没有关于数据类型的特别要求时,这个功能是不需要的,取 -1 即可。

kernel & anchor

这两个参数都是卷积相关的,因此放在一节里面讲述。接下来的内容假设你已经了解了图像卷积。

这里,kernel 很显然表示的是卷积核,这是一个 numpy.ndarray 类型的矩阵。这个矩阵的生成可以用 numpy 自带的函数,但是对于复杂一些的卷积核,OpenCV 内部的一些函数显然更合适。如 getStructuringElement,getGaussianKernel,前者用于获取特定形状的核,后者则是高斯核生生成器(不过要注意生成的是一个向量)。

# 方法一示例 kernel = cv.getStructuringElement(cv.MORPH_RECT, (11, 11)) # 方法二示例 vector = cv.getGaussianKernel(11, -1) kernel = vector @ vector.T

anchor 则表示锚点。什么叫锚点呢?看下面这张图:

convolution

可以说,锚点 anchor 决定了卷积核相对于生成目标点的位置。虽然锚点是相对于卷积核来定义的,但是卷积的过程更像是通过锚点去寻找卷积核。遍历图像中的每一个像素,以每一个像素为锚点,按照相对位置生成卷积范围,和卷积核对应元素相乘再求和得到目标图像中对应像素的值。可以用公式表示成: dst ( x , y ) = ∑ 0 ≤ x ′ < kernel.cols 0 ≤ y ′ < kernel.rows kernel ( x ′ , y ′ ) × src ( x + x ′ − anchor.x , y + y ′ − anchor.y ) \text{dst}(x, y)=\sum_{\begin{matrix}0\leq x^\prime < \text{kernel.cols} \\ 0 \leq y^\prime



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3