OpenCV(4)圖像邊緣檢測

上一章節,我們在使用圖像輪廓發現的時候使用了圖像邊緣檢測,一次來提高圖像輪廓發現的準確率。事實上在計算機的各個領域都有圖像邊緣檢測的身影。邊緣檢測一大優點就在於可以大幅度減少數據量,並且提出可以認爲不相關的信息,保留了圖像的結構屬性。邊緣檢測的方法有很多,但是絕大部分都可以分爲兩大類,第一類是基於搜索,也就是通過尋找圖像一階導數中的最大值和最小值來檢測邊界,通常是定位在梯度最大的方向。其次是基於零穿越的方法,其通過尋找圖像二階導數零穿越來尋找便捷,通常是Laplacian過零點或者非線性差分表示的過零點。(以下內容引用自百度百科

邊緣可能與視角有關—— 也就是說邊緣可能隨着視角不同而變化,典型地反映在場景、物體的幾何形狀一個將另一個遮擋起來,也可能與視角無關——這通常反映被觀察物體的屬性如表面紋理和表面形狀。在二維乃至更高維空間中,需要考慮透視投影的影響。

在我們需要檢測表面紋理和表面形狀時,我們往往需要更細緻的檢測,比如基於二階導數的Canny,但是很多時候簡單的基於一階導數的算子想過可能更好。不同的算子由於其具體算法不同,實際效果也存在比較大的差距。具體情況還需要具體處理。

Sobel 邊緣檢測

基本原理

Sobel算子是幾種邊緣檢測算子中最簡單的,其由兩組33矩陣組成(這裏用水平矩陣sobelx,垂直矩陣sobely表示)。將兩組算子與圖像(這裏用A表示)做平面卷積就可以的得到垂直和水平的亮度差分近似值。然後Gx=sobelxA,Gy=sobely*A,最終得到的結果就是:
Gx=Gx2+Gy22 G_x=\sqrt[2]{G_x^2+G_y^2}
Sobel相比於其他算子的優勢在於比較簡單和快速,只需要三次簡單運算就可以得到(Sobel需要灰度圖,所以更準確的說想要使用Sobel還需要灰度圖轉換的步驟)。同時Sobel也可以只檢測垂直方向或者只檢測水平方向。因此當我們不需要注意細紋理或者只需要單方向檢測的時候不妨使用一下Sobel。

下面是Sobel在OpenCV中的實現,這裏我們還是使用之前的OpenCV中自帶的水果分屍圖,下面是核心代碼,經過了這麼多次的我們就不再多寫數據加載,灰度轉換,窗口等待這些基本內容了:

代碼實現

# 使用sobel算子並進行邊緣檢測
sobelx = cv2.Sobel(gray, cv2.CV_64F, 1, 0)
sobely = cv2.Sobel(gray, cv2.CV_64F, 0, 1)

sobelx = numpy.uint8(numpy.absolute(sobelx))
sobely = numpy.uint8(numpy.absolute(sobely))

# 得帶最終結果
sobelcombine = cv2.bitwise_or(sobelx,sobely)

# 展示效果並保存
cv2.imshow("Edge detection by Sobel", numpy.hstack([gray,sobelx,sobely, sobelcombine]))
cv2.imwrite("1_edge_by_sobel.jpg", numpy.hstack([gray,sobelx,sobely, sobelcombine]))

Sobel 邊緣檢測 OpenCV

Canny邊緣檢測

基本原理

以下內容引用自百度百科

Canny邊緣檢測算子是John F. Canny於1986年開發出來的一個多級邊緣檢測算法。更爲重要的是Canny創立了“邊緣檢測計算理論”(computational theory of edge detection)解釋這項技術如何工作。

Canny的目標是找到一個最優的邊緣檢測算法,而這個最優邊緣檢測算法的含義是指三個方面:

  • 好的檢測- 算法能夠儘可能多地標識出圖像中的實際邊緣。
  • 好的定位- 標識出的邊緣要與實際圖像中的實際邊緣儘可能接近。
  • 最小響應- 圖像中的邊緣只能標識一次,並且可能存在的圖像噪聲不應標識爲邊緣。

爲了滿足這些要求Canny使用了變分法,這是一種尋找滿足特定功能函數的方法。最優檢測使用四個指數函數項的和表示,但是它非常近似於高斯函數的一階導數

爲了得到最好的結果,Canny算子需要多個步驟,第一步是降噪,任何一個邊緣檢測算法都不可能在一個沒有經過降噪的圖片上得到好的結果。Canny的第一步是進行高斯平滑操作,這樣可以有效避免少量噪音像素對最終結果造成不好的影響。

第二步是尋找梯度,爲了在各個方向更好地尋找梯度,Canny算法使用4個mask尋找水平,垂直和對角線方向的邊緣(可以和Sobel的兩種作對比),這樣和Sobel類似,可以得到圖像中每個像素的亮度梯度圖以及亮度梯度的方向圖。

第三步是跟蹤邊緣,較亮的亮度梯度更有可能是邊緣,但是較亮的亮度梯度並不一定都是邊緣,有些亮度梯度比較明亮可能是真正的邊緣,有些則可能不是。所以Canny使用了滯後閾值,滯後閾值由兩個閾值——高閾值和低閾值共同組成,我們需要同時使用他們來確定真正的邊緣。

首先假設圖像中的重要邊緣都是連續的曲線。那麼我們首先根據求導得到的方向信息,用一個較大的閾值標識出我們比較確信的真實邊緣,然後使用一個較小的閾值來擴展這些已經定了的真實邊緣。由於我們假設重要邊緣都是連續的曲線,那麼也就意味着只要我們不斷地沿着最可能是真實邊緣的方向(最亮梯度方向)不斷延長我們的真實邊緣,直到到達下一個最亮梯度達到最小閾值,這樣能夠最終獲得一個完美的曲線來表示我們想要尋找的重要邊緣。當整個過程完成,我們就得到了一個二值圖像,每點表示是否是一個邊緣點。

除此之外,還有一個獲得亞像素精度邊緣的改進實現是在梯度方向檢測二階方向導數的過零點。這裏我們不再進行詳細描述。

但是通過對Canny算法的具體瞭解,我們得到了兩個重要的內容就是有兩個核心的參數可以有效的影響Canny邊緣檢測的效果。一個是第一步的高斯平滑,第二是第三步的閾值設置。我們上一篇文章末尾的例子(opencv自帶的例子)就是使用的Canny算子進行的邊緣檢測的展示。其中也包含了這兩個核心的設置,模糊和閾值。

代碼實現

爲了方便演示我們來寫一個更簡單的例子:

canny = cv2.Canny(gray, 30, 150)

canny = numpy.uint8(numpy.absolute(canny))
#display two images in a figure
cv2.imshow("Edge detection by Canny", numpy.hstack([gray,canny]))

在這裏插入圖片描述

寫到這你可能很奇怪,爲什麼這裏Canny也是使用的灰度圖,我們上一次演示不是在彩色圖片上繪製出的邊緣嗎?這是因爲之前的demo思路和之前的圖像輪廓獲取一致的。都是在獲取要檢測的內容之後,將結果繪製在了原來的彩色圖片上。而且要注意的是這些demo中的閾值都是可以調節的哦,具體請見下圖:

在這裏插入圖片描述
在這裏插入圖片描述

其中第一幅圖片的高低閾值比例是固定的,而第二幅圖片沒有固定高低閾值,我們可以手動調節查看具體效果。這兩個更詳細的demo都是opencv自帶的例子,尤其第二個是可以實時從攝像頭獲取數據並檢測繪製的。我們之前還沒有接觸過有關的內容,但是之後的章節將會不斷接觸。

Note:你可以前往我的github——漫談計算機視覺下載有關代碼。

Laplacian邊緣檢測

Laplacian 算子是n維歐幾里德空間中的一個二階微分算子,可以用於圖像增強或者邊緣提取。效果和之前的差別不大,和Canny一樣屬於二階算法,但是由於要計算梯度,OpeCV的Laplacian算子內部也使用了Sobel,同時他又和Canny一樣進行了多個方向上的梯度檢測,因爲複雜度更好,細紋理的發現效果更好。由於篇幅原因這裏不再多講,直接看效果就好。

ap = cv2.Laplacian(gray, cv2.CV_64F,ksize=3)

Laplacian = cv2.convertScaleAbs(lap)
# 等價於上面的代碼
# Laplacian = numpy.uint8(numpy.absolute(lap))

#display two images in a figure
cv2.imshow("Edge detection by Laplacaian", numpy.hstack([gray,Laplacian]))

在這裏插入圖片描述

Scharr

OpenCV還有一個邊緣檢測Scharr,其主要是爲了配合Sobel,下面代碼是等價的。

Scharr(src,dst,ddepth,dx,dy,scale,delta,borderType)
sobel(src,dst,ddepth,dx,dy,CV_SCHARR,scale,delta,borderType)

寫在最後

總結

邊緣檢測是OpenCV中比較多的內容,完全可以鋪開講很多,但是考慮到該部分在當前的計算機視覺領域已經不算重點,所以這裏沒有講太多。但是萬變不離其宗,所以我們重點講述了一個一階算法Sobal,一個二階算法Canny,同時也代碼展示了OpenCV中的其他元素。希望這些能夠有所幫助。

而除了邊緣檢測,OpenCV中還有一類名字有點接近邊緣檢測的檢測器,那就是角點檢測。角點檢測使用範圍將會更廣。下次我們將從講點檢測談起,說說更復雜的內容。

下載

Note:你可以前往我的github——漫談計算機視覺下載有關代碼。

參考

  1. 百度百科-邊緣檢測

  2. OpenCV-github官方項目

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