0. 前言
邊緣檢測是一種圖像處理技術(shù),旨在標識和定位數(shù)字圖像中的邊緣和輪廓。邊緣是圖像中灰度值變化明顯的位置,通常是物體的邊緣或表面的變化。通過邊緣檢測算法,可以將圖像中的物體和背景分離出來,從而實現(xiàn)目標檢測、圖像分割、計算機視覺和機器人視覺等應(yīng)用。
邊緣檢測算法的基本原理是在數(shù)字圖像中尋找灰度變化的位置。其中,最常見的方法是基于圖像梯度的邊緣檢測算法,如Sobel算子、Prewitt算子、Roberts算子和Canny算子等。
1. Sobel算子
Sobel算子將數(shù)字圖像與兩個卷積核Gx和Gy進行卷積,Gx和Gy分別用于計算水平方向和垂直方向上的梯度:
G
x
=
[
?
1
0
1
?
2
0
2
?
1
0
1
]
G_x = \begin{bmatrix}-1 & 0 & 1 \\-2 & 0 & 2 \\-1 & 0 & 1\end{bmatrix}
Gx?=
??1?2?1?000?121?
?
G
y
=
[
?
1
?
2
?
1
0
0
0
1
2
1
]
G_y = \begin{bmatrix}-1 & -2 & -1 \\0 & 0 & 0 \\1 & 2 & 1\end{bmatrix}
Gy?=
??101??202??101?
?
在計算完Gx和Gy之后,可以計算每個像素的梯度強度和方向:
G
=
G
x
2
+
G
y
2
G = \sqrt{G_x^2 + G_y^2}
G=Gx2?+Gy2??
θ
=
tan
?
?
1
(
G
y
G
x
)
\theta = \tan^{-1}\left(\frac{G_y}{G_x}\right)
θ=tan?1(Gx?Gy??)
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 讀取圖片
img = cv2.imread("example.jpg", cv2.IMREAD_GRAYSCALE)
# 定義Sobel算子
sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])
# 對圖片進行Sobel邊緣檢測
img_sobel_x = cv2.filter2D(img, -1, sobel_x)
img_sobel_y = cv2.filter2D(img, -1, sobel_y)
# 計算梯度幅值和梯度方向
gradient_magnitude = np.sqrt(img_sobel_x ** 2 + img_sobel_y ** 2)
gradient_magnitude = (gradient_magnitude / gradient_magnitude.max())*255
gradient_direction = np.arctan2(img_sobel_y, img_sobel_x)
gradient_direction = (gradient_direction / gradient_direction.max()) * 255
# 顯示結(jié)果
fig, axs = plt.subplots(1, 4, figsize=(16, 4))
axs[0].imshow(img, cmap="gray")
axs[0].set_title("Original")
axs[1].imshow(img_sobel_x, cmap="gray")
axs[1].set_title("Sobel X")
axs[2].imshow(img_sobel_y, cmap="gray")
axs[2].set_title("Sobel Y")
axs[3].imshow(gradient_magnitude.astype(np.uint8), cmap="gray")
axs[3].set_title("Gradient Magnitude")
plt.show()
可以看到,Gx主要檢測出了豎直方向上的邊緣,Gy主要檢測出了水平方向上的邊緣。
2. Canny算子
Canny算子是在工業(yè)界廣泛使用的邊緣檢測算法,它的主要原理是通過檢測圖像中像素灰度變化的一階導(dǎo)數(shù)來檢測邊緣。
Canny算法主要分為以下幾個步驟:
-
去噪
由于圖像中可能存在噪聲,并且噪聲對邊緣檢測的影響較大(因為噪聲也是高頻信息),首先需要對圖像進行去噪聲處理。常見的方法是使用高斯濾波器對圖像進行平滑處理,以減少噪聲的影響。 -
計算梯度
在圖像平滑之后,需要計算每個像素點的梯度值和方向。常用的方法是使用Sobel算子,對圖像進行水平和垂直方向上的梯度計算。梯度方向的計算可以通過計算水平和垂直梯度值的反正切來得到。 -
非極大值抑制
由于Sobel算子計算的梯度值較大,圖像中可能存在多個方向的梯度,需要進行非極大值抑制來確定每個像素點的主要梯度方向。具體來說,對于每個像素點,沿著其梯度方向上的兩個鄰域像素點進行比較,如果當前像素點的梯度值最大,則保留它,否則將其置為零。 -
雙閾值檢測
經(jīng)過前面的處理之后,圖像中只剩下邊緣可能存在的位置。但是,由于圖像中存在很多噪聲和灰度變化,有些邊緣可能會被誤判為非邊緣。因此需要使用雙閾值檢測來進一步篩選邊緣。將梯度幅值分為兩個閾值:高閾值和低閾值。如果一個像素點的梯度幅值大于高閾值,則被認為是邊緣像素;如果一個像素點的梯度幅值小于低閾值,則被認為是非邊緣像素。如果一個像素點的梯度幅值在兩個閾值之間,則只有它與高閾值相連的像素點才被認為是邊緣像素。 -
邊緣連接
經(jīng)過上述處理之后,圖像中可能還存在一些不連續(xù)的邊緣。因此,需要使用邊緣連接算法將它們連接起來。一種常用的方法是使用基于滯后閾值的連接算法。具體來說,從高閾值像素開始,將與其相鄰的低閾值像素加入到邊緣中,直到不存在低閾。
3. 深度學習算法
3.1 Holistically-Nested Edge Detection(HED)
HED是一個端到端的邊緣檢測模型,總體架構(gòu)如下:
將移除了全連接層的VGG16作為特征提取器,每個stage會外接一個卷積和sigmoid,用于輸出單通道的邊緣檢測結(jié)果,即圖中的Side-output。
-
訓練階段:每個side-output的輸出經(jīng)過上采樣至GT的分辨率,然后分別與GT求loss;考慮到圖像中的邊緣信息占據(jù)比例較小,因此引入了 β \beta β解決類別不均衡的問題,對于非邊緣像素的損失分配較小的權(quán)重。
side部分的總損失等于各個side損失的加權(quán)求和
除了side-output,網(wǎng)絡(luò)還有一個fuse輸出,即將所有side輸出concat后進行卷積(輸出通道為1),然后經(jīng)過sigmoid輸出最終的fuse結(jié)果。fuse輸出也要利用GT進行監(jiān)督,損失函數(shù)為cross-entropy。
整個網(wǎng)絡(luò)的優(yōu)化目標為使side損失和fuse損失最低 -
測試階段:將所有side-output和fuse-output平均后的結(jié)果作為最終的邊緣檢測結(jié)果
3.2 Richer Convolutional Features(RCF)
RCF是針對HED的改進,主要改進有兩點:
- 改進點1:HED的side-output是每個stage最后一個卷積輸出的特征圖經(jīng)過卷積和sigmoid得來的,RCF中改為將每個stage中所有卷積的輸出經(jīng)過
1×1卷積->求和->1×1卷積->sigmoid
后的結(jié)果,利用了更豐富的特征信息。
文章來源:http://www.zghlxwxcb.cn/news/detail-434516.html
- 改進點2:設(shè)置一個閾值
η
\eta
η,小于閾值的不計算損失(分不清到底是邊緣還是非邊緣),計算非邊緣部分的損失時分配一個較小的權(quán)重
α
\alpha
α,計算邊緣部分的損失時分配一個較大的權(quán)重
β
\beta
β
參考資料
[1] Holistically-Nested Edge Detection
[2] Richer convolutional features for edge detection文章來源地址http://www.zghlxwxcb.cn/news/detail-434516.html
到了這里,關(guān)于【數(shù)字圖像處理】邊緣檢測的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!