卷积常用在信号处理中,而图像信息可以看作一种信号。
前言
图像处理中,平滑、模糊、去燥、锐化、边缘提取等等工作,其实都可以通过卷积操作来完成
一、图像卷积是什么?
在计算机看来,数字图像是一个二维的离散信号,对数字图像做卷积操作其实就是利用卷积核(卷积模板)在图像上滑动,将图像点上的像素灰度值与对应的卷积核上的数值相乘,然后将所有相乘后的值相加作为卷积核中间像素对应的图像上像素的灰度值,并最终滑动完所有图像的过程。
二、函数介绍
1.函数原型
代码如下(示例):
dst = cv.filter2D(src,
ddepth,
kernel
[,dst
[,anchor
[,delta
[,borderType]]]])
#src:输入图像
#ddepth:输出图像的数据类型(深度)
#kernel:单通道卷积核,数据类型为float32,卷积核大小多为3x3、5x5等
#dst:输出图像
#anchor:卷积模板的内核基准点(锚点)
#delta:偏差,在计算结果中加上偏差
#borderType:像素边界外推法选择标志
2.函数解释
函数主要用于求取图像和卷积核模板之间的卷积运算,并将卷积后的结果返回。函数的第一个参数src允许多通道图像。如果多通道的图像每一个通道不要每个通道进行不同卷积就可以使用同一个卷积模板,但是如果需要进行不同的卷积操作,那么就要将图像的各个通道进行分离,分离通道的函数cv.split(),将图像分离成不同通道在进行不同的卷积。函数的第二个参数ddepth为-1时,输出图像的数据类型与输入图像一致。dst参数的维度以及通道数和src保持一致。其中,anchor参数代表卷积模板中对应的图像像素,内核基准点的位置可以在卷积核模板中任意指定,其默认值为(-1,-1)代表内核基准点在kernel的中心,基准点是卷积核中与进行处理的像素重合的点,其位置必须位于卷积核内部。delta参数就是处理结果再加上它,最后作为结果输出。像素边界外推法的标志,默认值为CV.BORDER_DEFAULT,表示不包含边界值倒序填充。
像素边界外推法标志
标志 | 简记 | 作用 |
---|---|---|
cv.BORDER_CONSTANT | 0 | 用特定值填充 |
cv.BORDER_REPLICATE | 1 | 两端复制填充 |
cv.BORDER_REFLECT | 2 | 倒序填充 |
cv.BORDER_WRAP | 3 | 正序填充 |
cv.BORDER_REFLECT_101 | 4 | 不包含边界值倒序填充 |
cv.BORDER_TRANSPARENT | 5 | 随机填充 |
cv.BORDER_REFLECT101 | 4 | 不包含边界值倒序填充 |
cv.BORDER_DEFAULT | 4 | 不包含边界值倒序填充 |
cv.BORDER_ISOLATED | 16 | 不关系感兴趣区域之外的部分 |
# 常见卷积核 
import cv2
import cv2 as cv
import numpy as np
import sys
#读取图片
img = cv.imread("opencv_test\8.jpg",cv.IMREAD_GRAYSCALE)
if img is None:
print("fail to read images")
sys.exit()
#建立卷积核
#无效卷积核
kernel1 = np.array([ [0,0,0],
[0,1,0],
[0,0,0]],dtype='float32')
#均值卷积核
kernel2 = np.ones((3,3),np.float32)/9
#高斯卷积核
kernel3 = np.array([ [1,2,1],
[2,4,2],
[1,2,1]],dtype='float32')/16
#水平梯度
kernel4 = np.array([ [1,1,1],
[0,0,0],
[-1,-1,-1]],dtype='float32')
#垂直梯度
kernel5 = np.array([ [1,0,-1],
[1,0,-1],
[1,0,-1]],dtype='float32')
#梯度Laplacecian
kernel6 = np.array([ [1,1,1],
[1,-8,1],
[1,1,1]],dtype='float32')
#锐化
kernel7 = np.array([ [-1,-1,-1],
[-1,9,-1],
[-1,-1,-1]],dtype='float32')
if __name__ == "__main__":
result = cv.filter2D(img,-1,kernel=kernel3)
cv.imshow("origin",img)
cv.imshow("result",result)
cv.waitKey(0)
cv.destroyAllWindows()
总结
cv.filter2D()函数不会将卷积模板旋转,如果卷积模板并不是中心对称,需要将卷积模板先旋转180°在输入该函数。
参考文献
[1] 冯振、陈亚萌的基于python的opencv4详解[M],中国工信出版集团