python中opencv?Canny邊緣檢測
Canny邊緣檢測
Canny邊緣檢測是一種使用多級邊緣檢測算法檢測邊緣的方法。
OpenCV提供了函數(shù)cv2.Canny()實現(xiàn)Canny邊緣檢測。
Canny邊緣檢測基礎(chǔ)
Canny邊緣檢測分為如下幾個步驟:
- 去噪。噪聲會影響邊緣檢測的準(zhǔn)確性,因此首先要將噪聲過濾掉。
- 計算梯度的幅度與方向
- 非極大值抑制,即適當(dāng)?shù)刈屵吘?ldquo;變瘦”
- 確定邊緣。使用雙閾值算法確定最終的邊緣信息
高斯濾波去除圖像噪聲
圖像邊緣非常容易受到噪聲的干擾,因此為了避免檢測到錯誤的邊緣信息,通常需要對圖像進行濾波以去除噪聲。
濾波的目的是平滑一些紋理較弱的非邊緣區(qū)域,以便得到更準(zhǔn)確的邊緣。在實際處理過程中,通常采用高斯濾波去除圖像中的噪聲。在濾波過程中,通過濾波器對像素點周圍的像素計算加權(quán)平均值,獲取最終濾波結(jié)果。對于高斯濾波器,越臨近中心的點,權(quán)值越大。
濾波器的大小也是可變的,高斯核的大小對于邊緣檢測的效果具有很重要的作用。濾波器的核越大,邊緣信息對于噪聲的敏感度就越低。不過,核越大,邊緣檢測的定位錯誤也會隨之增加。通常來說,一個5×5的核能夠滿足大多數(shù)的情況。
計算梯度
關(guān)注梯度的方向,梯度的方向與邊緣的方向是垂直的。
邊緣檢測算子返回水平方向的Gx和垂直方向的Gy。
梯度的幅度G和方向Θ(用角度值表示)為:

atan2(·)表示具有兩個參數(shù)的arctan函數(shù)。
梯度的方向總是與邊緣垂直的,通常就近取值為水平(左、右)、垂直(上、下)、對角線(右上、左上、左下、右下)等8個不同的方向。
在計算梯度時,我們會得到梯度的幅度和角度(代表梯度的方向)兩個值。
梯度的表示法: 其中,每一個梯度包含幅度和角度兩個不同的值。為了方便觀察,這里使用了可視化表示方法。

左上角頂點的值“2↑”實際上表示的是一個二元數(shù)對“(2, 90)”,表示梯度的幅度為2,角度為90°。
非極大值抑制
在獲得了梯度的幅度和方向后,遍歷圖像中的像素點,去除所有非邊緣的點。
在具體實現(xiàn)時,逐一遍歷像素點,判斷當(dāng)前像素點是否是周圍像素點中具有相同梯度方向的最大值,并根據(jù)判斷結(jié)果決定是否抑制該點。
通過以上描述可知,該步驟是邊緣細(xì)化的過程。針對每一個像素點:
- 如果該點是正/負(fù)梯度方向上的局部最大值,則保留該點。
- 如果不是,則抑制該點(歸零)。
(梯度方向垂直于邊緣)
“正/負(fù)梯度方向上”是指相反方向的梯度方向。
對于同一個方向的若干個邊緣點,基本上僅保留了一個,因此實現(xiàn)了邊緣細(xì)化的目的。
應(yīng)用雙閾值確定邊緣
完成上述步驟后,圖像內(nèi)的強邊緣已經(jīng)在當(dāng)前獲取的邊緣圖像內(nèi)。但是,一些虛邊緣可能也在邊緣圖像內(nèi)。
這些虛邊緣可能是真實圖像產(chǎn)生的,也可能是由于噪聲所產(chǎn)生的。對于后者,必須將其剔除。設(shè)置兩個閾值,其中一個為高閾值maxVal,另一個為低閾值minVal。根據(jù)當(dāng)前邊緣像素的梯度值(指的是梯度幅度)與這兩個閾值之間的關(guān)系,判斷邊緣的屬性。
具體步驟為:
- 如果當(dāng)前邊緣像素的梯度值大于或等于maxVal,則將當(dāng)前邊緣像素標(biāo)記為強邊緣。
- 如果當(dāng)前邊緣像素的梯度值介于maxVal與minVal之間,則將當(dāng)前邊緣像素標(biāo)記為虛邊緣(需要保留)。
- 如果當(dāng)前邊緣像素的梯度值小于或等于minVal,則抑制當(dāng)前邊緣像素。
在上述過程中,我們得到了虛邊緣,需要對其做進一步處理。一般通過判斷虛邊緣與強邊緣是否連接,來確定虛邊緣到底屬于哪種情況。
通常情況下,如果一個虛邊緣:
- 與強邊緣連接,則將該邊緣處理為邊緣。
- 與強邊緣無連接,則該邊緣為弱邊緣,將其抑制。

高閾值maxVal和低閾值minVal不是固定的,需要針對不同的圖像進行定義。
Canny函數(shù)及使用
OpenCV提供了函數(shù)cv2.Canny()來實現(xiàn)Canny邊緣檢測,其語法形式如下:
edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])
- edges為計算得到的邊緣圖像。
- image為8位輸入圖像。
- threshold1表示處理過程中的第一個閾值。
- threshold2表示處理過程中的第二個閾值。
- apertureSize表示Sobel算子的孔徑大小。
- L2gradient為計算圖像梯度幅度(gradient magnitude)的標(biāo)識。其默認(rèn)值為False。如果為True,則使用更精確的L2范數(shù)進行計算(即兩個方向的導(dǎo)數(shù)的平方和再開方),否則使用L1范數(shù)(直接將兩個方向?qū)?shù)的絕對值相加)。

**例子:**使用函數(shù)cv2.Canny()獲取圖像的邊緣,并嘗試使用不同大小的threshold1和threshold2,觀察獲取到的邊緣有何不同。
import cv2 o=cv2.imread("./img/hand1.png", cv2.IMREAD_GRAYSCALE) r1=cv2.Canny(o,128,200) r2=cv2.Canny(o,32,128) cv2.imshow("original", o) cv2.imshow("result1", r1) cv2.imshow("result2", r2) cv2.waitKey() cv2.destroyAllWindows()
當(dāng)函數(shù)cv2.Canny()的參數(shù)threshold1和threshold2的值較小時,能夠捕獲更多的邊緣信息。
到此這篇關(guān)于python中opencv Canny邊緣檢測的文章就介紹到這了,更多相關(guān)opencv Canny內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python實現(xiàn)自動收集參數(shù)的技巧分享
在Python中,充分利用函數(shù)參數(shù)的自動收集和靈活處理,是寫出高效且易維護代碼的關(guān)鍵之一,本文將深入研究Python函數(shù)參數(shù)的收集方式,感興趣的小伙伴可以了解下2023-12-12
使用Filter過濾python中的日志輸出的實現(xiàn)方法
這篇文章主要介紹了使用Filter過濾python中的日志輸出,本文給大家分享幾種方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-07-07

