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



1、空间域平滑滤波

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

(1) 均值滤波器

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

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

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

该函数使用内核将图像平滑化,表示为:
在这里插入图片描述
作用:使用归一化卷积模板模糊图像
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()

在这里插入图片描述

(2) 高斯滤波器

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

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

高斯滤波常见模板如下。
在这里插入图片描述
在这里插入图片描述

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()

在这里插入图片描述
图像平滑通过积分过程使得图像边缘模糊,图像锐化则通过微分使得图像边缘突出、清晰。

2、空间域锐化滤波

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

(1) 梯度锐化法

梯度的定义如下:
在这里插入图片描述
其中:
在这里插入图片描述
梯度的方向就是函数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()

在这里插入图片描述

Prewitt算子

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

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

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

其计算公式如下所示。
在这里插入图片描述

# 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算子的更加明显。
在这里插入图片描述

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()

在这里插入图片描述

(2) Laplacian算子

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

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

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

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

四邻域模板如公式所示。
在这里插入图片描述
Laplacian算子的八邻域模板如下。
在这里插入图片描述

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()

在这里插入图片描述

参考博客
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

  • 6
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV中,我们可以使用一系列函数对图像进行空间增强。下面列出了一些常用的函数和它们的作用: 1. cv2.cvtColor():将图像从一种颜色空间转换为另一种颜色空间。 2. cv2.threshold():对图像进行二值化处理,将像素值大于阈值的设置为白色,其余的设置为黑色。 3. cv2.blur():对图像进行平滑处理,可以去除噪声。 4. cv2.medianBlur():对图像进行中值滤波,可以去除椒盐噪声。 5. cv2.equalizeHist():对图像进行直方图均衡化,可以增强图像的对比度。 6. cv2.Laplacian():对图像进行拉普拉斯变换,可以增强边缘。 7. cv2.Sobel():对图像进行Sobel变换,可以增强边缘。 下面是一个示例代码,演示了如何使用这些函数对图像进行增强: ``` python import cv2 img = cv2.imread('image.jpg') # 转换为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化处理 ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) # 平滑处理 blur = cv2.blur(thresh, (5, 5)) # 直方图均衡化 equ = cv2.equalizeHist(blur) # 拉普拉斯变换 laplacian = cv2.Laplacian(equ, cv2.CV_64F) # Sobel变换 sobelx = cv2.Sobel(equ, cv2.CV_64F, 1, 0, ksize=5) sobely = cv2.Sobel(equ, cv2.CV_64F, 0, 1, ksize=5) cv2.imshow('image', img) cv2.imshow('gray', gray) cv2.imshow('thresh', thresh) cv2.imshow('blur', blur) cv2.imshow('equ', equ) cv2.imshow('laplacian', laplacian) cv2.imshow('sobelx', sobelx) cv2.imshow('sobely', sobely) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个示例中,我们首先读入了一张图片,然后将其转换为灰度图像。接着,我们使用cv2.threshold()函数对图像进行二值化处理,然后使用cv2.blur()函数对图像进行平滑处理。接下来,我们使用cv2.equalizeHist()函数对图像进行直方图均衡化,然后分别使用cv2.Laplacian()和cv2.Sobel()函数对图像进行拉普拉斯变换和Sobel变换。最后,我们使用cv2.imshow()函数将处理后的图像显示出来。 当然,这只是一个简单的示例。在实际应用中,我们可能需要根据具体情况选择不同的函数和参数,以达到最好的效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值