1. 2D卷积(图像滤波)
像一维信号一样,图像也可以用各种高通道滤波器、地通道滤波器来进行滤波。低通道滤波器可以用来去除噪音,平滑图像;高通道滤波器可以用来寻找边缘。
OpenCV提供了一个函数cv2.filter2D()用卷积核对图像执行卷积操作。
void cv::filter2D (
InputArray src, //输入图
OutputArray dst, //输出图
int ddepth, //目标图期望深度(即输出mat的dtype,如uint8、uint16、32f、64f等,为-1则与输入图相同)
InputArray kernel, //卷积核(只能为单通道,奇数维度,若要对各通道分别滤波,则需要cv2.split通道后分别滤波)
Point anchor = Point(-1,-1), //卷积核中心点,默认(-1,-1)代表此卷积核处理的像素位于卷积核中心
double delta = 0, //滤波结果被写到实际像素前的,会加上此偏移值
int borderType = BORDER_DEFAULT //对于边缘像素的处理,详见文档描述
)
例如,使用一个5*5的均值滤波器对图像进行滤波:
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('test.jpg')
kernel = np.ones((5,5),np.float32)/25
dst = cv2.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()
2. 图像模糊(平滑)
图像模糊是通过一个低通道卷积核对图像滤波来实现的,对消除图像噪点有很好的作用。此操作实际上是删除了图像中的高频内容(例如:噪声、边缘),因此边缘会有点模糊(有一些模糊技术也不会模糊边缘)。OpenCV主要提供了四种类型的模糊技术。
2.1 均值模糊
均值模糊是通过使用标准化的箱式过滤器对图像滤波实现的。它只取内核区域下所有像素的平均值,并替换中心元素,通过函数cv2.fuzzy()或cv2.boxFilter()提供此功能。一个3x3的标准箱式过滤器如下所示:
void cv::blur (
InputArray src,
OutputArray dst,
Size ksize,
Point anchor = Point(-1,-1),
int borderType = BORDER_DEFAULT
)
与cv::blur相比,cv::boxFilter不一定要使用标准化的箱式过滤器,其计算结果也可以用于一些其它的计算
void cv::boxFilter
(
InputArray src,
OutputArray dst,
int ddepth,
Size ksize,
Point anchor = Point(-1,-1),
bool normalize = true,
int borderType = BORDER_DEFAULT
)
示例代码:
blur = cv2.blur(img, (5, 5))
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(blur), plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
2.2. 高斯模糊
cv2.GaussianBlur(),使用高斯核来代替箱形滤波器,指定内核的宽度和高度来执行滤波,这些宽度和高度应该是正的奇数。还可以分别指定X和Y方向、SigmaX和SigmaY方向的标准差。如果仅指定SigmaX,SigmaY将被视为与SigmaX相同。如果两者都以零的形式给出,则它们根据内核大小计算。高斯模糊是去除图像中噪点的有效方法。
void cv::GaussianBlur (
InputArray src,
OutputArray dst,
Size ksize,
double sigmaX,
double sigmaY = 0,
int borderType = BORDER_DEFAULT
)
如果不想用cv::GaussianBlur函数,也可以自己通过参数来 构造一个高斯卷积核
Mat cv::getGaussianKernel (
int ksize,
double sigma,
int ktype = CV_64F
)
高斯模糊示例代码:
dst = cv2.GaussianBlur(img,(5,5),0)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('GaussianBlur')
plt.xticks([]), plt.yticks([])
plt.show()
2.3 中值模糊
中值模糊取内核区域下所有像素的中间值来替代中心元素的值,对去除椒盐噪声非常有效。在前面的滤镜中,中心元素是一个新计算的值,而在中值模糊中,图像中的中心元素总是被某个像素值所替代,有效地降低了噪声。它的内核大小应该是一个正的奇数。
void cv::medianBlur (
InputArray src,
OutputArray dst,
int ksize
)
示例代码:
img = cv2.imread('test2.jpg')
dst = cv2.medianBlur(img,5)
plt.subplot(121), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(dst), plt.title('Median')
plt.xticks([]), plt.yticks([])
plt.show()
2.4 双边滤波
cv::bilateralFilter()函数在有效去除噪点的同时,保持边缘的锐利。但与其他过滤器相比,操作速度较慢。高斯滤波器取像素周围的像素,并求出其高斯加权平均值。这种高斯滤波器是空间的函数,在滤波时要考虑附近的像素。它不考虑像素是否具有几乎相同的亮度,也不考虑像素是否是边缘像素。所以它也模糊了边缘,这是我们不想做的。
双边滤波器在空间上也采用高斯滤波器,但多一个作用域像素亮度上的高斯滤波器。空间上高斯函数保证只邻近像素点,而亮度上的高斯函数只考虑与中心像素点相似的像素点。因此,它保留了边缘,因为边缘部分的像素将有很大的亮度变化。
void cv::bilateralFilter (
InputArray src,
OutputArray dst,
int d,
double sigmaColor,
double sigmaSpace,
int borderType = BORDER_DEFAULT
)
示例代码:
img = cv2.imread('test3.jpg')
dst = cv2.bilateralFilter(img,9,100,100)
dst2 = cv2.GaussianBlur(img, (5, 5), 0)
plt.subplot(131), plt.imshow(img), plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(132), plt.imshow(dst2), plt.title('GaussianBlur')
plt.xticks([]), plt.yticks([])
plt.subplot(133), plt.imshow(dst), plt.title('Bilateral')
plt.xticks([]), plt.yticks([])
plt.show()
可以看到与高斯模糊相比,双边滤波去除了一定的噪点,且边缘细节保存比较完好
本文链接:https://www.zoucz.com/blog/2019/03/08/0856c5e0-417e-11e9-9947-3d7b79f522a2/