OpenCV---Canny邊緣提取


一:Canny算法介紹

Canny 的目標是找到一個最優的邊緣檢測算法,最優邊緣檢測的含義是:
好的檢測- 算法能夠盡可能多地標識出圖像中的實際邊緣。
好的定位- 標識出的邊緣要盡可能與實際圖像中的實際邊緣盡可能接近。
最小響應- 圖像中的邊緣只能標識一次,並且可能存在的圖像噪聲不應標識為邊緣。

推文:Canny邊緣檢測算法原理及其VC實現詳解(一)

1.高斯模糊--GaussianBlur  消除噪聲。 一般情況下,使用高斯平滑濾波器卷積降噪。,因為canny是對噪聲敏感的算法,所以先降噪,但是降噪不要太過,以免丟失 2.灰度轉換--cvtColor   3.計算梯度--Sobel/Scharr 4.非最大信號抑制 5.高低閾值輸出二值圖像

補充:

非最大信號抑制

在Canny算法中,非極大值抑制是進行邊緣檢測的重要步驟,通俗意義上是指尋找像素點局部最大值,將非極大值點所對應的灰度值置為0
sobel算子中有一個x,y
根據x,y可以求出一個θ角度
1.要進行非極大值抑制,就首先要確定像素點C的灰度值在其8值鄰域內是否為最大。是最大則下一步
2.圖中藍色的線條方向為C點的梯度方向,這樣就可以確定其局部的最大值肯定分布在這條線上,也即出了C點外,梯度方向的交點dTmp1和dTmp2這兩個點的值也可能會是局部最大值。
因此,判斷C點灰度與這兩個點灰度大小即可判斷C點是否為其鄰域內的局部最大灰度點
3.如果經過判斷,C點灰度值小於這兩個點中的任一個,那就說明C點不是局部極大值,那么則可以排除C點為邊緣。
完成非極大值抑制后,會得到一個二值圖像,非邊緣的點灰度值均為0,可能為邊緣的局部灰度極大值點可設置其灰度為128
根據下文的具體測試圖像可以看出,這樣一個檢測結果還是包含了很多由噪聲及其他原因造成的假邊緣。因此還需要進一步的處理。

高低閾值輸出二值圖像

 二:Canny邊緣提取實現

def edge_demo(image):
    #1.高斯模糊 blurred = cv.GaussianBlur(image,(3,3),0) #2.灰度轉換 gray = cv.cvtColor(blurred,cv.COLOR_RGB2GRAY) #3.計算梯度 xgrad = cv.Sobel(gray,cv.CV_16SC1,1,0) #canny方法API要求不允許使用浮點數 ygrad = cv.Sobel(gray,cv.CV_16SC1,0,1) #4.Canny方法中包含非最大信號抑制和雙閾值輸出 edge_output = cv.Canny(xgrad,ygrad,50,150) #50是低閾值,150是高閾值 cv.imshow("Canny Edge",edge_output)

    dst = cv.bitwise_and(image,image,mask=edge_output)  #相與,獲取顏色
    cv.imshow("Color Edge",dst)

src = cv.imread("./g.png")  #讀取圖片
cv.namedWindow("input image",cv.WINDOW_AUTOSIZE) #創建GUI窗口,形式為自適應
cv.imshow("input image",src) #通過名字將圖像和窗口聯系

edge_demo(src)

cv.waitKey(0) #等待用戶操作,里面等待參數是毫秒,我們填寫0,代表是永遠,等待用戶操作
cv.destroyAllWindows() #銷毀所有窗口

 使用Canny計算梯度

def edge_demo(image):
 #1.高斯模糊 blurred = cv.GaussianBlur(image,(3,3),0) #2.灰度轉換 gray = cv.cvtColor(blurred,cv.COLOR_RGB2GRAY) #3.直接傳入灰度圖像,Canny方法中包含計算梯度,非最大信號抑制和雙閾值輸出 edge_output = cv.Canny(gray,50,150) #50是低閾值,150是高閾值
    cv.imshow("Canny Edge",edge_output)

    dst = cv.bitwise_and(image,image,mask=edge_output)
    cv.imshow("Color Edge",dst)

 相關知識補充

(一)Canny方法

(1)需要我們求出梯度

Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edges
使用帶自定義圖像漸變的Canny算法在圖像中查找邊緣,

其函數原型為:Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]]) -> edges

dx參數表示輸入圖像的x導數(x導數滿足16位,選擇CV_16SC1或CV_16SC3)

dy參數表示輸入圖像的y導數(y導數滿足16位,選擇CV_16SC1或CV_16SC3)。

threshold1參數表示設置的低閾值。

threshold2參數表示設置的高閾值,一般設定為低閾值的3倍 (根據Canny算法的推薦)。

edges參數表示輸出邊緣圖像,單通道8位圖像。

L2gradient參數表示L2gradient參數表示一個布爾值,如果為真,則使用更精確的L2范數進行計算(即兩個方向的倒數的平方和再開方),否則使用L1范數(直接將兩個方向導數的絕對值相加)。

(2)直接調用Canny算法在單通道灰度圖像中查找邊緣,

def Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None): # real signature unknown; restored from __doc__
image參數表示8位輸入圖像。

threshold1參數表示設置的低閾值。

threshold2參數表示設置的高閾值,一般設定為低閾值的3倍 (根據Canny算法的推薦)。

edges參數表示輸出邊緣圖像,單通道8位圖像。

apertureSize參數表示Sobel算子的大小。

L2gradient參數表示一個布爾值,如果為真,則使用更精確的L2范數進行計算(即兩個方向的倒數的平方和再開方),否則使用L1范數(直接將兩個方向導數的絕對值相加)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM