opencv邊緣檢測——乘風破浪

三天不練手生,一月不看傻眼

歡迎關注,敬請點贊!

乘風破浪的姐姐

原理

Canny邊緣檢測是一種非常流行的邊緣檢測算法,是John F.Canny在1986年提出的。它是一個由很多步構成的算法,我們接下來會逐步介紹:

(1) 噪聲去除

由於邊緣檢測很容易受到噪聲影響,所以第一步是使用5x5的高斯濾波器去除噪聲。

(2) 計算圖像梯度

對平滑後的圖像使用 Sobel 算子,計算水平方向和豎直方向的一階導數(圖像梯度)。根據得到的這兩幅梯度圖(Gx和Gy)找到邊界的梯度和方向,公式如下:
EdgeGradient(G)=Gx2+Gy2  (L2)Angle(θ)=tan1(GxGy) Edge-Gradient(G) = \sqrt{G_x^2 + G_y^2}\ \ ——嶺迴歸(L2範數)\\ Angle(\theta) = \tan^{-1}(\frac{G_x}{G_y})
梯度方向被歸爲四類:垂直、水平、兩個對角線。

梯度的方向通常是與邊界垂直

(3) 非極大值抑制

在獲得梯度的方向和大小之後,應該對整幅圖像做一個掃描,去除那些非邊界上的點。對每一個像素進行檢查,看這個點的梯度是不是周圍具有相同梯度方向的點中最大的。如下圖所示:
窄邊界二值圖像
A點在邊界上,梯度方向是邊界的法向量。點B和點C在梯度方向上面,所以拿點A來檢測點B和C是否形成了本地最大值,如果形成最大值,那麼就進行下一步,否則進行抑制(賦值爲0)。
簡單的說,得到了二值圖像的邊界,現在得到的是一個包含“窄邊界”的二值圖像。

(4) 滯後閾值

現在要確定哪些邊界纔是真正的邊界。這時我們需要設置兩個閾值:minVal和maxVal。

當圖像的灰度梯度高於maxVal時被認爲是真的邊界,那些低於 minVal 的邊界會被拋棄。如果介於兩者之間的話,就要看這個點是否與某個被確定爲真正的邊界點相連,如果是就認爲它也是邊界點,如果不是就拋棄。如下圖:
滯後閾值
A高於閾值maxVal,所以是真正的邊界點。C雖然低於maxVal但高於minVal,並且與A相連,所以也被認爲是真正的邊界點。而B就會被拋棄,因爲它不僅低於maxVal而且不與真正的邊界點相連。所以選擇合適的maxVal和minVal對於能否得到好的結果非常重要。在這一步一些小的噪聲點也會被除去,因爲我們假設邊界都是一些長的線段。

OpenCV中的Canny邊界檢測

返回頂部
在OpenCV中只需要一個函數:cv2.Canny(),就可以完成以上幾步。
Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None)

讓我們看如何使用這個函數:
第一個參數是輸入圖像;
第二和第三個分別是minVal和maxVal;
第四個參數用來設置Sobel卷積核的大小,默認值爲3;
最後一個參數是L2gradient,它可以用來設定求梯度大小的方程:如果設爲True,就會使用我們上面提到過的方程(L2範數);否則使用方程:
EdgeGradient(G)=Gx+Gy  Lasso(L1)Edge−Gradient(G) = |G_x|+|G_y|\ \ ——Lasso迴歸(L1範數)代替,默認值爲False。

代碼示例一(在一起)

在一起

import cv2
from matplotlib import pyplot as plt


img = cv2.imread('3.jpg', 0)

edges = cv2.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()

Edge在一起

代碼示例二(乘風破浪)

返回頂部
(小練習——滾動條調節minVal和maxVal)

import cv2


def nothing(x):
    pass

if __name__ == '__main__':
    img = cv2.imread('chengfengpolang.jpg')
    edges = img
    cv2.namedWindow('Original')
    cv2.namedWindow('Canny')
    cv2.createTrackbar('Min', 'Canny', 0, 100, nothing)
    cv2.createTrackbar('Max', 'Canny', 100, 200, nothing)

    while True:
        cv2.imshow('Original', img)
        cv2.imshow('Canny', edges)
        minVal = cv2.getTrackbarPos('Min', 'Canny')
        maxVal = cv2.getTrackbarPos('Max', 'Canny')
        edges = cv2.Canny(img, minVal, maxVal)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cv2.destroyAllWindows()

乘風破浪

隨想

那些以局外人心態來指責中國程序員做不出來MatLab、編程語言的同胞們,自己的工作是否做到自己滿意?有空可以學學編程,練練腦子。

正如那些批判國足的人們,可以下場踢踢足球,流流汗。

不過,中國的程序員和國足們,確實也該努力去披荊斬棘、乘風破浪!!!
街邊足球
歡迎關注,敬請點贊!
返回頂部

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章