【youcans 的 OpenCV 例程200篇】148. 图像分割之线检测
2. 点、线和边缘检测
本节基于图像灰度的不连续性,讨论根据灰度的突变检测边界,以此为基础进行图像分割。
- 边缘像素是图像中灰度突变的像素,而边缘是相连边缘像素的集合。
- 线是一条细边缘线段,其两侧的背景灰度与线段的像素灰度存在显著差异。
- 孤立的点是一个被背景像素围绕的前景像素,或一个被前景像素围绕的背景像素。
导数可以用来检测灰度的局部突变:
- 一阶导数通常产生粗边缘;
- 二阶导数对精细细节(如细线、孤立点和噪声)的响应更强;
- 二阶导数在灰度斜坡和台阶过渡处会产生双边缘响应,即二阶导数在进入和离开边缘时的符号相反;
- 二阶导数的符号可用于确定边缘的过渡是从亮到暗还是从暗到亮。
计算图像中每个像素位置的一阶导数和二阶导数的方法是空间卷积。对一个 3*3 模板,计算模板区域内灰度值与模板系数的卷积。
### 2.2 图像的线检测
线检测的复杂度更高。
使用二阶导数将导致更强的滤波器响应,产生比一阶导数更细的线,因此可以使用拉普拉斯核进行线检测。
由于拉普拉斯检测核是各向同性的,其响应与方向无关。如果希望检测某些特定方向的线,可以使用与方向有关的卷积核:
K
0
o
=
[
−
1
−
1
−
1
2
2
2
−
1
−
1
−
1
]
,
K
+
4
5
o
=
[
2
−
1
−
1
−
1
2
−
1
−
1
−
1
2
]
,
K
9
0
o
=
[
−
1
2
−
1
−
1
2
−
1
−
1
2
−
1
]
,
K
−
4
5
o
=
[
−
1
−
1
2
−
1
2
−
1
2
−
1
−
1
]
\begin{aligned} &K_{0^o} = \begin{bmatrix} -1 & -1 & -1\\ 2 & 2 & 2\\ -1 & -1 & -1\\ \end{bmatrix}, \ &K_{+45^o} = \begin{bmatrix} 2 & -1 & -1\\ -1 & 2 & -1\\ -1 & -1 & 2\\ \end{bmatrix}, \\ &K_{90^o} = \begin{bmatrix} -1 & 2 & -1\\ -1 & 2 & -1\\ -1 & 2 & -1\\ \end{bmatrix}, \ &K_{-45^o} = \begin{bmatrix} -1 & -1 & 2\\ -1 & 2 & -1\\ 2 & -1 & -1\\ \end{bmatrix} \end{aligned}
K0o=⎣⎡−12−1−12−1−12−1⎦⎤, K90o=⎣⎡−1−1−1222−1−1−1⎦⎤, K+45o=⎣⎡2−1−1−12−1−1−12⎦⎤,K−45o=⎣⎡−1−12−12−12−1−1⎦⎤
例程 11.2:图像的线检测
# 11.2 图像的线检测 (Laplace 算子)
imgGray = cv2.imread("../images/Fig0905a.tif", flags=0)
# scipy.signal 实现卷积运算 (注意:不能用 cv2.filter2D 处理)
from scipy import signal
kernelLaplace = np.array([[1, 1, 1], [1, -8, 1], [1, 1, 1]]) # Laplacian kernel
imgLaplace = signal.convolve2d(imgGray, kernelLaplace, boundary='symm', mode='same') # same 卷积
kernel1 = np.array([[-1, -1, -1], [2, 2, 2], [-1, -1, -1]]) # 0 degree, horizontal
kernel2 = np.array([[2, -1, -1], [-1, 2, -1], [-1, -1, 2]]) # +45 degree
kernel3 = np.array([[-1, 2, -1], [-1, 2, -1], [-1, 2, -1]]) # 90 degree, vertical
kernel4 = np.array([[-1, -1, 2], [-1, 2, -1], [2, -1, -1]]) # -45 degree
imgLine1 = signal.convolve2d(imgGray, kernel1, boundary='symm', mode='same') # horizontal kernel
imgLine2 = signal.convolve2d(imgGray, kernel2, boundary='symm', mode='same')
imgLine3 = signal.convolve2d(imgGray, kernel3, boundary='symm', mode='same') # vertical kernel
imgLine4 = signal.convolve2d(imgGray, kernel4, boundary='symm', mode='same')
plt.figure(figsize=(9, 7))
plt.subplot(231), plt.axis('off'), plt.title("original")
plt.imshow(imgGray, cmap='gray', vmin=0, vmax=255)
plt.subplot(232), plt.axis('off'), plt.title("abs(Laplacian)")
plt.imshow(np.maximum(imgLaplace, -imgLaplace), cmap='gray', vmin=0, vmax=255)
plt.subplot(233), plt.axis('off'), plt.title("horizontal")
plt.imshow(imgLine1[200:,200:], cmap='gray', vmin=0, vmax=255)
plt.subplot(234), plt.axis('off'), plt.title("+45 degree")
plt.imshow(imgLine2[:286,:286], cmap='gray', vmin=0, vmax=255)
plt.subplot(235), plt.axis('off'), plt.title("vertical")
plt.imshow(imgLine3[200:,200:], cmap='gray', vmin=0, vmax=255)
plt.subplot(236), plt.axis('off'), plt.title("-45 degree")
plt.imshow(imgLine4[:286,200:], cmap='gray', vmin=0, vmax=255)
plt.tight_layout()
plt.show()
(本节完)
版权声明:
youcans@xupt 原创作品,转载必须标注原文链接:(https://blog.csdn.net/youcans/article/details/124027129)
Copyright 2022 youcans, XUPT
Crated:2022-4-8