一:Canny算法介紹
Canny 的目標是找到一個最優的邊緣檢測算法,最優邊緣檢測的含義是: 好的檢測- 算法能夠盡可能多地標識出圖像中的實際邊緣。 好的定位- 標識出的邊緣要盡可能與實際圖像中的實際邊緣盡可能接近。 最小響應- 圖像中的邊緣只能標識一次,並且可能存在的圖像噪聲不應標識為邊緣。
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范數(直接將兩個方向導數的絕對值相加)。