天天看點

Python+OpenCV:Canny邊緣檢測

Python+OpenCV:Canny邊緣檢測

理論

Canny邊緣檢測是目前比較流行的邊緣檢測算法,它由John F. Canny發明。

1. 這是一個多階段的算法。

2. 降噪:由于邊緣檢測容易受到圖像中噪聲的影響,第一步使用5x5高斯濾波器去除圖像中的噪聲。

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

Python+OpenCV:Canny邊緣檢測

梯度方向總是垂直于邊緣。它是圓形的四個角之一,代表垂直,水準和兩個對角線方向。

4. Non-maximum抑制:在獲得梯度大小和方向後,對圖像進行全面掃描,以便删除任何不需要的像素(可能不構成邊緣)。

為此,在每個像素處,檢查像素是否在梯度方向上的鄰域記憶體在局部極大值。檢視下圖:

Python+OpenCV:Canny邊緣檢測

點A在邊緣上(垂直方向)。梯度方向垂直于邊緣。點B和點C是梯度方向的。是以,對點A和點B、C進行檢驗,看它是否形成局部極大值。如果是,則考慮進入下一階段,否則,它将被抑制(設為零)。

簡而言之,你得到的結果是一個“薄邊緣”的二值圖像。

5. 滞後門檻值(Hysteresis Thresholding):這個階段決定哪些是真正的邊,哪些不是邊。為此,我們需要兩個門檻值,minVal和maxVal。

任何強度梯度大于maxVal的邊肯定是邊,而低于minVal的邊肯定是非邊,是以被丢棄。

那些位于這兩個門檻值之間的邊是根據它們的連接配接性而分類為邊緣或非邊緣。如果它們連接配接到“确定邊緣”像素,它們被認為是邊緣的一部分。否則,它們也會被丢棄。請看下圖:

Python+OpenCV:Canny邊緣檢測

邊A在maxVal的上方,是以被認為是“确定的邊”。盡管C邊在maxVal下方,但它與A邊相連,是以這條邊也被認為是有效邊,我們得到了那條完整的曲線。但邊B雖然在minVal之上,且與邊C處于同一區域,但它沒有連接配接到任何“sure-edge”,是以被丢棄。是以,我們必須相應地選擇minVal和maxVal以獲得正确的結果,這是非常重要的。

這個階段也可以假設邊緣是長線,而去除小像素噪聲。

最終,我們得到的是圖像中的強邊。

示例

####################################################################################################
# Canny邊緣檢測(Canny Edge Detection)
def lmc_cv_canny_edge_detection():
    """
        函數功能: Canny邊緣檢測(Canny Edge Detection).
    """

    # 讀取圖像
    image = lmc_cv.imread('D:/99-Research/Python/Image/Lena.jpg')
    image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2GRAY)

    # Canny邊緣檢測(Canny Edge Detection)
    edges_image = lmc_cv.Canny(image, 100, 250, L2gradient=False)

    # 顯示圖像
    pyplot.figure('Image Display')
    titles = ['Original Image', 'Canny Edge Image']
    images = [image, edges_image]
    for i in range(2):
        pyplot.subplot(1, 2, i + 1)
        pyplot.imshow(images[i], 'gray')
        pyplot.title(titles[i])
        pyplot.xticks([])
        pyplot.yticks([])
    pyplot.show()

    # 根據使用者輸入儲存圖像
    if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
        # 銷毀視窗
        pyplot.close()
    return
           
Python+OpenCV:Canny邊緣檢測