
邊緣檢測是一種影像處理技術,用于識別影像中目標或區域的邊界(邊緣),邊緣是影像中最重要的特征之一,我們通過影像的邊緣來了解影像的基本結構,因此,計算機視覺處理管道在應用中廣泛地使用邊緣檢測,
1.如何檢測邊緣?
邊緣的特征是像素強度的突然變化,為了檢測邊緣,我們需要在鄰近的像素中尋找這些變化,來吧,讓我們探討一下OpenCV中可用的兩種重要邊緣檢測演算法的使用:Sobel邊緣檢測和Canny邊緣檢測,我們將討論這些理論,并演示它們在OpenCV中的使用,
2.簡單的代碼示例
首先,看一看演示邊緣檢測的代碼,我們將詳細討論每一行代碼,以便您能夠完全理解它,
(1)Python
import cv2
# 讀取原始影像
img = cv2.imread('test.jpg')
# 顯示原始影像
cv2.imshow('Original', img)
cv2.waitKey(0)
# 轉換為灰度圖
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 模糊影像以更好地檢測邊緣
img_blur = cv2.GaussianBlur(img_gray, (3,3), 0)
# Sobel邊緣檢測
sobelx = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=0, ksize=5) # X軸上的Sobel邊緣檢測
sobely = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=0, dy=1, ksize=5) # Y軸上的Sobel邊緣檢測
sobelxy = cv2.Sobel(src=img_blur, ddepth=cv2.CV_64F, dx=1, dy=1, ksize=5) # 結合X和Y的Sobel邊緣檢測
# 顯示Sobel邊緣檢測影像
cv2.imshow('Sobel X', sobelx)
cv2.waitKey(0)
cv2.imshow('Sobel Y', sobely)
cv2.waitKey(0)
cv2.imshow('Sobel X Y using Sobel() function', sobelxy)
# Canny邊緣檢測
edges = cv2.Canny(image=img_blur, threshold1=100, threshold2=200)
# 顯示Canny邊緣檢測影像
cv2.imshow('Canny Edge Detection', edges)
cv2.waitKey(0)
(2)C++
#include <opencv2/opencv.hpp>
#include <iostream>
// 命名空間
using namespace std;
using namespace cv;
int main()
{
// 讀取原始影像
Mat img = imread("test.jpg");
// 顯示原始影像
imshow("original Image", img);
waitKey(0);
// 轉換為灰度圖
Mat img_gray;
cvtColor(img, img_gray, COLOR_BGR2GRAY);
// 模糊影像以更好地檢測邊緣
Mat img_blur;
GaussianBlur(img_gray, img_blur, Size(3,3), 0);
// Sobel邊緣檢測
Mat sobelx, sobely, sobelxy;
Sobel(img_blur, sobelx, CV_64F, 1, 0, 5);
Sobel(img_blur, sobely, CV_64F, 0, 1, 5);
Sobel(img_blur, sobelxy, CV_64F, 1, 1, 5);
// 顯示Sobel邊緣檢測影像
imshow("Sobel X", sobelx);
waitKey(0);
imshow("Sobel Y", sobely);
waitKey(0);
imshow("Sobel XY using Sobel() function", sobelxy);
waitKey(0);
// Canny 邊緣檢測
Mat edges;
Canny(img_blur, edges, 100, 200, 3, false);
// 顯示Canny邊緣檢測影像
imshow("Canny edge detection", edges);
waitKey(0);
destroyAllWindows();
return 0;
}





查看Sobel影像在x方向上主要識別垂直邊緣(即那些在x方向上梯度最大的),而在y方向上則表示水平邊(即在y方向上梯度最大的),仔細看看這兩張照片上老虎的條紋,注意,在Sobel影像中,條紋的垂直邊緣在x方向上更加明顯,對Sobel影像進行兩個方向的梯度,將原始影像提取為邊緣結構表示,使其結構完整性保持不變,
我們使用的下限為100,上限為200,正如你所看到的,該演算法已經識別出了影像中的主要邊緣,在這個程序中消除了那些對整體結構不太重要的邊緣,然而,結果可以很容易地調整,所以去嘗試不同的影像,改變模糊的數量,并嘗試不同的閾值來獲得自己的感覺,
3.Sobel邊緣檢測
Sobel邊緣檢測是應用最廣泛的邊緣檢測演算法之一,Sobel算子檢測像素強度突然變化的邊緣,如下圖所示,

當我們畫出強度函式的一階導數時,強度的增加就更加明顯了,

從上圖可以看出,在梯度高于某一特定閾值的區域可以檢測到邊緣,此外,導數的突然變化也會顯示像素強度的變化,記住這個,我們可以用3×3核來近似導數,我們使用一個核來檢測X方向上像素強度的突然變化,另一個在Y方向上,
這些是用于Sobel邊緣檢測的核:


當這些核與原始影像進行卷積時,就得到了Sobel邊緣影像.
- 如果我們只使用垂直核,卷積產生一個Sobel影像,邊緣在x方向增強
- 使用水平核生成一個Sobel影像,在y方向上增強邊緣,
設
G
x
G_x
Gx?和
G
y
G_y
Gy?分別表示x和y方向上的強度梯度,如果A和B表示上面定義的X和Y核:
G
x
=
A
?
I
G
y
=
B
?
I
G_x = A * I\\G_y = B * I
Gx?=A?IGy?=B?I其中
?
*
?為卷積算子,
I
I
I為輸入影像,
梯度幅值 G G G的最終近似可計算為: G = G x 2 + G y 2 G=\sqrt{G^2_x+G^2_y} G=Gx2?+Gy2? ?
梯度的方向可以近似為: Θ = a r c t a n ( G y G x ) \Theta=arctan(\frac{G_y}{G_x}) Θ=arctan(Gx?Gy??)
在下面的代碼示例中,我們使用Sobel()函式進行計算:Sobel(src, ddepth, dx, dy)
引數ddepth指定輸出影像的精度,而dx和dy指定每個方向的導數的順序,例如:
- 如果
dx=1 dy=0,我們計算x方向上的一階Sobel像, - 如果
dx=1 dy=1,我們計算兩個方向上的一階Sobel像 - 如果
dx=0 dy=1,我們計算y方向上的一階Sobel像,
4.Canny邊緣檢測
Canny邊緣檢測是當今最流行的邊緣檢測方法之一,因為它具有很強的魯棒性和靈活性,這一程序分為四個階段,包括:
- 降噪
- 計算影像的強度梯度
- 偽邊抑制
- 遲滯閾值法
1)降噪
在Canny邊緣檢測中,高斯模糊濾波器被用來去除或最小化不必要的細節,這些細節可能導致不理想的邊緣,看看下面兩張圖片中的老虎,右邊的圖片應用了高斯模糊,正如你所看到的,它看起來有點模糊,但仍然保留了大量的細節,從這些細節可以計算出邊緣,

2)計算影像的強度梯度
一旦影像被平滑(模糊),它被一個包含水平和垂直的Sobel核過濾,然后使用這些濾波操作的結果來計算每個像素的強度梯度大小(
G
G
G)和方向(
Θ
\Theta
Θ),如下所示,
G
=
G
x
2
+
G
y
2
Θ
=
a
r
c
t
a
n
(
G
y
G
x
)
G=\sqrt{G^2_x+G^2_y}\\\Theta=arctan(\frac{G_y}{G_x})
G=Gx2?+Gy2?
?Θ=arctan(Gx?Gy??)
然后將梯度方向四舍五入到最近的45度角,下圖(右)顯示了這個組合處理步驟的結果,

3)偽邊抑制
在降低噪聲和計算強度梯度之后,這一步的演算法使用了一種稱為非最大邊緣抑制的技術來過濾掉不需要的像素(實際上可能不構成邊緣),為了做到這一點,每個像素與它的鄰近像素比較,在正和負梯度方向,如果當前像素的梯度大小大于其相鄰像素,則保持不變,否則,當前像素的大小設定為零,下面的圖片演示了一個示例,如你所見,老虎皮毛的許多邊緣都被明顯榷訓了,

4)遲滯閾值法
在Canny邊緣檢測的最后一步中,將梯度值與兩個較小的閾值進行比較,
- 如果梯度幅值高于較大的閾值,則這些像素與強邊緣相關聯,并包含在最終的邊緣圖中,
- 如果梯度幅值低于較小的閾值,則像素被抑制,并從最終的邊緣圖中排除,
- 所有其他像素,其梯度大小落在這兩個閾值之間,被標記為“弱”邊緣(即它們成為最終邊緣圖中的候選者),
- 如果“弱”像素與那些與強邊緣相關的像素相連接,那么它們也會被包含在最終的邊緣圖中,
面是使用OpenCV應用Canny邊緣檢測的語法:Canny(image, threshold1, threshold2)
Canny()函式實作了上面描述的方法,我們只提供Canny邊緣檢測演算法使用的兩個閾值,OpenCV處理所有實作細節,在呼叫Canny()函式之前,不要忘記模糊影像,這是一個強烈推薦的預處理步驟,
在性能方面,Canny邊緣檢測得到了最好的結果,因為它不僅使用了Sobel邊緣檢測,而且還使用了非最大抑制和遲滯閾值,這為在演算法的最后階段如何識別和連接邊提供了更多的靈活性,
總結
我們討論了什么使邊緣檢測成為如此重要的影像處理技術,并重點了解了它的兩個最重要的演算法(Sobel邊緣檢測和Canny邊緣檢測),在演示它們在OpenCV中的使用時,我們強調了為什么模糊是如此重要的預處理步驟,
您還看到了Canny邊緣檢測實際上是如何使用Sobel算子來計算數值導數的,并且具有魯棒性和靈活性,甚至使用非最大抑制和遲滯閾值來獲得最大優勢,最后,您了解了為什么Canny邊緣檢測是執行邊緣檢測的首選和最廣泛使用的方法,
參考目錄
https://learnopencv.com/edge-detection-using-opencv/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/302961.html
標籤:AI
上一篇:不會真有人覺得聊天機器人難吧——微調BERT模型得到句子間的相似度
下一篇:貝葉斯定理簡單理解
