1 - 引言
空间滤波是图像处理领域应用广泛的主要工具之一。这里我们主要讨论怎样使用空间滤波来增强图像。
2 - 平滑空间滤波器
平滑滤波器用于模糊处理和降低噪声。模糊处理经常用于预处理任务中,例如在目标提取之前去除图像中的一些琐碎细节。
2.1 - 平滑线性滤波器
平滑线性空间滤波器的输出(响应)是包含在滤波器过滤核中像素的简单平均值,也成为均值滤波。
这种处理的结果降低了图像灰度的“尖锐”变化。
这种滤波器(3x3)一般分为两种
- 第一种为标准像素平均值 R = 1 9 ∑ i = 1 9 z i R = \frac{1}{9}\sum_{i=1}^9z_i R=91i=1∑9zi
- 第二种为加权平均 g ( x , y ) = ∑ s = − a a ∑ t = − b b w ( s , t ) f ( x + s , y + t ) ∑ s = − a a ∑ t = − b b w ( s , t ) g(x,y)=\frac{\sum_{s=-a}^a\sum_{t=-b}^bw(s,t)f(x+s,y+t)}{\sum_{s=-a}^a\sum_{t=-b}^bw(s,t)} g(x,y)=∑s=−aa∑t=−bbw(s,t)∑s=−aa∑t=−bbw(s,t)f(x+s,y+t)
import cv2
import numpy as np
img = cv2.imread('images/cat.jpg')
cv2.imshow('images',img)
"""
blur—图像均值平滑滤波
函数原型:blur(src, ksize, dst=None, anchor=None, borderType=None)
src:图像矩阵
ksize:滤波窗口尺寸
"""
res = cv2.blur(img, (3, 3))
cv2.imshow('res', res)
"""
GaussianBlur—图像高斯平滑滤波
函数原型:GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
src:图像矩阵
ksize:滤波窗口尺寸
sigmaX:标准差
"""
res2 = cv2.GaussianBlur(img,(3,3),0)
cv2.imshow('res2', res2)
cv2.waitKey()
(可以用来磨皮哦,手动滑稽)
2.2 - 非线性滤波器
这种滤波器的响应一滤波器过滤核中像素的排序为基础,然后使用统计排序的结果决定代替中心像素的值。这一类最知名的滤波器是中值滤波器,正如其名,它是将像素领域内灰度的终止代替该像素的值。中值滤波器对处理脉冲噪声非常有效,这种噪声也成为椒盐噪声。
import cv2
import numpy as np
img = cv2.imread('images/lena_1.jpg')
cv2.imshow('img', img)
"""
medianBlur—图像中值滤波
函数原型:medianBlur(src, ksize, dst=None)
src:图像矩阵
ksize:滤波窗口尺寸
"""
res = cv2.medianBlur(img, 5)
cv2.imshow('res', res)
cv2.waitKey()
3 - 锐化空间滤波器
锐化处理的主要目的是突出灰度的过度部分。
3.1 - 使用二阶微分进行图像锐化——拉普拉斯算子
一个二维图像函数f(x,y)的拉普拉斯算子定义为
▽
2
f
=
∂
2
f
∂
x
2
+
∂
2
f
∂
y
2
\triangledown ^2f=\frac{\partial^2 f}{\partial x^2}+\frac{\partial^2 f}{\partial y^2}
▽2f=∂x2∂2f+∂y2∂2f
离散形式为
▽
2
f
=
f
(
x
+
1
,
y
)
+
f
(
x
−
1
,
y
)
+
f
(
x
,
y
+
1
)
+
f
(
x
,
y
−
1
)
−
4
f
(
x
,
y
)
\triangledown ^2f=f(x+1,y)+f(x-1,y)+f(x,y+1)+f(x,y-1)-4f(x,y)
▽2f=f(x+1,y)+f(x−1,y)+f(x,y+1)+f(x,y−1)−4f(x,y)
我们可以发现这正好可以写成滤波器:
由于拉普拉斯是一种微分算子,因此其应用强调的是图像中灰度的突变,并不强调灰度级缓慢变化的区域。将原图像和拉普拉斯图像叠加在一起的简单方法,可以复原背景特性并保持拉普拉斯锐化处理的效果。
如果所使用的定义具有负的中心系数,那么必须将原图像减去拉普拉斯变换后的图像而不是加上它,从而得到锐化的结果。
import cv2
import numpy as np
img = cv2.imread('images/lena.jpg')
cv2.imshow('img',img)
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)
#kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
dst = cv2.filter2D(img, -1, kernel=kernel)
cv2.imshow('res',dst)
cv2.waitKey(0)
3.2 - 非锐化岩壁和高提升滤波
在印刷和出版界已用了多年的图像锐化处理过程是从原图像中减去一副非锐化(平滑过)版本。
非锐化掩蔽的处理过程为:
- 模糊原图像
- 从原图像中减去模糊图像(产生的差值图像成为模板)
- 将模板加到原图像上
(这个较为简单就不进行试验了)
3.3 - 使用一阶微分对(非线性)图像锐化——梯度
使用梯度锐化图像的算子叫Sobel算子
Sobel算子依然是一种过滤器
图像的每一个像素的横向及纵向梯度近似值可用以下的公式结合,来计算梯度的大小。
G
=
G
x
2
+
G
y
2
G = \sqrt{G_x^2+G_y^2}
G=Gx2+Gy2
Sobel算子包含两组3x3的矩阵,分别为横向及纵向模板,将之与图像作平面卷积,即可分别得出横向及纵向的亮度差分近似值。实际使用中,常用如下两个模板来检测图像边缘。
G
x
=
[
−
1
0
1
−
2
0
2
−
1
0
1
]
G
y
=
[
1
2
1
0
0
0
−
1
−
2
−
1
]
G_x=\begin{bmatrix} -1 &0 &1 \\ -2 & 0 & 2\\ -1 &0 & 1 \end{bmatrix} G_y=\begin{bmatrix} 1 &2 &1 \\ 0 & 0 & 0\\ -1 &-2 & -1 \end{bmatrix}
Gx=⎣⎡−1−2−1000121⎦⎤Gy=⎣⎡10−120−210−1⎦⎤
# coding=utf-8
import cv2
img = cv2.imread("images/lena.jpg")
cv2.imshow('img',img)
"""
Sobel函数
Sobel(src, ddepth, dx, dy, dst=None, ksize=None, scale=None, delta=None, borderType=None)
前四个是必须的参数:
第一个参数是需要处理的图像;
第二个参数是图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
第三和第四:dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2。
其后是可选的参数
"""
x = cv2.Sobel(img, -1, 0, 1)
cv2.imshow('res',x)
cv2.waitKey(0)