【計算機視覺】OpenCV篇(8) - 邊緣檢測 邊緣檢測︱基於 HED網絡TensorFlow 和 OpenCV 實現圖片邊緣檢測

基礎篇-Canny邊緣檢測html

Canny邊緣檢測方法常被譽爲邊緣檢測的最優方法,先看下面的示例:python

import cv2
import numpy as np

# 1.Canny邊緣檢測
img = cv2.imread('images/handwriting.jpg', 0)
edges = cv2.Canny(img, 30, 70) #參數二、3表示最低、高閾值

cv2.imshow('canny', np.hstack((img, edges)))
cv2.waitKey(0)

Canny邊緣檢測原理算法

Canny邊緣檢測算法能夠分爲如下5個步驟:網絡

  1. 使用高斯濾波消除噪聲(邊緣檢測自己屬於銳化操做,對噪點比較敏感,因此須要進行平滑處理)。
  2. 計算圖像中每一個像素點的梯度強度和方向。
  3. 應用非極大值(Non-Maximum Suppression)抑制,以消除邊緣檢測帶來的雜散響應:非極大值抑制是一種邊緣稀疏技術,非極大值抑制的做用在於「瘦」邊。對圖像進行梯度計算後,僅僅基於梯度值提取的邊緣仍然很模糊。對於標準3,對邊緣有且應當只有一個準確的響應。而非極大值抑制則能夠幫助將局部最大值以外的全部梯度值抑制爲0,對梯度圖像中每一個像素進行非極大值抑制的算法是:1) 將當前像素的梯度強度與沿正負梯度方向上的兩個像素進行比較。2) 若是當前像素的梯度強度與另外兩個像素相比最大,則該像素點保留爲邊緣點,不然該像素點將被抑制。
  4. 應用雙閾值(Double-Threshold)檢測來肯定真實的和潛在的邊緣:在施加非極大值抑制以後,剩餘的像素能夠更準確地表示圖像中的實際邊緣。然而,仍然存在因爲噪聲和顏色變化引發的一些邊緣像素。爲了解決這些雜散響應,必須用弱梯度值過濾邊緣像素,並保留具備高梯度值的邊緣像素,能夠經過選擇高低閾值來實現。若是邊緣像素的梯度值高於高閾值,則將其標記爲強邊緣像素;若是邊緣像素的梯度值小於高閾值而且大於低閾值,則將其標記爲弱邊緣像素;若是邊緣像素的梯度值小於低閾值,則會被抑制。閾值的選擇取決於給定輸入圖像的內容。
  5. 經過抑制孤立的弱邊緣最終完成邊緣檢測:到目前爲止,被劃分爲強邊緣的像素點已經被肯定爲邊緣,由於它們是從圖像中的真實邊緣中提取出來的。然而,對於弱邊緣像素,將會有一些爭論,由於這些像素能夠從真實邊緣提取也能夠是因噪聲或顏色變化引發的。爲了得到準確的結果,應該抑制由後者引發的弱邊緣。一般,由真實邊緣引發的弱邊緣像素將鏈接到強邊緣像素,而噪聲響應未鏈接。爲了跟蹤邊緣鏈接,經過查看弱邊緣像素及其8個鄰域像素,只要其中一個爲強邊緣像素,則該弱邊緣點就能夠保留爲真實的邊緣。

先閾值分割後檢測post

在不少狀況下,閾值分割後再檢測邊緣,效果會更好:url

# 2.先閾值,後邊緣檢測
# 閾值分割(使用到了Otsu自動閾值)
_, thresh = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) #_表示不會用到這個值
edges = cv2.Canny(thresh, 30, 70)

cv2.imshow('canny', np.hstack((img, thresh, edges)))
cv2.waitKey(0)

 

進階篇-基於深度神經網絡的邊緣檢測spa

canny 算法的檢測效果,過分依賴於人工閾值的設定,沒法再通用場景下工做,如何找到一個在天然場景下能夠正確工做的邊緣檢測器呢?答案是使用CNN。htm

邊緣檢測︱基於 HED網絡TensorFlow 和 OpenCV 實現圖片邊緣檢測blog