Python3+OpenCV(七):空间域滤波增强


    • 1、空间域平滑滤波
      • (1) 均值滤波器
      • (2) 高斯滤波器
    • 2、空间域锐化滤波
      • (1) 梯度锐化法
        • Roberts算子
        • Prewitt算子
        • Sobel算子
      • (2) Laplacian算子


1、空间域平滑滤波

任何一幅原始图像,在其获取和传输等过程中,会受到各种噪声的干扰,使图像模糊,对图像分析不利。为了抑制噪声,改善图像质量所进行的处理称图像平滑或去噪。

(1) 均值滤波器

均值滤波(normalized box filter)就是用其像素点周围像素的平均值代替元像素值,在滤除噪声的同时也会滤掉图像的边缘信息的方法。

但均值滤波本身存在着固有的缺陷,即它不能很好地保护图像细节,在图像去噪的同时也破坏了图像的细节部分,从而使图像变得模糊,不能很好地去除噪声点。特别是椒盐噪声。

cv2.blur(src, ksize, dst=None, anchor=None, borderType=None)

该函数使用内核将图像平滑化,表示为:
Python3+OpenCV(七):空间域滤波增强_第1张图片
作用:使用归一化卷积模板模糊图像
src:图像矩阵
ksize:滤波窗口(算子)尺寸
anchor:锚点
borderType:边界扩充类型

import cv2
import numpy as np
import matplotlib.pyplot as plt

# 均值滤波器
# 读取灰度图像 
img = cv2.imread("D:/Study/digital image processing/test/saltLena.bmp",0)
# 模板大虚5*5
blur = cv2.blur(img,(5,5))
plt.subplot(121),plt.imshow(img,'gray')
plt.subplot(122),plt.imshow(blur,'gray')
plt.show()

Python3+OpenCV(七):空间域滤波增强_第2张图片

(2) 高斯滤波器

高斯滤波是一种线性平滑滤波器,对于服从正态分布的噪声有很好的抑制作用。在实际场景中,我们通常会假定图像包含的噪声为高斯白噪声,所以在许多实际应用的预处理部分,都会采用高斯滤波抑制噪声,如传统车牌识别等。

高斯滤波和均值滤波一样,都是利用一个掩膜和图像进行卷积求解。不同之处在于:均值滤波器的模板系数都是相同的为1,而高斯滤波器的模板系数,则随着距离模板中心的增大而系数减小(服从二维高斯分布)。所以,高斯滤波器相比于均值滤波器对图像个模糊程度较小,更能够保持图像的整体细节。

高斯滤波常见模板如下。
Python3+OpenCV(七):空间域滤波增强_第3张图片
Python3+OpenCV(七):空间域滤波增强_第4张图片

cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

作用:根据像素距离使用高斯函数生成权重进行滤波
dst:输出图像
src:输入图像
ksize:卷积核的大小
sigmaX:x方向上的标准差
sigmaY:y方向上的标准差
borderType:边界模式,默认为BORDER_DEFAULT

# 高斯滤波器
img = cv2.imread("D:/Study/digital image processing/test/saltLena.bmp",0)
# 若只给了一个sigma则同时视为两轴的sigma,若均为0则根据尺寸自动生成。
dst = cv2.GaussianBlur(img,(5,5),0)

plt.subplot(121),plt.imshow(img,'gray')
plt.subplot(122),plt.imshow(dst,'gray')
plt.show()

Python3+OpenCV(七):空间域滤波增强_第5张图片
图像平滑通过积分过程使得图像边缘模糊,图像锐化则通过微分使得图像边缘突出、清晰。

2、空间域锐化滤波

锐化处理的主要目的是为了突出图像的边缘信息,增强图像的轮廓特征,以便于人眼的观察和机器的识别。

(1) 梯度锐化法

梯度的定义如下:
在这里插入图片描述
其中:
Python3+OpenCV(七):空间域滤波增强_第6张图片
梯度的方向就是函数f(x,y)最大变化率的方向。梯度的幅值作为最大变化率大小的度量。
在这里插入图片描述
离散的二维函数f(i,j),可以用有限差分作为梯度的一个近似值。
在这里插入图片描述
为了简化计算,可以用绝对值来近似。
在这里插入图片描述

Roberts算子

采用对角相差的差分法来代替微分,其计算公式如下所示。
在这里插入图片描述在这里插入图片描述

cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]])

作用:实现边缘提取
src:输入图像
dst:输出的边缘图,其大小和通道数与输入图像相同
ddepth:目标图像所需的深度
kernel:卷积核,一个单通道浮点型矩阵
anchor:内核的基准点,其默认值为(-1,-1),位于中心位置
delta:在储存目标图像前可选的添加到像素的值,默认值为0
borderType:边框模式

cv2.convertScaleAbs(src[, dst[, alpha[, beta]]])

作用:返回uint8类型的图片
可选参数alpha是伸缩系数,beta是加到结果上的一个值。

# Roberts算子
# 读取图像
img = cv2.imread("D:/Study/digital image processing/test/LenaRGB.bmp")
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
# 灰度化处理
grayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# Roberts算子
kernelx = np.array([[-1, 0],[0, 1]],dtype=int)
kernely = np.array([[0, -1],[1, 0]],dtype=int)

# 对图像求导后,结果有正有负,且有可能超出255,所以求梯度时要注意像素的数值类型
# 求梯度时将像素的数值类型转换为cv2.CV_16S来存放可能超出范围的结果
# cv2.CV_16S,16位有符号的数据类型,以防止截断
x = cv2.filter2D(grayImage,cv2.CV_16S,kernelx)
y = cv2.filter2D(grayImage,cv2.CV_16S,kernely)
# 用convertScaleAbs()函数将其转为uint8形式,否则将无法显示图像,而只是一副灰色的窗口
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Roberts = cv2.addWeighted(absX,0.5,absY,0.5,0) # 图像融合

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示图形
titles = [u'原始图像', u'Roberts算子']
images = [lenna_img, Roberts]
for i in xrange(2):
    plt.subplot(1,2,i+1), plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

Python3+OpenCV(七):空间域滤波增强_第7张图片

Prewitt算子

Prewitt是一种图像边缘检测的微分算子,其原理是利用特定区域内像素值产生的差分实现边缘检测。

由于Prewitt算子采用3x3模型对区域内的像素值进行计算,而Robert算子的模板为2x2,故Prewitt算子的边缘检测结果在水平/垂直方向均比Robert算子更加明显。Prewitt算子适合用来识别噪声较多,灰度渐变的图像。

Prewitt算子的实现过程与Roberts算子比较相似。通过Numpy定义模板,再调用OpenCV的 filter2D() 函数实现对图像的卷积运算,最终通过convertScaleAbs()addWeighted() 函数实现边缘提取。

其计算公式如下所示。
Python3+OpenCV(七):空间域滤波增强_第8张图片

# Prewitt算子
# 读取图像
img = cv2.imread("D:/Study/digital image processing/test/LenaRGB.bmp")
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Prewitt算子
kernelx = np.array([[1,1,1],[0,0,0],[-1,-1,-1]], dtype=int)
kernely = np.array([[-1,0,1],[-1,0,1],[-1,0,1]], dtype=int)
x = cv2.filter2D(grayImage, cv2.CV_16S, kernelx)
y = cv2.filter2D(grayImage, cv2.CV_16S, kernely)
# 转uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
imgPrewitt = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示图形
titles = [u'原始图像', u'Prewitt算子']
images = [lenna_img,imgPrewitt]
for i in xrange(2):
    plt.subplot(1,2,i + 1), plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Prewitt算子图像锐化提取的边缘轮廓,其效果图比Robert算子的更加明显。
Python3+OpenCV(七):空间域滤波增强_第9张图片

Sobel算子

Sobel算子是一种用于边缘检测的离散的离散微分算子,它结合了高斯平滑和微分求导。该算子用于计算图像明暗程度近似值,根据图像边缘化旁边明暗程度把该区域内超过某个数的特定点记为边缘。

Sobel算子在Prewitt算子的基础上增加了权重的概念,认为 相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大 ,从而实现图像锐化并突出边缘轮廓。

Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。

Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])

src:输入图像
dst:输出的边缘图,其大小和通道数与输入图像相同
ddepth:目标图像所需的深度,针对不同的输入图像,输出目标图像有不同的深度
dx:x方向上的差分阶数,取值1或0
dy:y方向上的差分阶数,取值1或0
ksize:Sobel算子的大小,其值必须是正数和奇数
scale:缩放导数的比例常数,默认情况下没有伸缩系数
delta:将结果存入目标图像之前,添加到结果中的可选增量值

# Sobel算子
# 读取图像
img = cv2.imread("D:/Study/digital image processing/test/LenaRGB.bmp")
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

x = cv2.Sobel(grayImage,cv2.CV_16S,1,0)
y = cv2.Sobel(grayImage,cv2.CV_16S,0,1)
# 转uint8
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
imgSobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示图形
titles = [u'原始图像', u'Sobel算子']
images = [lenna_img, imgSobel]
for i in xrange(2):
    plt.subplot(1,2,i + 1), plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Python3+OpenCV(七):空间域滤波增强_第10张图片

(2) Laplacian算子

拉普拉斯(Laplacian)算子是n维欧几里德空间中的一个二阶微分算子,常用于图像增强领域和边缘提取。

它通过灰度差分计算邻域内的像素.基本流程是:判断图像中心像素灰度值与它周围其他像素的灰度值,如果中心像素的灰度更高,则提升中心像素的灰度;反之降低中心像素的灰度,从而实现图像锐化操作。

在算法实现过程中,Laplacian算子通过对邻域中心像素的四方向或八方向求梯度,再将梯度相加起来判断中心像素灰度与邻域内其他像素灰度的关系,最后通过梯度运算的结果对像素灰度进行调整。

Laplacian算子分为四邻域和八邻域,四邻域是对邻域中心像素的四方向求梯度,八邻域是对八方向求梯度。

四邻域模板如公式所示。
Python3+OpenCV(七):空间域滤波增强_第11张图片
Laplacian算子的八邻域模板如下。
Python3+OpenCV(七):空间域滤波增强_第12张图片

cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])

src:输入图像
dst:输出的边缘图,其大小和通道数与输入图像相同
ddepth:目标图像所需的深度
ksize:用于计算二阶导数的滤波器的孔径大小,其值必须是正数和奇数,且默认值为1
scale:计算拉普拉斯算子值的可选比例因子。默认值为1
delta:将结果存入目标图像之前,添加到结果中的可选增量值,默认值为0
borderType:边框模式

# Laplacian算子
# 读取图像
img = cv2.imread("D:/Study/digital image processing/test/LenaRGB.bmp")
lenna_img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
# 灰度化处理图像
grayImage = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 拉普拉斯算法
# ksize=1时,Laplacian()函数采用3×3的孔径(四邻域模板)进行变换处理
dst = cv2.Laplacian(grayImage,cv2.CV_16S,ksize=3)
Laplacian = cv2.convertScaleAbs(dst)

# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示图形
titles = [u'原始图像', u'Laplacian算子']
images = [lenna_img,Laplacian]
for i in xrange(2):
    plt.subplot(1,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

Python3+OpenCV(七):空间域滤波增强_第13张图片

参考博客
https://blog.csdn.net/my_kun/article/details/105798956
https://www.cnblogs.com/laumians-notes/p/8692888.html
https://www.cnblogs.com/zhouzetian/p/13324627.html
https://bbs.huaweicloud.com/blogs/145887

你可能感兴趣的:(OpenCV,计算机视觉,opencv)