opencv-python学习【7】图像平滑处理


图像平滑处理(Smoothing Images),也称为图像模糊处理、图像滤波(Images Filtering),就是在保留图像原有信息的情况下,过滤掉图像内部的噪声,所得到的图像称为平滑图像。例如下图左为噪声图,右图为平滑图像。
在这里插入图片描述

图像平滑处理是对图像中与周围像素点的像素值差异较大的像素点进行处理,将其调整为周围像素点像素值的近似值,而取近似值的方式有很多,主要有均值滤波方框滤波中值滤波高斯滤波双边滤波2D 卷积

一.均值滤波

1.基本原理

均值滤波是指用当前像素点周围 NxN 个像素值的均值来代替当前像素值。使用该方法遍历图像内每一个像素点,便可以完成整幅图像的均值滤波。在进行均值滤波时,首先要考虑对周围多少个像素点取平均值,通常情况是以当前像素点为中心,对行数和列数相等的一块区域内的所有像素点的像素值求平均值。选定的区域一般被称作滤波核或卷积核


现有如下 5x5 的图像,不同位置的像素点有不同的像素值:
在这里插入图片描述

以图像中心点 ‘23’ 为当前像素点,对周围 3x3 区域内的像素值求平均值:

n e w V a l u e = [ ( 148 + 124 + 136 ) + ( 140 + 23 + 133 ) + ( 144 + 151 + 144 ) ] / ( 3 ∗ 3 ) = 127 newValue = [(148+124+136)+(140+23+133)+(144+151+144)]/(3*3)=127 newValue=[(148+124+136)+(140+23+133)+(144+151+144)]/(33)=127,此时 ‘127’ 就成为中心点的像素值。

当然在对图像的第一个像素点 ‘132’ 进行均值滤波操作时,图像的外部并没有像素点,此时有两种计算方式:

(1).只去图像内存在的周围邻域内的像素值的均值

n e w V a l u e = [ ( 132 + 147 ) + ( 151 + 148 ) ] / ( 2 ∗ 2 ) = 127 = 145 newValue = [(132+147)+(151+148)]/(2*2)=127=145 newValue=[(132+147)+(151+148)]/(22)=127=145,此时 ‘145’ 就成为图像的第一个像素点的像素值。

(2).扩展图像的边缘
在这里插入图片描述

如上图所示,可以将 5x5 的图像扩展为 9x9 大小的图像,根据不同的需求可以选择不同的填充方式在新增的行列内填充像素值,填充完成后便可以按一般情况进行均值求解。

2.相关函数

dst = blur(src, ksize[, anchor[, borderType]])

  • dst:返回结果
  • src:输入的图像
  • ksize:滤波核大小
  • anchor:锚点,表示当前计算均值的点位于滤波核的中心点的位置。默认(-1,-1),表示位于滤波核的中心点
  • borderType:边界样式,表示如何扩充边缘
类型说明
cv2.BORDER_CONSTANTiiiiii|abcdefgh|iiiiii,i 为特定值
cv2.BORDER_REPLICATEaaaaaa|abcdefgh|hhhhhh
cv2.BORDER_REFLECTfedcba|abcdefgh|hgfedcb
cv2.BORDER_WRAPcdefgh|abcdefgh|abcdefg
cv2.BORDER_REFLECT101
cv2.BORDER_REFLECT_101
cv2.BORDER_DEFAULT
gfedcb|abcdefgh|gfedcba
cv2.BORDER_TRANSPARENTuvwxyz|abcdefgh|ijklmno

简写为 dst = blur(src, ksize)

3.示例

import cv2

src = cv2.imread('photo.jpg')
dst3 = cv2.blur(src,(3,3))
dst15 = cv2.blur(src,(15,15))
dst70 = cv2.blur(src,(70,70))
cv2.imshow('src',src)
cv2.imshow('dst3',dst3)
cv2.imshow('dst15',dst15)
cv2.imshow('dst70',dst70)
cv2.waitKey()
cv2.destroyAllWindows()

运行结果如下:
在这里插入图片描述

可以看到滤波核越大,图像失真情况会越明显,所在在实际中,既要达到去噪效果,又不能让图像过分失真,就要选取合适大小的滤波核。

二.方框滤波

1.基本原理

在均值滤波中,对每一个像素点进行邻域求均值时,当邻域大小为 3x3 时,原图、滤波核与结果图的结果可以表示如下:
在这里插入图片描述
当我们不进行均值求解,只计算当前像素点邻域内的像素值之和,作为当前像素点的新像素值时,上图可以变换为下图的模式:
在这里插入图片描述

和均值滤波不同的是,方框滤波可以自由选择以上两种方式中的一种方式作为处理方式,其中像素值之和的方式又称为结果归一化方式。由于像素值之和很可能超过像素值的最大范围,被截断处理为最大值后,处理后的图像有可能会为一张白色的图像。

2.相关函数

dst = boxFilter(src, ddepth, ksize[, anchor[, normalize[, borderType]]])

  • dst:返回结果
  • src:输入的图像
  • ddepth:dst 的图像深度,一般使用 -1 表示与 src 的图像深度相同
  • ksize:滤波核大小
  • anchor:锚点,表示当前计算均值的点位于滤波核的中心点的位置。默认(-1,-1),表示位于滤波核的中心点
  • normalize:表示滤波时是否进行结果归一化,取值为 0 或 1,默认为1
    • 0:不进行归一化,结果采取邻域像素值之和
    • 1:归一化,结果采取邻域像素值之和除以滤波核面积大小
  • borderType:边界样式,表示如何扩充边缘,同 cv2.blur

3.示例

import cv2

src = cv2.imread('photo.jpg')
dst0 = cv2.boxFilter(src,-1,(3,3),normalize=0)
dst1 = cv2.boxFilter(src,-1,(3,3),normalize=1)
cv2.imshow('src',src)
cv2.imshow('dst0',dst0)
cv2.imshow('dst1',dst1)
cv2.waitKey()
cv2.destroyAllWindows()

三.高斯滤波

1.基本原理

在进行均值滤波和方框滤波时,滤波核内的值都是相同的,即滤波值的权重相同。在高斯滤波中,会将滤波核中心点的权重加大,原理中心点的权重值减小,然后在此基础上计算邻域内的像素值之和。
在这里插入图片描述
进一步可表示为:
在这里插入图片描述

在实际使用中,高斯滤波核不仅使用的滤波核大小多种多样,而且同一大小滤波核也会使用不同的权重比。


对下图的中心点进行高斯滤波求值时:
在这里插入图片描述

n e w V a l u e = 148 ∗ 0.05 + 124 ∗ 0.1 + . . . . . . + 151 ∗ 0.1 + 144 ∗ 0.05 = 92.6 newValue=148*0.05+124*0.1+......+151*0.1+144*0.05=92.6 newValue=1480.05+1240.1+......+1510.1+1440.05=92.6,此时的结果并没有取均值进行归一化,但实际使用时往往需要进行归一化,严格来讲,没有进行归一化的结果往往是错误的。

2.相关函数

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

  • dst:返回结果
  • src:输入的图像
  • ksize:滤波核大小
  • sigmaX:卷积核在水平方向(X轴)上的标准差,用于控制权重比例
  • sigmaY:卷积核在垂直方向(Y轴)上的标准差,用于控制权重比例
    • 当 sigmaY = 0 时,只采用 sigmaX 的值
    • 当 sigmaX = sigmaY = 0 时,根据 ksize 重新计算这两个值:
      • $sigmaX = 0.3*[(ksize.width-1)*0.5-1] + 0.8 $
      • $sigmaY = 0.3*[(ksize.height-1)*0.5-1] + 0.8 $
  • borderType:边界样式,表示如何扩充边缘,同 cv2.blur

在使用时一般将 sigmaX 和 sigmaY 都设置为0,所以函数简化为:

dst = GaussianBlur(src, ksize, 0, 0)

3.示例

import cv2

src = cv2.imread('photo.jpg')
dst3 = cv2.GaussianBlur(src,(3,3),0,0)
dst5 = cv2.GaussianBlur(src,(5,5),0,0)
cv2.imshow('src',src)
cv2.imshow('dst3',dst3)
cv2.imshow('dst5',dst5)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

四.中值滤波

1.基本原理

中值滤波不再采用加权求均值的的方式计算结果,而是采用邻域内所有像素点的中间值来代替当前像素点的像素值。中值滤波会取当前像素点及周围邻域像素点的像素值,将它们排序,然后取中间位置的像素值作为当前点的像素值。


以下图为例,采用 3x3 的邻域,对中心点 ‘23’ 采区中值滤波进行像素替换:
在这里插入图片描述

排序前:148,124,136,140,23,133,144,151,144

排序后:23,124,133,136,140,144,144,148,151

取中值 140 作为中心点的新像素值。

2.相关函数

dst = medianBlur(src, ksize)

  • dst:输出结果
  • src:输入图像
  • ksize:滤波核大小,必须是大于 1 的标量奇数,例如3,5,7

3.示例

import cv2

src = cv2.imread('photo.jpg')
dst = cv2.medianBlur(src,3)
cv2.imshow('src',src)
cv2.imshow('dst3',dst)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

五.双边滤波

1.基本原理

双边滤波是综合考虑了空间信息和色彩信息的滤波方式,既能够有效地去除噪声,又能够较好的保护边缘信息。之前上述的滤波方式基本都只考虑了空间的权重信息,计算起来比较方便,但是在边缘信息的处理上存在较大问题。

双边滤波在处理边缘时,与当前像素点色彩相近(即像素差值较小)的点会被赋予较大的权重,而与当前像素点色彩相差较大(即像素差值较大)的点会被赋予较小的权重,甚至为 0,这样就做到了保护边缘信息的效果。


如下图所示,图像左侧为白色,右侧为黑色,中间是它们的边缘:
在这里插入图片描述

使用均值滤波、方框滤波、高斯滤波对上图进行平滑处理,可以看到处理后的边缘信息变得很模糊:
在这里插入图片描述

2.相关函数

dst = bilateralFilter(src, d, sigmaColor, sigmaSpace[, borderType])

  • dst:输出结果
  • src:输入图像
  • d:滤波时选取的空间距离参数,表示以当前像素点为中心点的直径
    • d ≤ 0 时,会从参数 sigmaSpace 自动重新计算
    • d > 5 时,滤波速度会较慢
    • 一般选取 d = 5,对于较大噪声的离线滤波,可选择 d = 9
  • sigmaColor:滤波处理时选取的颜色差值范围,该值决定了周围哪些像素点可以参与滤波运算,邻域内与当前像素点差值小于 sigmaColor 值的像素点可以参与运算
  • sigmaSpace:表示空间坐标中的 sigma 值,该值越大,则有越多的点能够参与滤波运算
    • 当 d > 0 时,该值失效
    • 当 d ≤ 0 时,d 与 sigmaSpace 成正比,根据 sigmaSpace 重新计算 d
  • borderType:同上

3.示例

import cv2

img = cv2.imread('2.png')
print(img)
dst1 = cv2.blur(img,(3,3))
dst2 = cv2.bilateralFilter(img,5,150,150)

cv2.imshow('src',img)
cv2.imshow('1',dst1)
cv2.imshow('2',dst2)
cv2.waitKey()
cv2.destroyAllWindows()

对同一个图分别进行均值滤波、双边滤波,明显看到双边滤波处理边缘效果更好:
在这里插入图片描述

六.2D卷积

1.基本原理

之前介绍的滤波方式中的滤波核都具有一定的灵活性,可以设置的大小和数值,然而它也不能够满足特定需求,有时候我们需要特定的卷积实现卷积操作,这时候就需要Opencv 中的2D卷积。

2.相关函数

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

  • dst:返回结果
  • src:输入的图像
  • ddepth:dst 的图像深度,一般使用 -1 表示与 src 的图像深度相同
  • kernel:卷积核,单通道数组。处理彩色图像时可将彩色图通道分解,不同通道使用不同卷积核
  • anchor:锚点,表示当前计算均值的点位于滤波核的中心点的位置。默认(-1,-1),表示位于滤波核的中心点
  • delta:偏置值,滤波的结果基础上加上该值作为最终的滤波处理结果
  • borderType:边界样式,表示如何扩充边缘,同 cv2.blur

在使用时一般可选项都设置为默认值,所以函数简化为:

dst = filter2D(src, ddepth, kernel)

3.示例

自定义一个 7 x 7 的卷积核对图像进行卷积操作,代码与结果如下:

import cv2
import numpy as np

img = cv2.imread('dog.jpg')
kernel = np.ones((7, 7)) / 81.0
dst = cv2.filter2D(img, -1, kernel)

cv2.imshow('src', img)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值