Py-OpenCV学习记录5-滤波处理(一)

前言

滤波分为线性滤波非线性滤波两种,线性滤波中有方框滤波、均值滤波和高斯滤波三种,非线性滤波则有中值滤波和双边滤波两种。在介绍滤波方式之前先以二维滤波的形式介绍滤波的运算。

滤波操作

二维滤波(二维卷积)

用二维滤波的方法选取不同的卷积核可以实现各种不同的效果,虽然OpenCV中内置函数能实现不同的操作,但是通过自己构建卷积核矩阵能够使我们更好的理解不同操作背后的运算逻辑。
将源图像和内核卷积处理,内核kernel(卷积核)是一个浮点数的矩阵,一个5×5的均值滤波内核矩阵如下所示,将内核(卷积核)的中心 与图像的一个像素对齐,5×5的内核则需要将中心周围的25个像素取平均值,并以此值替换中心的像素值,依次对整个图像的其他所有像素操作,便得到了滤波后的图像。
K = 1 9 [ 1 1 1 1 1 1 1 1 1 ] K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1\\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} K=91111111111
首先介绍一下矩阵卷积的计算理论。
离散二维卷积公式:
B ( i , j ) = ∑ m = 0 ∑ n = 0 K ( m . n ) × A ( i − m , h − m ) B(i,j)=\sum_{m=0}\sum_{n=0}K(m.n)×A(i-m,h-m) B(i,j)=m=0n=0K(m.n)×A(im,hm)
其中A为被卷积矩阵、B为卷积结果、K为卷积内核。

A = [ 1 2 3 4 5 6 7 8 9 ] K = [ 1 2 3 4 5 6 7 8 9 ] A = \begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} K = \begin{bmatrix} 1 & 2 & 3\\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{bmatrix} A=147258369K=147258369
将卷积内核K翻转180°
K ∗ = [ 9 8 7 6 5 4 3 2 1 ] K\\^* = \begin{bmatrix} 9 & 8 & 7\\ 6& 5 & 4 \\ 3 & 2& 1 \end{bmatrix} K=963852741
被卷积矩阵A拓展为 (m+2(n%2))x(m+2(n%2)) 的矩阵,在外围无元素位置以0填补
A ∗ = [ 0 0 0 0 0 0 1 2 3 0 0 4 5 6 0 0 7 8 9 0 0 0 0 0 0 ] A\\^* = \begin{bmatrix} 0 & 0 & 0 & 0 & 0 \\ 0 &1 & 2 & 3 & 0\\ 0 & 4 & 5 & 6 & 0 \\ 0 & 7 & 8 & 9 & 0 \\ 0 & 0 &0 & 0 & 0\end{bmatrix} A=0000001470025800369000000
将K*的中心依次对准A*的元素,相乘后相加
A ∗ = [ 0 × 9 0 × 8 0 × 7 0 0 0 × 6 1 × 5 2 × 4 3 0 0 × 3 4 × 2 5 × 1 6 0 0 7 8 9 0 0 0 0 0 0 ] A\\^* = \begin{bmatrix} \color{red}0×9 & \color{red}0×8 & \color{red}0×7 & 0 & 0 \\ \color{red}0×6 &\color{red}1×5 & \color{red}2×4 & 3 & 0\\ \color{red}0×3 & \color{red}4×2 & \color{red}5×1 & 6 & 0 \\ 0 & 7 & 8 & 9 & 0 \\ 0 & 0 &0 & 0 & 0\end{bmatrix} A=0×90×60×3000×81×54×2700×72×45×1800369000000
红色部分得出:0+0+0+0+5+8+0+8+5=26 为B(1,1)的值,依次对所有的元素计算,最终得出一个3x3的矩阵,便完成了矩阵的卷积运算。
结果为
K ∗ = [ 26 56 54 84 155 144 134 258 186 ] K\\^* = \begin{bmatrix} 26 & 56 & 54\\ 84& 155 & 144 \\ 134 & 258 & 186 \end{bmatrix} K=26841345615525854144186
下面介绍函数
dst = cv2.filter2D(src, ddepth, kernel, dst=..., anchor=..., delta=..., borderType=...)

参数介绍
src输入源图像
ddepth图像的深度,当值为-1时为和源图像相同
kernal卷积内核,多取边长为奇数(便于取中心像素点)
dst计算结果图像有和dst相同的大小和通道数
anchor内核的锚点,默认为(-1,-1)
delta卷积过程中会加在每个像素上,默认值为0
borderType卷积计算时边界的形式,默认为 BORDER_DEAFAULT

anchor 的取值会影响中心像素的位置,默认值(-1,-1)表示锚点位于内核中心。

import cv2
import numpy as np

#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',0), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)

#用Numpy生成了三个内核
#内核1为一个均值滤波的5x5的核
#内核2为一个3x3的边缘检测的核
#内核3为一个对对角线敏感的3x3的核
kernel1 = np.ones((5,5), np.float32)/25
kernel2 = np.mat('-1 -1 -1; -1 8 -1; -1 -1 -1', np.float32)
kernel3 = np.mat('-2 -1 0; -1 0 1; 0 1 2', np.float32)

#分别进行卷积运算
dst1 = cv2.filter2D(im1, -1, kernel1)
dst2 = cv2.filter2D(im1, -1, kernel2)
dst3 = cv2.filter2D(im1, -1, kernel3)

img = [im1, dst1, dst2, dst3]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows() 

二维滤波操作结果

图1 二维滤波操作结果

线性滤波

方框滤波/均值滤波

这是最简单的一种滤波方式,方框滤波/均值滤波的作用是模糊一张图片。
使用的是 cv2.boxFilter() 方框滤波和 cv2.blur() 均值滤波
卷积核如下所示
K e r n a l = α [ 1 1 . . . 1 1 1 . . . 1   . . . . . . 1 1 1 ] Kernal = \alpha \begin{bmatrix} 1 & 1 &... & 1\\ 1& 1 & .. .& 1\ \\ ... & ... & & \\ 1 & 1 & & 1 \end{bmatrix} Kernal=α11...111...1......11 1
α = { 1 k s i z e × k s i z e ,  n o r m a l i z e = T r u e 1 ,  n o r m a l i z e = F a l s e \alpha = \begin{cases} \frac{1}{ksize×ksize} &\text{, } normalize = True \\ 1 &\text{, } normalize = False \end{cases} α={ksize×ksize11normalize=Truenormalize=False
当方框滤波的参数 normalizeTrue 时,方框滤波的内核和均值滤波的内核相同。
dst=cv.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]])

参数介绍
src输入源图像,可以有多种通道,不过不同通道之间是分开处理的
ddepth图像的深度,当值为-1时为和源图像相同
ksize卷积核的尺寸,如(5,5)
dst计算结果图像有和dst相同的大小和通道数
anchor内核的锚点,默认为(-1,-1)表示锚点在卷积核中心
normalize如上公式所示
borderType卷积计算时边界的形式,默认为 BORDER_DEAFAULT 一般不管

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

参数介绍
src输入源图像,可以有多种通道,不过不同通道之间是分开处理的
ksize卷积核的尺寸,如(5,5)
dst计算结果图像有和dst相同的大小和通道数
anchor内核的锚点,默认为(-1,-1)表示锚点在卷积核中心
borderType卷积计算时边界的形式,默认为 BORDER_DEAFAULT 一般不管
import cv2
import numpy as np

#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',1), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)
#生成内核卷积与OpenCV的均值模糊相对比
kernal_1 = np.ones((5,5), np.float32)/25

#分别进行卷积运算
dst1 = cv2.blur(im1, (5,5))
dst2 = cv2.boxFilter(im1, -1, (5,5))
dst3 = cv2.filter2D(im1, -1, kernal_1)

img = [im1, dst1, dst2, dst3]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows() 

图生成内核的模糊与均值模糊相对比

图2 生成内核的模糊与均值模糊相对比
右下为生成内核的模糊图

高斯滤波

高斯滤波是一种线性平滑滤波,用来消除高斯噪声效果极佳,通常用于图像的降噪。高斯滤波的卷积运算是一个加权平均的计算过程,其权函数来自正态分布函数,其本质便是图像与正态分布做卷积运算,正态分布也叫高斯分布,因此得名高斯滤波/高斯模糊。
高斯滤波是图像处理中十分常用的一种滤波技术,处理的效果好但是效率并不高。由于高斯函数的傅里叶变换后任为高斯函数,只是幅度和方差发生了变化,所以高斯滤波对于图像来说也是一种低通滤波操作。
一维高斯函数如下:
G ( x ) = α e − ( i − ( k s i z e − 1 2 ) ) 2 2 σ 2 G(x) = \alpha e\\^{-\frac{(i-(\frac{ksize-1}{2}))\\^2}{2\sigma\\^2}} G(x)=αe2σ2(i(2ksize1))2
其中
i 为满足 0<=i<=ksize-1 的整数
α 为使得 ∑G = 1 的一个值
ksize 为卷积核的阶数(长度)
σ 为标准差,通常取1其值越大表示周围的像素点权重越大,也可由下式计算得
σ = 0.3 × ( k s i z e − 1 2 − 1 ) + 0.8 \sigma =0.3×(\frac{ksize-1}{2}-1)+0.8 σ=0.3×(2ksize11)+0.8
例如
当卷积核阶数为3时,即 ksize = 3 ,那么 i = 0,1,2
σ=1
则有 G’1=[0.60653 1 0.60653]
通过计算可得
a = 1 Σ G i = 1 2.21306 = 0.45186 a=\frac{1}{\Sigma G\\_i}=\frac{1}{2.21306}=0.45186 a=ΣGi1=2.213061=0.45186
最终得出 G1=[0.27410 0.45186 0.27410]
此时得出的为一维的高斯权值
计算二维得高斯模板可以通过 GTG 计算
得:
G T G = [ 0.0751 0.1239 0.0751 0.1239 0.2047 0.1239   0.0751 0.1239 0.0751 ] G\\^TG =\begin{bmatrix} 0.0751 & 0.1239 & 0.0751\\ 0.1239& 0.2047 & 0.1239\ \\0.0751 & 0.1239 & 0.0751 \end{bmatrix} GTG=0.07510.12390.07510.12390.20470.12390.07510.1239 0.0751
在OpenCV中也可以通过 cv2.getGaussianKernal() 来创造高斯卷积核。
dst=cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

参数介绍
src输入源图像,可以有不同的通道,但是不同通道之间是分开处理的
ksize内核的尺寸,宽度和长度可以不同,但是必须为奇数
sigmaXX方向上的标准差,与上面 的介绍相同,若取0则由ksize求
sigmaYY方向上的标准差,与上面 的介绍相同,若不取值则与sigmaX相等
borderType图像边缘像素的边界形式
import cv2
import numpy as np
#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',1), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)

#生成5x5的高斯内核与OpenCV的高斯模糊相对比
kernal_1 = np.mat('0.00297 0.01331 0.02194 0.01331 0.00297;\
                    0.01331 0.05963 0.09832 0.05963 0.01331;\
                    0.02194 0.09832 0.16210 0.09832 0.02194;\
                    0.01331 0.05963 0.09832 0.05963 0.01331;\
                    0.00297 0.01331 0.02194 0.01331 0.00297', np.float32)

#分别进行卷积运算
dst1 = cv2.GaussianBlur(im1, (5,5), 1)
#dst2 = cv2.GaussianBlur(im1, (5,5), 0.1)
#dst3 = cv2.GaussianBlur(im1, (5,5), 100)
dst2 = cv2.filter2D(im1, -1, kernal_1)

img = [im1, dst1, dst2]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows() 

代码及结果如下所示,完全相同!
在这里插入图片描述

图3 高斯模糊对比
最后还是附一张封面(。ì _ í。)

图像处理图片
最后祝大家学习顺利噢!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小聪民

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值