高斯拉普拉斯算子(LoG)算子边缘检测
-
高斯拉普拉斯算子(LoG)算子边缘检测
- 1. 前言
- 2. 高斯拉普拉斯算子(LoG)算子描述
- 3. 代码实现
1. 前言
在图像中,灰度或结构等信息的突变处称为边缘。边缘可以看作一个区域的结束,另一个区域的开始。利用边缘的特征,可以对图像进行分割。根据定义可以知道,利用各种算法检测到的边缘,并不代表目标的实际边缘。由于图像是二维的,而目标实物是三维的,从三维到二维的投影,已经造成了信息的丢失,再加上成像过程受光照、噪声的影响,使得有边缘的地方不一定被检测出来,而检测出来的边缘也不一定代表实际边缘。
图像的边缘有方向和幅度两个属性,沿边缘方向像素变化平缓,垂直于边缘方向像素变化剧烈。因此,利用图像边缘的变化特性,通过微分算子可以将边缘检查出来,通常用一阶或二阶导数来检测边缘。一阶导数以最大值对应边缘位置,二阶导数以过零点为边缘位置。
2. 高斯拉普拉斯算子(LoG)算子描述
利用二阶导数的零交叉点来检测边缘点的算法对噪声非常敏感,因此在增强边缘前对图像降噪是十分必要的,高斯拉普拉斯(LoG)边检算子正是基于这种需要提出的。在20世纪70年代,Marr理论根据神经生理学实验得出了以下结论:物体的边界是将亮度图像与其解释连接起来的最重要线索,并且符合人类视觉特性。
高斯拉普拉斯算子(LoG)算子的数学推导如下:
Laplacian算子边缘检测的数学表达式:
▽
2
f
(
x
,
y
)
=
∂
2
f
∂
x
2
+
∂
2
f
∂
y
2
(1)
\triangledown^2f(x,y) = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2f}{\partial y^2} \tag{1}
▽2f(x,y)=∂x2∂2f+∂y2∂2f(1)
一维高斯函数如下:
G
σ
x
=
1
2
π
σ
2
e
−
x
2
2
σ
2
(2)
G_{\sigma x} = \frac{1}{\sqrt{2\pi\sigma^2}}e^{-\frac{x^2}{2\sigma^2}} \tag{2}
Gσx=2πσ21e−2σ2x2(2)
二维高函数如下:
G
σ
(
x
,
y
)
=
1
2
π
σ
2
e
−
x
2
+
y
2
2
σ
2
(3)
G_{\sigma(x,y)} = \frac{1}{2\pi\sigma^2}e^{-\frac{x^2 + y^2}{2\sigma^2}}\tag{3}
Gσ(x,y)=2πσ21e−2σ2x2+y2(3)
二维高斯函数的一阶偏导数为:
∂
G
σ
(
x
,
y
)
∂
x
=
(
−
1
2
π
σ
4
)
x
e
−
x
2
+
y
2
2
σ
2
(4)
\frac{\partial G_{\sigma(x,y)}}{\partial x} = (-\frac{1}{2\pi\sigma^4})xe^{-\frac{x^2 + y^2}{2\sigma^2}} \tag{4}
∂x∂Gσ(x,y)=(−2πσ41)xe−2σ2x2+y2(4)
∂
G
σ
(
x
,
y
)
∂
y
=
(
−
1
2
π
σ
4
)
y
e
−
x
2
+
y
2
2
σ
2
(5)
\frac{\partial G_{\sigma(x,y)}}{\partial y} = (-\frac{1}{2\pi\sigma^4})ye^{-\frac{x^2 + y^2}{2\sigma^2}} \tag{5}
∂y∂Gσ(x,y)=(−2πσ41)ye−2σ2x2+y2(5)
二维高斯函数的一阶梯度为:
▽
G
σ
(
x
,
y
)
=
∣
∂
G
σ
(
x
,
y
)
∂
x
∣
+
∣
∂
G
σ
(
x
,
y
)
∂
y
∣
(6)
\triangledown G_{\sigma(x,y)} = |\frac{\partial G_{\sigma(x,y)}}{\partial x}| + |\frac{\partial G_{\sigma(x,y)}}{\partial y}| \tag{6}
▽Gσ(x,y)=∣∂x∂Gσ(x,y)∣+∣∂y∂Gσ(x,y)∣(6)
二维高斯函数的二阶偏导数为:
∂
2
G
σ
(
x
,
y
)
∂
x
2
=
(
−
1
2
π
σ
4
)
(
1
−
x
2
σ
2
)
e
−
x
2
+
y
2
2
σ
2
(7)
\frac{\partial^2 G_{\sigma(x,y)}}{\partial x^2} = (-\frac{1}{2\pi\sigma^4})(1-\frac{x^2}{\sigma^2})e^{-\frac{x^2 + y^2}{2\sigma^2}} \tag{7}
∂x2∂2Gσ(x,y)=(−2πσ41)(1−σ2x2)e−2σ2x2+y2(7)
∂
2
G
σ
(
x
,
y
)
∂
y
2
=
(
−
1
2
π
σ
4
)
(
1
−
y
2
σ
2
)
e
−
x
2
+
y
2
2
σ
2
(8)
\frac{\partial^2 G_{\sigma(x,y)}}{\partial y^2} = (-\frac{1}{2\pi\sigma^4})(1-\frac{y^2}{\sigma^2})e^{-\frac{x^2 + y^2}{2\sigma^2}} \tag{8}
∂y2∂2Gσ(x,y)=(−2πσ41)(1−σ2y2)e−2σ2x2+y2(8)
二维高斯函数的二阶梯度为:
▽
2
G
σ
(
x
,
y
)
=
∣
∂
2
G
σ
(
x
,
y
)
∂
x
2
∣
+
∣
∂
2
G
σ
(
x
,
y
)
∂
y
2
∣
(9)
\triangledown^2 G_{\sigma(x,y)} = |\frac{\partial^2 G_{\sigma(x,y)}}{\partial x^2}| + |\frac{\partial^2 G_{\sigma(x,y)}}{\partial y^2}| \tag{9}
▽2Gσ(x,y)=∣∂x2∂2Gσ(x,y)∣+∣∂y2∂2Gσ(x,y)∣(9)
方向梯度(角度
θ
\theta
θ取弧度):
i
→
=
x
cos
θ
+
y
sin
θ
(10)
\overrightarrow i = x\cos\theta + y \sin\theta \tag{10}
i=xcosθ+ysinθ(10)
一维高斯函数梯度方向:
∂
G
x
∂
i
→
=
∂
G
x
∂
x
cos
θ
+
∂
G
x
∂
y
sin
θ
(11)
\frac{\partial G_x}{\partial \overrightarrow{i}} = \frac{\partial G_x}{\partial x}\cos\theta + \frac{\partial G_x}{\partial y}\sin\theta \tag{11}
∂i∂Gx=∂x∂Gxcosθ+∂y∂Gxsinθ(11)
二维高斯函数梯度方向:
∂
2
G
σ
(
x
,
y
)
∂
i
→
2
=
∂
2
G
σ
(
x
,
y
)
∂
x
2
cos
2
θ
+
∂
2
G
σ
(
x
,
y
)
∂
y
2
sin
2
θ
+
2
∂
2
G
σ
(
x
,
y
)
∂
x
∂
y
cos
θ
sin
θ
(12)
\frac{\partial^2 G_{\sigma(x,y)}}{\partial \overrightarrow{i}^2} = \frac{\partial^2 G_{\sigma(x,y)}}{\partial x^2}\cos^2\theta + \frac{\partial^2 G_{\sigma(x,y)}}{\partial y^2}\sin^2\theta + 2\frac{\partial^2 G_{\sigma(x,y)}}{\partial x \partial y}\cos\theta\sin\theta \tag{12}
∂i2∂2Gσ(x,y)=∂x2∂2Gσ(x,y)cos2θ+∂y2∂2Gσ(x,y)sin2θ+2∂x∂y∂2Gσ(x,y)cosθsinθ(12)
原图像与高斯核函数卷积后再做Laplace运算:
△
[
G
σ
(
x
,
y
)
∗
f
(
x
,
y
)
]
=
[
△
G
σ
(
x
,
y
)
]
∗
f
(
x
,
y
)
(13)
\triangle[G_{\sigma(x,y)} * f(x,y)] = [\triangle G_{\sigma(x,y)}] * f(x,y) \tag{13}
△[Gσ(x,y)∗f(x,y)]=[△Gσ(x,y)]∗f(x,y)(13)
证明如下:
d
d
t
2
[
h
(
t
)
∗
f
(
t
)
]
=
d
d
t
∫
f
(
τ
)
h
(
t
−
τ
)
d
τ
=
∫
f
(
τ
)
d
d
t
2
h
(
t
−
τ
)
d
τ
=
f
(
t
)
∗
d
d
t
2
h
(
t
)
(14)
ddt2[h(t)∗f(t)]=ddt∫f(τ)h(t−τ)dτ=∫f(τ)ddt2h(t−τ)dτ=f(t)∗ddt2h(t)
展开后得到,
L
o
G
=
△
G
σ
(
x
,
y
)
=
∂
2
G
σ
(
x
,
y
)
∂
x
2
+
∂
2
G
σ
(
x
,
y
)
∂
y
2
=
x
2
+
y
2
−
2
σ
2
σ
4
e
−
x
2
+
y
2
2
σ
2
(15)
LoG = \triangle G_{\sigma(x,y)} = \frac{\partial^2 G_{\sigma(x,y)}}{\partial x^2} + \frac{\partial^2 G_{\sigma(x,y)}}{\partial y^2} = \frac{x^2 + y^2 - 2\sigma^2}{\sigma^4}e^{-\frac{x^2+y^2}{2\sigma^2}} \tag{15}
LoG=△Gσ(x,y)=∂x2∂2Gσ(x,y)+∂y2∂2Gσ(x,y)=σ4x2+y2−2σ2e−2σ2x2+y2(15)
所以,
L
o
G
∗
f
(
x
,
y
)
=
x
2
+
y
2
−
2
σ
2
σ
4
[
G
σ
(
x
,
y
)
∗
f
(
x
,
y
)
]
(16)
LoG * f(x,y) = \frac{x^2+y^2-2\sigma^2}{\sigma^4}[G_{\sigma(x,y)}*f(x,y)] \tag{16}
LoG∗f(x,y)=σ4x2+y2−2σ2[Gσ(x,y)∗f(x,y)](16)
先对高斯核函数求取二阶导数,再与原图像进行卷积操作。由于高斯函数是圆对称的,因此LoG算子可以有效地实现极值点或局部极值区域的检测。
高斯函数、高斯函数的一阶导数、高斯函数的二阶导数分别如下图:
LoG算子特点是由于先进行了高斯滤波,因而可以一定程度上克服噪声的影响。它的局限性在于以下两个方面:
- (1)可能产生假边缘(false edges);
- (2)对一些曲线边缘(curved edges)的定位误差较大。
3. 代码实现
import numpy as np
import matplotlib.pyplot as plt
import scipy
from scipy.signal import convolve2d
import scipy.signal as sgn
import cv2
# 拉普拉斯边缘检查
# @thresh:阈值
# @useThresh:是否使用阈值过滤边缘检查结果
def lapace_edge(src,thresh=20,useThresh=False):
# 检查图像是否为灰度图像
assert(len(src.shape) == 2)
# 拉普拉斯内核
kernel = np.array([
[0,1,0],
[1,-4,1],
[0,1,0]
])
# 卷积运算
#G = convolve2d(np.float32(src),kernel, boundary='symm', mode='same')
G = convolve2d(np.float32(src),kernel, boundary='symm', mode='same')
G = np.abs(G)
# 按阈值提取
if useThresh:
idx = G >= thresh
G[idx] = src[idx]
G[~idx] = 0
else:
G = np.clip(G,0,255)
return G.astype(np.uint8)
# 生成高斯卷积核
# 按参数生成高斯卷积核
def gaussian_kernel(size=5, sigma=1.0):
x, y = np.mgrid[-(size//2):(size//2)+1, -(size//2):(size//2)+1]
normal = 1 / (2 * np.pi * sigma**2)
kernel = normal * np.exp(-((x**2 + y**2)/(2 * sigma**2)))
return kernel
# 图像高斯模糊
def gaussian_blur(src,sigma,truncate=4.0):
assert(len(src.shape) == 2)
kernel = gaussian_kernel(sigma,truncate)
blured = convolve2d(np.float32(src),kernel, boundary='symm', mode='same')
return np.clip(blured,0,255).astype(np.uint8)
# Log算子边缘检测
def LoG_edge(src,sigma,truncate=4.0):
blured = gaussian_blur(src,sigma,truncate)
edged = lapace_edge(blured)
return edged
def main():
src = cv2.imread('resources/images/',0)
dst = LoG_edge(src,2.2)
# dst_thresh = lapace_edge(src,thresh=20,useThresh=True)
# dst2 = (src,cv2.CV_8UC1,ksize=3)
plt.figure()
plt.subplot(1,2,1)
plt.imshow(src,'gray')
plt.title('Source Image')
plt.xticks([])
plt.yticks([])
plt.subplot(1,2,2)
plt.imshow(dst,'gray')
plt.title('LoG Edge sigma=2.2')
plt.xticks([])
plt.yticks([])
plt.show()
if __name__ == '__main__':
main()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
程序运行结果: