opencv-python-學習筆記十四(Canny邊緣檢測)


原理

Canny邊緣檢測是一種常用的邊緣檢測算法。由 John F. Canny提出

這是一個多階段的算法,我們將經歷每個階段。

1.降低噪音

由於邊緣檢測容易受到圖像中噪聲的影響,第一步是用5x5高斯濾波器去除圖像中的噪聲。我們在前幾章已經見過了。

2.尋找圖像的強度梯度

然后對平滑后的圖像進行水平方向和垂直方向的Sobel核濾波,得到水平方向(Gx)和垂直方向(Gy)的一階導數。這兩幅圖像中,我們可以發現每個像素的邊緣梯度和方向如下:

梯度方向總是垂直於邊緣,它是四角之一,代表垂直、水平和兩個對角線方向。

3.非極大值抑制

得到梯度大小和方向后,對圖像進行全面掃描,去除非邊界點。在每個像素處,看這個點的梯度是不是周圍具有相同梯 度方向的點中最大的,查看下圖:

 

點A在邊緣上(垂直方向)。梯度方向垂直於邊緣。點B和點C在梯度方向上,因此,點A與點B和點C進行檢查,看它是否形成局部最大值,如果是,則將其考慮到下一階段,否則將抑制它(使其為零)。

簡而言之,您得到的結果是一個具有“細邊”的二進制圖像。

 

4.滯后閾值

現在要確定那些邊界才是真正的邊界,為此,我們需要兩個閾值,minVal和maxVal。任何強度梯度大於maxVal的邊都肯定是邊,小於minVal的邊肯定是非邊,所以丟棄。位於這兩個閾值之間的根據它們的連接性對邊緣或非邊緣進行分類(如果介於兩者之間的話,就要看這個點是 否與某個被確定為真正的邊界點相連,如果是就認為它也是邊界點,如果不是 就拋棄。如下圖:

A 高於閾值 maxVal 所以是真正的邊界點。C 雖然低於 maxVal 但高於minVal 並且與 A 相連,所以也被認為是真正的邊界點。而 B 就會被拋棄,因 為他不僅低於 maxVal 而且不與真正的邊界點相連。所以選擇合適的 maxVal 和 minVal 對於能否得到好的結果非常重要。 在這一步一些小的噪聲點也會被除去,因為我們假設邊界都是一些長的線段。

 

OpenCV中的Canny邊緣檢測

OpenCV將所有這些都放在一個函數cv.Canny中。第一個參數是輸入圖像。第二個和第三個參數分別是minVal和maxVal。第三個參數是aperture_size,它是用來尋找圖像梯度的Sobel內核的大小,默認值是3。最后一個參數是L2gradient,它指定了求梯度大小的方程。

函數:

edges=cv.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]])

edges=cv.Canny(dx, dy, threshold1, threshold2[, edges[, L2gradient]])

參數:

dx 16-bit 輸入圖像的x導數 (CV_16SC1 or CV_16SC3).
dy 16-bit 輸入圖像的y導數 (和dx有相同類型).
edges 輸出的邊緣地圖; 單通道8-bit 圖像, 與輸入圖像有相同大小。
threshold1 第一個閾值,低閾值                                                                      
threshold2 第二個閾值,高閾值
L2gradient 如果為真,則使用更精確的L2范數進行計算(即兩個方向的倒數的平方和再開方),否則使用L1范數(直接將兩個方向導數的絕對值相加)。

舉例:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

img = cv.imread('4.jpg', 0)
edges = cv.Canny(img, 100, 200)
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122), plt.imshow(edges, cmap='gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.show()

 


免責聲明!

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



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