拉普拉斯滤波
Laplacian滤波器是对图像亮度进行二次微分从而检测边缘的滤波器。由于数字图像是离散的,
x
x
x方向和
y
y
y方向的一次微分分别按照以下式子计算:
I
x
(
x
,
y
)
=
I
(
x
+
1
,
y
)
−
I
(
x
,
y
)
(
x
+
1
)
−
x
=
I
(
x
+
1
,
y
)
−
I
(
x
,
y
)
I
y
(
x
,
y
)
=
I
(
x
,
y
+
1
)
−
I
(
x
,
y
)
(
y
+
1
)
−
y
=
I
(
x
,
y
+
1
)
−
I
(
x
,
y
)
I_x(x,y)=\frac{I(x+1,y)-I(x,y)}{(x+1)-x}=I(x+1,y)-I(x,y)\\ I_y(x,y) =\frac{I(x, y+1) - I(x,y)}{(y+1)-y}= I(x, y+1) - I(x,y)
Ix(x,y)=(x+1)−xI(x+1,y)−I(x,y)=I(x+1,y)−I(x,y)Iy(x,y)=(y+1)−yI(x,y+1)−I(x,y)=I(x,y+1)−I(x,y)
因此二次微分按照以下式子计算:
I
x
x
(
x
,
y
)
=
I
x
(
x
,
y
)
−
I
x
(
x
−
1
,
y
)
(
x
+
1
)
−
x
=
I
x
(
x
,
y
)
−
I
x
(
x
−
1
,
y
)
=
[
I
(
x
+
1
,
y
)
−
I
(
x
,
y
)
]
−
[
I
(
x
,
y
)
−
I
(
x
−
1
,
y
)
]
=
I
(
x
+
1
,
y
)
−
2
I
(
x
,
y
)
+
I
(
x
−
1
,
y
)
\begin{aligned} &I_{xx}(x,y) \\ =& \frac{I_x(x,y) - I_x(x-1,y)}{(x+1)-x} \\ =& I_x(x,y) - I_x(x-1,y)\\ =&[I(x+1, y) - I(x,y)] - [I(x, y) - I(x-1,y)]\\ =& I(x+1,y) - 2\ I(x,y) + I(x-1,y) \end{aligned}
====Ixx(x,y)(x+1)−xIx(x,y)−Ix(x−1,y)Ix(x,y)−Ix(x−1,y)[I(x+1,y)−I(x,y)]−[I(x,y)−I(x−1,y)]I(x+1,y)−2 I(x,y)+I(x−1,y)
同理:
I
y
y
(
x
,
y
)
=
I
(
x
,
y
+
1
)
−
2
I
(
x
,
y
)
+
I
(
x
,
y
−
1
)
I_{yy}(x,y)=I(x,y+1)-2\ I(x,y)+I(x,y-1)
Iyy(x,y)=I(x,y+1)−2 I(x,y)+I(x,y−1)
特此,Laplacian 表达式如下:
∇
2
I
(
x
,
y
)
=
I
x
x
(
x
,
y
)
+
I
y
y
(
x
,
y
)
=
I
(
x
−
1
,
y
)
+
I
(
x
,
y
−
1
)
−
4
∗
I
(
x
,
y
)
+
I
(
x
+
1
,
y
)
+
I
(
x
,
y
+
1
)
\begin{aligned} &\nabla^2\ I(x,y)\\ =&I_{xx}(x,y)+I_{yy}(x,y)\\ =&I(x-1,y) + I(x,y-1) - 4 * I(x,y) + I(x+1,y) + I(x,y+1) \end{aligned}
==∇2 I(x,y)Ixx(x,y)+Iyy(x,y)I(x−1,y)+I(x,y−1)−4∗I(x,y)+I(x+1,y)+I(x,y+1)
如果把这个式子表示为卷积核是下面这样的:
K
=
[
0
1
0
1
−
4
1
0
1
0
]
K= \left[ \begin{matrix} 0&1&0\\ 1&-4&1\\ 0&1&0 \end{matrix} \right]
K=⎣⎡0101−41010⎦⎤
代码实现
import cv2 # 我只用它来做图像读写和绘图,没调用它的其它函数哦
import numpy as np # 进行数值计算
# padding 函数
def padding(img, K_size=3):
# img 为需要处理图像
# K_size 为滤波器也就是卷积核的尺寸,这里我默认设为3*3,基本上都是奇数
# 获取图片尺寸
H, W, C = img.shape
pad = K_size // 2 # 需要在图像边缘填充的0行列数,
# 之所以我要这样设置,是为了处理图像边缘时,滤波器中心与边缘对齐
# 先填充行
rows = np.zeros((pad, W, C), dtype=np.uint8)
# 再填充列
cols = np.zeros((H+2*pad, pad, C), dtype=np.uint8)
# 进行拼接
img = np.vstack((rows, img, rows)) # 上下拼接
img = np.hstack((cols, img, cols)) # 左右拼接
return img
# Prewitt 滤波函数
def laplacian(img, K_size=3):
# 获取图像尺寸
H, W, C = img.shape
# 进行padding
pad = K_size // 2
out = padding(img, K_size=3)
# 滤波器系数
K = np.array([[0., 1., 0.],[1., -4., 1.], [0., 1., 0.]])
# 进行滤波
tem = out.copy()
for h in range(H):
for w in range(W):
for c in range(C):
out[pad+h, pad+w, c] = np.sum(K * tem[h:h+K_size, w:w+K_size, c], dtype=np.float)
out = np.clip(out, 0, 255)
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
return out
# 这里需要把图像先灰度化
# 直接用之前的灰度化代码
# 灰度化函数
def BGR2GRAY(img):
# 获取图片尺寸
H, W, C = img.shape
# 灰度化
out = np.ones((H,W,3))
for i in range(H):
for j in range(W):
out[i,j,:] = 0.299*img[i,j,0] + 0.578*img[i,j,1] + 0.114*img[i,j,2]
out = out.astype(np.uint8)
return out
# 读取图片
path = 'C:/Users/86187/Desktop/image/'
file_in = path + 'cake.jpg'
file_out = path + 'laplacian_filter.jpg'
img = cv2.imread(file_in)
# 调用函数进行灰度化
img = BGR2GRAY(img)
# 调用函数进行sobel滤波
out = laplacian(img)
# 保存图片
cv2.imwrite(file_out, out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果展示
原图 | 拉普拉斯提取图像边缘 |
---|---|
laplacian滤波器实现图像的锐化
由于拉普拉斯是一种微分算子,它的应用可增强图像中灰度突变的区域,减弱灰度的缓慢变化区域。
因此,锐化处理可选择拉普拉斯算子对原图像进行处理,产生描述灰度突变的图像,再将拉普拉斯图像与原始图像叠加而产生锐化图像:
g
(
x
,
y
)
=
f
(
x
,
y
)
+
c
[
∇
2
f
(
x
,
y
)
]
g(x, y)=f(x, y)+c\left[\nabla^{2} f(x, y)\right]
g(x,y)=f(x,y)+c[∇2f(x,y)]
其中,
f
(
x
,
y
)
f(x,y)
f(x,y)为原始图像,
g
(
x
,
y
)
g(x,y)
g(x,y)为锐化后图像,
c
c
c为-1(卷积核中间为负数时,若卷积核中间为正数,则
c
c
c为1)。
代码实现
import cv2 # 我只用它来做图像读写和绘图,没调用它的其它函数哦
import numpy as np # 进行数值计算
# padding 函数
def padding(img, K_size=3):
# img 为需要处理图像
# K_size 为滤波器也就是卷积核的尺寸,这里我默认设为3*3,基本上都是奇数
# 获取图片尺寸
H, W, C = img.shape
pad = K_size // 2 # 需要在图像边缘填充的0行列数,
# 之所以我要这样设置,是为了处理图像边缘时,滤波器中心与边缘对齐
# 先填充行
rows = np.zeros((pad, W, C), dtype=np.uint8)
# 再填充列
cols = np.zeros((H+2*pad, pad, C), dtype=np.uint8)
# 进行拼接
img = np.vstack((rows, img, rows)) # 上下拼接
img = np.hstack((cols, img, cols)) # 左右拼接
return img
# Prewitt 滤波函数
def laplacian(img, K_size=3):
# 获取图像尺寸
H, W, C = img.shape
# 进行padding
pad = K_size // 2
out = padding(img, K_size=3)
# 滤波器系数
K = np.array([[0., 1., 0.],[1., -4., 1.], [0., 1., 0.]])
# 进行滤波
tem = out.copy()
for h in range(H):
for w in range(W):
for c in range(C):
out[pad+h, pad+w, c] = (-1)*np.sum(K * tem[h:h+K_size, w:w+K_size, c]) + tem[pad+h, pad+w, c]
out = np.clip(out, 0, 255)
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
return out
# 这里需要把图像先灰度化
# 直接用之前的灰度化代码
# 灰度化函数
def BGR2GRAY(img):
# 获取图片尺寸
H, W, C = img.shape
# 灰度化
out = np.ones((H,W,3))
for i in range(H):
for j in range(W):
out[i,j,:] = 0.299*img[i,j,0] + 0.578*img[i,j,1] + 0.114*img[i,j,2]
out = out.astype(np.uint8)
return out
# 读取图片
path = 'C:/Users/86187/Desktop/image/'
file_in = path + 'cake.jpg'
file_out = path + 'laplacian_filter_1.jpg'
img = cv2.imread(file_in)
# 调用函数进行灰度化
img = BGR2GRAY(img)
# 调用函数进行sobel滤波
out = laplacian(img)
# 保存图片
cv2.imwrite(file_out, out)
cv2.imshow("result", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
结果展示
原图 | 锐化 |
---|---|