基于KITTI数据集的无人驾驶感知与传感器融合实现—(5)—高斯滤波
学习前言
之前弄了蛮多图像预处理的操作,但是在进行梯度和颜色域分离这种操作之前呢,我们加个滤波器,可以有效的去除一些烦人的噪声。老样子,我还是把原作者的项目连接放上面啦~ 连接.
一、高斯滤波
在图像处理中,滤波器比较常见的有均值滤波、中值滤波和高斯滤波。
- 均值滤波
图像处理中最常用的手段,简单的说就是取这个卷积核里面的平均值作为图像的值嘛。从频率域观点来看均值滤波是一种低通滤波器,高频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。
特点:易收到噪声的干扰,不能完全消除噪声,只能相对减弱噪声。 - 中值滤波
也是消除图像噪声最常见的手段之一,特别是消除椒盐噪声,中值滤波的效果要比均值滤波更好。中值滤波是跟均值滤波唯一不同是,不是用均值来替换中心每个像素,而是将周围像素和中心像素排序以后,取中值。
特点:对噪声不是那么敏感,能够较好的消除椒盐噪声,但是容易导致图像的不连续性。 - 高斯滤波
离散化窗口划船卷积时主要利用的是高斯核,高斯核的大小为奇数,因为高斯卷积会在其覆盖区域的中心输出结果。
高斯模板是通过高斯函数计算出来的,公式如下:
说得简单点,高斯滤波器的核就是符合高斯分布的一个中间值最大,然后往外值越来越小的一个卷积核。
特点:对图像进行平滑的同时,同时能够更多的保留图像的总体灰度分布特征。 正因为高斯滤波可以保留图像的总体特征所以才采用的高斯滤波器。
二、API介绍
dst = GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])
API功能:使用高斯滤镜模糊图像。该函数将源图像与指定的高斯内核进行卷积。
参数:
src: 输入图像;图像可以具有任意数量的通道,这些通道可以独立处理,但深度应为CV_8U,CV_16U,CV_16S,CV_32F或CV_64F。
ksize: (ksize.width, ksize.height) 高斯核大小。ksize.width和ksize.height可以不同,但是它们都必须为正数和奇数。或者,它们可以为零,然后根据sigma计算得出。
sigmaX: X方向上的高斯核标准偏差。
sigmaY: Y方向上的高斯核标准差;如果sigmaY为零,则将其设置为等于sigmaX;如果两个sigmas为零,则分别从ksize.width和ksize.height计算得出;为了完全控制结果,而不考虑将来可能对所有这些语义的修改,建议指定所有ksize,sigmaX和sigmaY。
borderType:像素外推方法。
返回:
dst: 高斯滤波后的输出图像。
三、代码&效果
代码先将原图进行不同参数的高斯滤波器进行滤波然后对比,在对已经滤波了的每一张图片进行Sobel算子的梯度运算后再对比一下。
import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import pickle
# 读入图片
image = mpimg.imread('test_image/test4.jpg')
# 定义Sobel函数,因为做边缘检测时只考虑梯度的大小,所以对返回结果做绝对值处理
def sobel(img, orient='x', sobel_kernel=3, sobel_thresh=(30, 100)):
# 转换为单通道灰度图,像素值做归一化
gray = cv2.cvtColor(img, cv2.COLOR_RGBA2GRAY)
# 按方向进行梯度计算
if orient == 'x':
sobel = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
if orient == 'y':
sobel = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
abs_sobel = np.absolute(sobel)
# 转换到 8-bit (0 - 255) 并转换为type = np.uint8
scaled_sobel = (abs_sobel / (np.max(abs_sobel) / 255)).astype(np.uint8)
# 根据梯度阈值,创建一个二进制掩膜
binary_output = np.zeros_like(scaled_sobel)
# 将原图中高于阈值的像素点在掩膜中的对应位置置为1
binary_output[(scaled_sobel >= sobel_thresh[0]) & (scaled_sobel <= sobel_thresh[1])] = 1
return binary_output
# 不同kernel size和标准差参数,对比差异
Blur_1 = cv2.GaussianBlur(image, ksize=(9, 9), sigmaX=0.5) # sigmaX: x方向的标准差
Blur_2 = cv2.GaussianBlur(image, ksize=(9, 9), sigmaX=2.0)
Blur_3 = cv2.GaussianBlur(image, ksize=(9, 9), sigmaX=5.0)
Blur_4 = cv2.GaussianBlur(image, ksize=(21, 21), sigmaX=5.0)
# 高斯滤波后再进行sobel效果
sobel_origin = sobel(image)
sobel_1 = sobel(Blur_1)
sobel_2 = sobel(Blur_2)
sobel_3 = sobel(Blur_3)
sobel_4 = sobel(Blur_4)
# 可视化结果
f, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(5, 2, figsize=(24, 24))
f.tight_layout()
ax1[0].imshow(image)
ax1[0].set_title('Original Image', fontsize=15)
ax1[1].imshow(sobel_origin, cmap='gray')
ax1[1].set_title('Sobel Original', fontsize=15)
ax2[0].imshow(Blur_1)
ax2[0].set_title('GaussianBlur with ksize=(9,9) sigmaX=0.5', fontsize=15)
ax2[1].imshow(sobel_1, cmap='gray')
ax2[1].set_title('Sobel with ksize=(9,9) sigmaX=0.5', fontsize=15)
ax3[0].imshow(Blur_2)
ax3[0].set_title('GaussianBlur with ksize=(9,9) sigmaX=2.0', fontsize=15)
ax3[1].imshow(sobel_2, cmap='gray')
ax3[1].set_title('Sobel with ksize=(9,9) sigmaX=2.0', fontsize=15)
ax4[0].imshow(Blur_3)
ax4[0].set_title('GaussianBlur with ksize=(9,9) sigmaX=5.0', fontsize=15)
ax4[1].imshow(sobel_3, cmap='gray')
ax4[1].set_title('Sobel with ksize=(9,9) sigmaX=5.0', fontsize=15)
ax5[0].imshow(Blur_4)
ax5[0].set_title('GaussianBlur with ksize=(21,21) sigmaX=5.0', fontsize=15)
ax5[1].imshow(sobel_4, cmap='gray')
ax5[1].set_title('Sobel with ksize=(21,21) sigmaX=5.0', fontsize=15)
plt.subplots_adjust(left=0., right=1., top=0.9, wspace = 0., bottom=0.1, hspace=0.6)
plt.show()
四、结论
可以看到,高斯滤波标准差sigma越大意味着分布越宽,图片进过处理后也越模糊,再进行梯度计算后可以过滤掉更多无关特征,留下比较明显的特征(比如说车道线)。另外,如果增加卷积核,同样可以起到在更大范围内模糊并降噪的效果。