Smoothing Images
Goals
Learn to:
- Blur images with various low pass filters
- Apply custom-made filters to images (2D convolution)
学习:
- 用各种低通滤波器处理模糊图像
- 应用定制滤波器处理图像(2D卷积)
2D Convolution ( Image Filtering )
As in one-dimensional signals, images also can be filtered with various low-pass filters (LPF), high-pass filters (HPF), etc. LPF helps in removing noise, blurring images, etc. HPF filters help in finding edges in images.
OpenCV provides a function cv.filter2D() to convolve a kernel with an image. As an example, we will try an averaging filter on an image. A 5x5 averaging filter kernel will look like the below:
K=125????????1111111111111111111111111????????
The operation works like this: keep this kernel above a pixel, add all the 25 pixels below this kernel, take the average, and replace the central pixel with the new average value. This operation is continued for all the pixels in the image. Try this code and check the result:
和一维信号一样,图片也可以用各种低通滤波器(LPF),高通滤波器(HPF)来滤波。例如,LPF帮助去除噪声,模糊图片等等。HPF帮助找到图片的边缘。
OpenCV提供一个函数cv.filter2D()来卷积图片和内核。例如,我们将在一张图片上尝试均值滤波。一个5x5的均值滤波内核将如下:
操作如此:保持内核在一个像素之上,添加所有25个低于内核的像素,取均值,用新值代替中心像素。该操作在对图像的所有像素继续进行。试一试这段代码,检查结果:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('opencv_logo.png')
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()
Result:
Image Blurring (Image Smoothing)图像模糊(图像平滑)
Image blurring is achieved by convolving the image with a low-pass filter kernel. It is useful for removing noise. It actually removes high frequency content (eg: noise, edges) from the image. So edges are blurred a little bit in this operation (there are also blurring techniques which don’t blur the edges). OpenCV provides four main types of blurring techniques.
图像模糊是通过将图像和一个低通滤波器内核卷积来实现。它对于噪声消除很有用。它实际上从图片移除了高频部分(例如,噪声,边缘)。所以边缘在该操作变模糊了一点(也有不模糊边缘的模糊技术)。OpenCV提供了四种主要类型的模糊技术。
1. Averaging
This is done by convolving an image with a normalized box filter. It simply takes the average of all the pixels under the kernel area and replaces the central element. This is done by the function cv.blur() or cv.boxFilter(). Check the docs for more details about the kernel. We should specify the width and height of the kernel. A 3x3 normalized box filter would look like the below:
这是通过图像和归一化框滤镜卷积而得的。它简单的取内核下的所有像素的平均值并代替中心元素。这是通过函数cv.blur()或cv.boxFilter()来完成的档。查阅文档获得更多关于内核的细节。我们应该指定内核的宽度和高度。一个3x3的归一化框滤镜如下所示:
K=19???111111111???
-
Note
If you don’t want to use a normalized box filter, use cv.boxFilter(). Pass an argument normalize=False to the function.
Check a sample demo below with a kernel of 5x5 size:
-
笔记
如果你不想用归一化框滤镜,使用cv.boxFilter()。传递参数
normalize = False
给函数。请看下面用5x5内核的一个简单例子:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread("opencv-logo-white.png")
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([])
olt.show()
Result:
2. Gaussian Blurring高斯模糊
In this method, instead of a box filter, a Gaussian kernel is used. It is done with the function, cv.GaussianBlur(). We should specify the width and height of the kernel which should be positive and odd. We also should specify the standard deviation in the X and Y directions, sigmaX and sigmaY respectively. If only sigmaX is specified, sigmaY is taken as the same as sigmaX. If both are given as zeros, they are calculated from the kernel size. Gaussian blurring is highly effective in removing Gaussian noise from an image.
If you want, you can create a Gaussian kernel with the function, cv.getGaussianKernel().
The above code can be modified for Gaussian blurring:
在这个方法中,代替盒式滤波器,高斯内核被使用。是用函数cv.GaussianBlur()实现的。我们应该指定内核的宽度和高度,并且是正数和奇数。我们还要指定x和y方向上的标准方差,分别为sigmaX and sigmaY 。如果只有sigmaX 被指定,sigmaY将取与sigmaX一样。如果两个都为0,则根据内核的大小进行计算。在去除图片的高斯噪声上,高斯模糊非常有效。
用函数cv.getGaussianKernel()创建高斯内核。
可修改下列代码来实现高斯模糊:
blur = cv.GaussianBlur(img,(5,5),0)
3. Median Blurring中位模糊
Here, the function cv.medianBlur() takes the median of all the pixels under the kernel area and the central element is replaced with this median value. This is highly effective against salt-and-pepper noise in an image. Interestingly, in the above filters, the central element is a newly calculated value which may be a pixel value in the image or a new value. But in median blurring, the central element is always replaced by some pixel value in the image. It reduces the noise effectively. Its kernel size should be a positive odd integer.
In this demo, I added a 50% noise to our original image and applied median blurring. Check the result:
函数cv.medianBlur()取内核下的所有像素的中值,并用该中值替代中间元素。这对去除图像中的椒盐噪声非常有用。在上述滤波器中,中间元素可能是一个像素值或者一个新的值。但是在中位模糊中,中间元素总是被图像中的一些像素值所替代。有效减少噪声。内核尺寸应该是正数和整数。
在例子中,我加了50%的噪声,应用中位模糊。
median = cv.medianBlur(img,5)
4. Bilateral Filtering双边滤波
cv.bilateralFilter() is highly effective in noise removal while keeping edges sharp. But the operation is slower compared to other filters. We already saw that a Gaussian filter takes the neighbourhood around the pixel and finds its Gaussian weighted average. This Gaussian filter is a function of space alone, that is, nearby pixels are considered while filtering. It doesn’t consider whether pixels have almost the same intensity. It doesn’t consider whether a pixel is an edge pixel or not. So it blurs the edges also, which we don’t want to do.
Bilateral filtering also takes a Gaussian filter in space, but one more Gaussian filter which is a function of pixel difference. The Gaussian function of space makes sure that only nearby pixels are considered for blurring, while the Gaussian function of intensity difference makes sure that only those pixels with similar intensities to the central pixel are considered for blurring. So it preserves the edges since pixels at edges will have large intensity variation.
The below sample shows use of a bilateral filter (For details on arguments, visit docs).
在保持边缘锋利的同时,cv.bilateralFilter对噪声去除很有效。但是与其他滤波器比很慢一些。我们已经看见了高斯滤波器取像素的邻域并求其高斯加权平均值。高斯滤波器仅是空间函数,滤波的时候考虑周围的像素。它不考虑像素是否有相同的强度,不考虑像素是否是边缘像素。所以它也模糊了边缘,这是我们不想要的。
双边滤波也在空间上采用高斯滤波器,但是另一个高斯滤波器负责像素差异。空间上的高斯滤波器保证模糊的仅是周围的像素。强度差异上的高斯滤波器确保仅有相似强度的像素被模糊。所以保留了边缘,因为边缘像素有巨大的强度差异。
blur = cv.bilateraFilter(img,9,75,75)
See, the texture on the surface is gone, but the edges are still preserved.
表面纹理消失了,但边缘仍保留。
Additional Resources
- Details about the bilateral filtering