python OpenCV学习笔记(十一):平滑图像

官方文档 – https://docs.opencv.org/3.4.0/d4/d13/tutorial_py_filtering.html


2D卷积(图像滤波)

在一维信号,图像也可以过滤各种低通滤波器(LPF),高通滤波器(高通滤波器)。LPF有助于消除噪音,模糊图像等。HPF过滤器有助于在图像中找到边缘。
OpenCV提供了一个函数cv.filter2D()来使用一个图像来对一个内核进行卷积。
作为一个例子,我们将在图像上尝试一个平均的过滤器。一个5x5的平均过滤内核看起来如下:
python OpenCV学习笔记(十一):平滑图像_第1张图片
操作是这样的:将这个内核保持在一个像素之上,在这个内核下面添加所有25个像素点,取其平均值,然后用新的平均值替换中心像素。它对图像中的所有像素进行操作。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt


img = cv.imread('opencv.jpg')

kernel = np.ones((5,5), np.float32)/25
dst = cv.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()

dst = cv.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])
ddepth:目标图像的期望深度,详见combinations;当ddepth=-1时,输出图像将具有与源相同的深度。
kernel:卷积核(或者说是一个相关的核),一个单通道的浮点矩阵;如果您想将不同的内核应用到不同的通道,将图像分割为单独的彩色平面,并分别处理它们。
anchor:锚,表示内核中过滤点的相对位置的内核的锚;锚应该在内核中;默认值(-1,-1)表示锚位于内核中心。

图像模糊(图像平滑)

通过将图像与低通滤波器内核进行卷积来实现图像模糊。它对消除噪音很有用。它实际上从图像中去除高频率的内容(如:噪音、边缘)。所以在这个操作中,边缘是模糊的。(当然,有些模糊的技术也不会模糊边缘)。OpenCV主要提供四种模糊技术。

1、均值滤波

这是通过将图像与标准化的box过滤器进行卷积来完成的。它只需要在内核区域中使用所有像素的平均值,然后替换中心元素。这是由函数cv.blur()cv.boxFilter()完成的。我们应该指定内核的宽度和高度。一个3x3的规范化框过滤器看起来如下:
这里写图片描述
ps:如果您不想使用标准化的box过滤器,请使用cv.boxFilter()。将一个参数normalize=False传递给函数。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('opencv.jpg')

blur = cv.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()

cv.blur(src, ksize[, dst[, anchor[, borderType]]])
使用标准化的box过滤器模糊图像。
ksize:模糊内核的大小这里写图片描述

cv.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]])
使用box过滤器模糊图像。
ddepth:输出图像深度
ksize:模糊内核的大小python OpenCV学习笔记(十一):平滑图像_第2张图片其中这里写图片描述
normalize:指定内核是否被它的区域标准化。
所以,blur(src, dst, ksize, anchor, borderType)boxFilter(src, dst, src.type(), anchor, true, borderType)是一样的

2、高斯模糊

在这里,使用了高斯内核,而不是使用box过滤器。它是用函数cv.GaussianBlur()完成的。我们应该指定内核的宽度和高度,应该是正的和奇数的。我们还应该分别指定X和Y方向上的标准偏差,分别是sigmaX和sigmaY。如果只指定了sigmaX,则sigmaY被认为与sigmaX一样。如果两个都是0,那么它们是根据内核大小(宽和高)计算的。高斯模糊在消除高斯噪声中非常有效。
如果需要,可以使用函数cv.getGaussianKernel()创建一个高斯内核。

blur = cv.GaussianBlur(img, (5,5), 0)

cv.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
cv.getGaussianKernel(ksize, sigma[, ktype])
ksize:孔径大小,值为≥1的奇数
sigma:高斯标准差。如果是非正数,则sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8.

3、中值模糊

cv.medianBlur()取内核区域中所有像素的中值,并且中心元素被替换成中值。这在处理椒盐噪声时非常有效。有趣的是,在上面的过滤器中,中央元素是一个新计算的值,它可能是图像中的一个像素值或一个新值。但在中间值的模糊中,中心元素总是被图像中的一些像素值所取代。它能有效地减少噪音。它的内核大小应该是一个正奇数。

median = cv.medianBlur(img, 5)

cv.medianBlur(src, ksize[, dst])
ksize:孔径线性尺寸。它一定是奇数,大于1

4、双边滤波

cv.bilateralFilter()在保持边缘锋利的同时,在消除噪音方面是非常有效的。但与其他过滤器相比,操作要慢得多。
高斯滤波器会在一个邻域附近,找到它的高斯加权平均值。高斯滤波器是一个单独的空间函数,也就是说,在过滤的时候,会考虑附近的像素。它不考虑像素是否具有同样的强度。它不考虑像素是否是一个边缘像素。所以它也模糊了边缘,这是我们不想要的。
双边滤波器也在空间中使用高斯滤波器,但一个高斯滤波器是一个像素差的函数。空间的高斯函数确保只有附近的像素被认为是模糊的,而强度差的高斯函数确保只有那些与中心像素有相似强度的像素被认为是模糊的。所以它保留了边缘,因为边缘的像素会有很大的强度变化。(大概理解,不是非常的清楚)

blur = cv.bilateralFilter(img, 9, 75, 75)

cv.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])
d:在过滤过程中使用的每个像素区域的直径。如果是非正的,则从sigmaSpace计算出来。
sigmaColor:在颜色空间中过滤sigma。参数越大,表示像素区域内更远的颜色将会混合在一起,形成一个更大的半等色区域
sigmaSpace:在坐标空间中过滤sigma。参数越大,表示只要颜色相近,更远的像素就会相互影响。当d>0时,则不考虑该参数,否则,d与sigmaSpace成比例。

你可能感兴趣的:(OpenCV)