Practical Python and OpenCV,3rd Edition 11
smoothing and blurring
我很确定我们都知道模糊是什么。当您的相机拍摄失焦时会发生这种情况。图像中较清晰的区域会丢失其细节,通常为圆盘/圆形。
实际上,这意味着图像中的每个像素与其周围的像素强度混合在一起。邻域中像素的这种“混合”成为我们模糊的像素。
虽然这种效果在我们的照片中通常是不受欢迎的,但在执行图像处理任务时它实际上非常有用。
新建一个blurring.py文件
averaging
我们要探索的第一个模糊方法是平均。
顾名思义,我们将在图像顶部定义一个k×k滑动窗口,其中k始终为奇数。此窗口将从左到右,从上到下滑动。然后将该矩阵中心的像素(我们必须使用奇数,否则不会有真正的“中心”)设置为围绕它的所有其他像素的平均值。
我们将此滑动窗口称为“卷积内核”或仅称为“内核”。我们将在本章中继续使用这个术语。
正如我们将看到的,随着内核大小的增加,我们的图像变得越模糊。
# Let's apply standard "averaging" blurring first. Average
# blurring (as the name suggests), takes the average of all
# pixels in the surrounding area and replaces the centeral
# element of the output image with the average. Thus, in
# order to have a central element, the area surrounding the
# central must be odd. Here are a few examples with varying
# kernel sizes. Notice how the larger the kernel gets, the
# more blurred the image becomes
blurred = np.hstack([
cv2.blur(image,(3,3)),
cv2.blur(image,(5,5)),
cv2.blur(image,(7,7))
])
cv2.imshow("Averaged",blurred)
cv2.waitKey(0)


使用3×3内核(左),5×5内核(中)和7×7内核(右)执行平均模糊
为了平均模糊图像,我们使用cv2.blur函数。此函数需要两个参数:我们想要模糊的图像和内核的大小。我们使用不同大小的内核来模糊我们的图像。我们的内核越大,我们的图像就越模糊
我们使用np.hstack函数将输出图像堆叠在一起。此方法将我们的三个图像“水平堆叠”成一行。这很有用,因为我们不想使用cv2.imshow函数创建三个单独的窗口。
Gaussian
接下来,我们将回顾高斯模糊。高斯模糊类似于平均模糊,但是我们现在使用加权平均值而不是使用简单均值,其中更接近中心像素的邻域像素对平均值贡献更多“权重”。
最终结果是我们的图像比使用上一节中讨论的平均方法更少模糊,但更自然地模糊。
继续前面的blurring.py编写
# We can also apply Gaussian blurring, where the relevant
# parameters are the image we want to blur and the standard
# deviation in the X and Y direction. Again, as the standard
# deviation size increases, the image becomes progressively
# more blurred
blurred = np.hstack([
cv2.GaussianBlur(image,(3,3),0),
cv2.GaussianBlur(image,(5,5),0),
cv2.GaussianBlur(image,(7,7),0)
])
cv2.imshow("Gaussian",blurred)
cv2.waitKey(0)
显示结果:

在这里你可以看到我们正在使用cv2.GaussianBlur函数。函数的第一个参数是我们想要模糊的图像。然后,类似于cv2.blur,我们提供一个表示内核大小的元组。同样,我们从3×3的小内核开始,并开始增加它到7x7。
最后一个参数是我们的σ,即x轴方向的标准偏差。通过将此值设置为0,我们指示OpenCV根据内核大小自动计算它们。
我们可以在上图看到高斯模糊的输出。与使用平均方法相比,我们的图像具有更少的模糊效果; 然而,由于加权平均值的计算,模糊本身更自然,而不是允许内核邻域中的所有像素具有相等的权重。
Median
传统上,中值模糊方法在去除椒盐噪声时最有效。这种类型的噪音正是它听起来的样子:想象一下拍照,把它放在餐桌上,然后在上面洒上盐和胡椒。 使用中值模糊方法,您可以从图像中删除盐和胡椒。
在应用中值模糊时,我们首先定义内核大小k。然后,如在平均模糊方法中,我们考虑大小为k×k的邻域中的所有像素。但是,与平均方法不同,我们不是用邻域的平均值替换中心像素,而是用邻域的中值替换中心像素。
中值模糊在去除图像中的盐和胡椒样式噪声方面更有效,因为每个中心像素总是被图像中存在的像素强度替换。
平均和高斯方法可以计算邻域的平均值或加权平均值——该平均像素强度可能存在于邻域中,也可能不存在。但根据定义,中间像素必须存在于我们的邻域中。通过用中值而不是平均值替换我们的中心像素,我们可以大大降低噪声。
# The cv2.medianBlur function is mainly used for removing
# what is called "salt-and-pepper" noise. Unlike the Average
# method mentioned above, the median method (as the name
# suggests), calculates the median pixel value amongst the
# surrounding area.
blurred = np.hstack([
cv2.medianBlur(image,3),
cv2.medianBlur(image,5),
cv2.medianBlur(image,7)
])
cv2.imshow("Median",blurred)
cv2.waitKey(0)
显示效果:

通过调用cv2.medianBlur函数来实现应用中值模糊。此方法有两个参数:我们想要模糊的图像和内核的大小。我们从内核大小3开始,然后将其增加到5和7。
bilateral
我们要探索的最后一种方法是双边模糊。
到目前为止,我们的模糊方法的目的是减少图像中的噪声和细节; 但是,我们往往会丢失图像中的边缘。
为了在保持边缘的同时降低噪音,我们可以使用双边模糊。双边模糊通过引入两个高斯分布来实现这一点。
第一高斯函数仅考虑空间邻居,即在图像的(x,y)坐标空间中出现在一起的像素。然后,第二高斯模型对邻域的像素强度进行建模,确保在模糊的实际计算中仅包括具有相似强度的像素。
总的来说,这种方法能够保留图像的边缘,同时还能降低噪点。这种方法的最大缺点是它比平均,高斯和中值模糊对应物慢得多。
# You may have noticed that blurring can help remove noise,
# but also makes edge less sharp. In order to keep edges
# sharp, we can use bilateral filtering. We need to specify
# the diameter of the neighborhood (as in examples above),
# along with sigma values for color and coordinate space.
# The larger these sigma values, the more pixels will be
# considered within the neighborhood.
blurred = np.hstack([
cv2.bilateralFilter(image,5,21,21),
cv2.bilateralFilter(image,7,31,31),
cv2.bilateralFilter(image,9,41,41)
])
cv2.imshow("Bilateral",blurred)
cv2.waitKey(0)
显示效果:

我们通过调用cv2.bilateralFilter函数来应用双边模糊。我们提供的第一个参数是我们想要模糊的图像。然后,我们需要定义像素邻域的直径。第三个参数是我们的颜色σ。颜色σ的值越大意味着在计算模糊时将考虑邻域中的更多颜色。最后,我们需要提供空间σ。较大的空间值σ意味着距离中心像素较远的像素将影响模糊计算,前提是它们的颜色足够相似。
用到的函数
np.hstack
cv2.blur
cv2.GaussianBlur
cv2.medianBlur
cv2.bilateralFilter
更多的参考:
Numpy中stack(),hstack(),vstack()函数详解
PPaO Chapter 8——Smoothing and Blurring
;