OpenCV-Python学习(九):图像滤波

目录:

  • 1.滤波的相关概念
  • 2.卷积操作
  • 3.平滑操作(低通滤波)
    • 均值滤波
    • 中值滤波
    • 高斯滤波
    • 双边滤波
  • 4.锐化操作(高通滤波)
    • 自定义锐化核
    • USM锐化(UnsharpMask)
  • 5.梯度操作(高通滤波)
    • Sobel算子
    • Scharr算子
    • Laplacian算子

一、滤波的概念

滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。

图像滤波是图像预处理中不可缺少的操作,其处理效果的好坏将直接影响到后续图像处理和分析的有效性和可靠性。图像滤波,即在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制。图像滤波的目的:

  • 1.消除图像中混入的噪声;
  • 2.为图像识别抽取出图像特征。

滤波可分为 低通滤波、高通滤波、中通滤波、阻带滤波。

  • 低通滤波/平滑滤波:减弱或阻隔高频信号,保留低频信号。可使图像变模糊,主要用于去噪。
  • 高通滤波:减弱或阻隔低频信号,保留高频信号。一般用于获取图像边缘、轮廓或梯度。
  • 中通滤波:获取已知频率范围内的信号。
  • 阻带滤波:去掉已知频率范围内的信号。

二、卷积操作

图像的滤波操作一般用卷积操作来实现,卷积核一般称为滤波器。

卷积操作:图像卷积可以看成是一个滑动的窗口(卷积核)在一个比它大的图像上有规则(从左向右,从上往下)地滑动,对每一次窗口覆盖到的图像子区域都会进行点乘操作,并将得到的值作为原图中被窗口覆盖区域的中心像素点的新值。

与CNN里的卷积不同,经典的卷积算子(即卷积核)往往是人们根据研究和经验事先设定好的特征提取算子,而CNN里的卷积核是通过训练不断调整最终得到合适的权值参数。

函数:

1.卷积操作
  filter2D(src, ddepth, kernel, dst=None, anchor=None, delta=None, borderType=None)
  参数:
  ddepth:图像深度。ddepth=-1表示目标图像与原始图像使用相同的图像深度

示例:

import cv2
import numpy

img = cv2.imread("image/1.jpg")
# 1.定义一个卷积核
kernel = numpy.float32([[1, 1, 0], [1, 0, -1], [0, -1, -1]])
# 2.卷积操作
dst = cv2.filter2D(img, -1, kernel)

cv2.imshow("iamge", img)
cv2.imshow("dst", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:

三、平滑操作(低通滤波)

函数:

2.平滑操作(低通滤波)
  1)均值滤波:blur(src, ksize)
  2)中值滤波:medianBlur(src, ksize),ksize为大于1的奇数
    中值滤波一般用于处理椒盐噪声。
  3)高斯滤波:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
    ksize为奇数,
    sigmaX是高斯函数在x轴方向上的标准差。
    sigmaY是高斯函数在y轴方向上的标准差。若不指定sigmaY,则sigmaY=sigmaX。
  4)双边滤波:bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
    d是每个像素的领域直径,
    sigmaColor:在颜色空间中的过滤sigma。
    sigmaSpace:在坐标系空间中的过滤sigma。

    sigma为无穷大时,效果等价于高斯模糊。sigma为0时,与原图一样。

高斯滤波和双边滤波的区别:
1)高斯核只考虑了空间分布,没有考虑到像素值的差异,会将图像的边缘模糊掉。
2)双边滤波是基于高斯滤波提出的,结合了图像的空间邻近度和像素值相似度的一种折衷处理,具有保边特性。

示例:

import cv2

img1 = cv2.imread("image/5.jpg")
img2 = cv2.imread("image/25.jpg")

# 1.均值滤波: blur(src, ksize, dst=None, anchor=None, borderType=None)
mean = cv2.blur(img1, ksize=(5, 5))
# 2.中值滤波: medianBlur(src, ksize, dst=None) ksize为大于1的奇数
median = cv2.medianBlur(img1, ksize=7)
# 3.高斯滤波: GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
# ksize为奇数
# sigmaX是高斯函数在x轴方向上的标准差。若不指定sigmaY,则sigmaY=sigmaX。
gaussian = cv2.GaussianBlur(img2, ksize=(7, 7), sigmaX=6, sigmaY=6)
# 4.双边滤波: bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
# d是每个像素的领域直径
# sigmaColor:在颜色空间中的过滤sigma。sigmaSpace:在坐标系空间中的过滤sigma。
# sigma为无穷大时,效果等价于高斯模糊。sigma为0时,与原图一样。
bilateral = cv2.bilateralFilter(img2, 9, 75, 75)
# bilateral = cv2.bilateralFilter(img2, 9, 0, 0)

cv2.imshow("img1", img1)
cv2.imshow("mean", mean)
cv2.imshow("median", median)
cv2.imshow("img2", img2)
cv2.imshow("gaussian", gaussian)
cv2.imshow("bilateral", bilateral)
cv2.waitKey(0)
cv2.destroyWindow()

结果如下:

四、锐化操作(高通滤波)

示例:

import cv2
import numpy

src = cv2.imread("image/1.jpg")

# 1.自定义锐化核
kernel = numpy.float32([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])
dst1 = cv2.filter2D(src, -1, kernel)
# 2.USM锐化(UnsharpMask)
gaussian = cv2.GaussianBlur(src, (5, 5), 6)
dst2 = cv2.addWeighted(src, 2, gaussian, -1, 0)

cv2.imshow("src", src)
cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)
cv2.waitKey(0)
cv2.destroyWindow()

结果如下:

五、梯度操作(高通滤波)

梯度算子有 Sobel、Scharr 和 Laplacian算子。
Sobel 和 Scharr 其实就是求一阶或二阶导数。Scharr 是对 Sobel(使用小的卷积核求解求解梯度角度时)的优化。而Laplacian 是求二阶导数。
Sobel 算子是高斯平滑与微分操作的结合体,所以它的抗噪声能力很好。
Scharr 滤波器是对Sobel滤波器的改进版本。

函数:

4.梯度操作(高通滤波)
  1)Sobel算子
    Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None)
    dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
  2)Scharr算子
    Scharr(src, ddepth, dx, dy, dst=None, scale=None, delta=None, borderType=None)
    dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
  3)Laplacian算子
    Laplacian(src, ddepth, dst=None, ksize=None, scale=None, delta=None, borderType=None)

示例:

import cv2
import matplotlib.pyplot as plt

gray = cv2.imread("image/2.jpg", cv2.IMREAD_GRAYSCALE)

# 1.Sobel算子: dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
sobel_x = cv2.Sobel(gray, -1, dx=1, dy=0)  # x轴方向上的一阶导数
sobel_y = cv2.Sobel(gray, -1, dx=0, dy=1)  # y轴方向上的一阶导数
sobel_x_abs = cv2.convertScaleAbs(sobel_x)
sobel_y_abs = cv2.convertScaleAbs(sobel_y)
sobel = cv2.addWeighted(sobel_x, 0.5, sobel_y, 0.5, 0)  # 近似有|G|=|Gx|+|Gy|
# 2.Scharr算子: dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
scharr_x = cv2.Scharr(gray, -1, dx=1, dy=0)  # x轴方向上的一阶导数
scharr_y = cv2.Scharr(gray, -1, dx=0, dy=1)  # y轴方向上的一阶导数
scharr_x_abs = cv2.convertScaleAbs(scharr_x)
scharr_y_abs = cv2.convertScaleAbs(scharr_y)
scharr = cv2.addWeighted(scharr_x_abs, 0.5, scharr_y_abs, 0.5, 0)  # 近似有|G|=|Gx|+|Gy|
# 近似有|G|=|Gx|+|Gy|
# 3.Laplacian算子
laplacian = cv2.Laplacian(gray, -1)

# 结合matplotlib显示多张图片
titles = ['Original Gray', 'Sobel x', 'Sobel y', 'Sobel', 'Scharr x', 'Scharr y', 'Scharr', 'Laplacian']
images = [gray, sobel_x, sobel_y, sobel, scharr_x, scharr_y, scharr, laplacian]
for i in range(8):
    plt.subplot(2, 4, i + 1)
    plt.imshow(images[i], cmap="gray")
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

结果如下:

你可能感兴趣的:(OpenCV-Python学习(九):图像滤波)