Canny邊緣檢測原理

2021-02-13 AI與計算機視覺

點擊上方「AI與計算機視覺」,選擇加"星標"或「置頂

重磅乾貨,第一時間送達

本文轉載自:https://sheng.blog.csdn.net/article/details/53213515

如有不妥之處,請聯繫作者刪除。

https://sheng.blog.csdn.net/article/details/53213515

一. Canny基本思想

1. 邊緣檢測

解析:邊緣是對象和背景之間的邊界,還能表示重疊對象之間的邊界。邊緣檢測是圖像分割的一部分,圖像分割的目的是識別出圖像中的區域。邊緣檢測是定位邊緣像素的過程,而邊緣增強是增加邊緣和背景之間的對比度以便能夠更清楚地看清邊緣的過程。邊緣跟蹤是沿著邊緣進行跟蹤的過程,這個過程通常會把邊緣像素採集到一個列表中,鏈碼算法是邊緣跟蹤算法的一個特例。

2. 最優邊緣準則 [1]

Canny邊緣檢測算子是John F. Canny於1986年開發出來的一個多級邊緣檢測算法。Canny的目標是找到一個最優的邊緣檢測算法,最優邊緣檢測的含義,如下所示:

(1)最優檢測:算法能夠儘可能多地標識出圖像中的實際邊緣,漏檢真實邊緣的概率和誤檢非邊緣的概率都儘可能小;

(2)最優定位準則:檢測到的邊緣點的位置距離實際邊緣點的位置最近,或者是由於噪聲影響引起檢測出的邊緣偏離物體的真實邊緣的程度最小;

(3)檢測點與邊緣點一一對應:算子檢測的邊緣點與實際邊緣點應該是一一對應。

二. Canny算法實現

1. 高斯濾波圖像去噪

垃圾進,垃圾出,數據預處理工作是非常重要的,圖像處理也不例外。這裡使用高斯濾波進行圖像去噪,比如blur = cv2.GaussianBlur(img, (5,5), 0),處理後的圖像與原始圖像相比稍微有些模糊。這樣單獨的一個像素噪聲在經過高斯濾波的圖像上變得幾乎沒有影響。

2. 計算圖像梯度

Canny算法的基本思想是找尋一幅圖相中灰度強度變化最強的位置。所謂變化最強,即指梯度方向。對平滑後的圖像使用Sobel算子計算水平方向和豎直方向的一階導數(圖像梯度)(Gx和Gy)。根據得到的這兩幅梯度圖(Gx和Gy)找到邊界的梯度和方向。如下所示:

梯度的方向一般總是與邊界垂直。梯度方向被歸為四類:垂直,水平,和兩個對角線。

3. 非極大值抑制

在獲得梯度的方向和大小之後,應該對整幅圖像做一個掃描,去除那些非邊界上的點。對每一個像素進行檢查,看這個點的梯度是不是周圍具有相同梯度方向的點中最大的。如下所示:

上圖中的數字代表了像素點的梯度強度,箭頭方向代表了梯度方向。以第二排第三個像素點為例,由於梯度方向向上,則將這一點的強度(7)與其上下兩個像素點的強度(5和4)比較,由於這一點強度最大,則保留。

4. 滯後閾值

現在要確定那些邊界才是真正的邊界。這時我們需要設置兩個閾值:minVal和maxVal。當圖像的灰度梯度高於maxVal時被認為是真的邊界,那些低於minVal的邊界會被拋棄。如果介於兩者之間的話,就要看這個點是否與某個被確定為真正的邊界點相連,如果是就認為它也是邊界點,如果不是就拋棄。如下所示:

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

三. Canny代碼應用

import cv2import numpy as np

if __name__ == '__main__':

def nothing(*arg):pass

cv2.namedWindow('edge')cv2.createTrackbar('thrs1', 'edge', 2000, 5000, nothing)cv2.createTrackbar('thrs2', 'edge', 4000, 5000, nothing)

cap = cv2.VideoCapture(0)while True:flag, img = cap.read()img = cv2.GaussianBlur(img, (3,3), 0)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)thrs1 = cv2.getTrackbarPos('thrs1', 'edge')thrs2 = cv2.getTrackbarPos('thrs2', 'edge')edge = cv2.Canny(gray, thrs1, thrs2, apertureSize=5)vis = img.copy()vis = np.uint8(vis/2.)vis[edge != 0] = (0, 255, 0)cv2.imshow('edge', vis)ch = cv2.waitKey(5) & 0xFFif ch == 27:breakcv2.destroyA

解析:

1. cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges

(1)其中較大的threshold2用於檢測圖像中明顯的邊緣,但一般情況下檢測的效果不會那麼完美,邊緣檢測出來是斷斷續續的,所以這時候用較小的threshold1用於將這些間斷的邊緣連接起來。

(2)可選參數apertureSize是Sobel算子的大小(默認值為3),而參數L2gradient是一個布爾值,如果為真,則使用更精確的L2範數進行計算(即兩個方向的倒數的平方和再開方),否則使用L1範數(直接將兩個方向導數的絕對值相加)。

2. cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst

(1)ddepth表示圖像的深度,-1表示採用的是與原圖像相同的深度。目標圖像的深度必須大於等於原圖像的深度;

(2)dx和dy表示求導的階數,0表示這個方向上沒有求導,一般為0、1、2。

(3)ksize表示Sobel算子的大小,必須為1、3、5、7。

(4)scale:optional scale factor for the computed derivative values; by default, no scaling is applied。

(5)delta:optional delta value that is added to the results prior to storing them in dst.

(6)borderType:pixel extrapolation method.

3. cv2.convertScaleAbs(src[, dst[, alpha[, beta]]]) → dst

(1)Scales, calculates absolute values, and converts the result to 8-bit, namely dst = src*alpha + beta.
(2)alpha:optional scale factor.
(3)beta:optional delta added to the scaled values.

4. cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) → dst

(1)alpha表示src1的權重。

(2)beta表示src2的權重。

(3)gamma:scalar added to each sum.

(4)dtype:optional depth of the output array; when both input arrays have the same depth, dtype can be set to -1, which will be equivalent to src1.depth().

cv2.addWeighted表示計算兩個數組的權重和,即dst = src1*alpha + src2*beta + gamma。

說明:邊緣檢測常用方法:Canny算子,Sobel算子,Laplace算子,Scharr濾波器。

參考文獻:

[1] Canny算法:http://baike.baidu.com/link?url=AAePc4GAMaZkiEOS17ldzT0DAIKre8w55f7oR56mqniSpQSnc8tDMwXEU2BQ0aGGaaPrsaiNbhTIMohvfgj6aPENnr0VHVXnmF2xPGrnlju

[2] OpenCV官方教程中文版

[3] OpenCV-Python教程:http://blog.csdn.net/sunny2038/article/details/9170013

相關焦點

  • OpenCV實戰系列(四):Canny邊緣檢測
    OpenCV為我們提供了一個非常方便的邊緣檢測接口Canny函數,該函數的命名是以其發明者Jhon F.Canny命名的,自1986年被發明後該算法就一直很受歡迎
  • OpenCV(四)邊緣檢測
    點擊「藍字」關注我們上一章節,我們在使用圖像輪廓發現的時候使用了圖像邊緣檢測,一次來提高圖像輪廓發現的準確率。事實上在計算機的各個領域都有圖像邊緣檢測的身影。邊緣檢測一大優點就在於可以大幅度減少數據量,並且提出可以認為不相關的信息,保留了圖像的結構屬性。
  • 使用 Pytorch 從頭實現 Canny 邊緣檢測
    Canny濾波器當然是最著名和最常用的邊緣檢測濾波器。我會逐步解釋用於輪廓檢測的canny濾波器。因為canny濾波器是一個多級濾波器。Canny過濾器很少被集成到深度學習模型中。所以我將描述不同的部分,同時使用Pytorch實現它。它可以幾乎沒有限制的進行定製,我允許自己一些偏差。
  • Python 圖像處理 OpenCV (11):Canny 算子邊緣檢測技術
    邊緣檢測 邊緣檢測是基於灰度突變來分割圖像的常用方法,其實質是提取圖像中不連續部分的特徵。目前常見邊緣檢測算子有差分算子、 Roberts 算子、 Sobel 算子、 Prewitt 算子、 Log 算子以及 Canny 算子等。
  • 圖像處理之Canny邊緣檢測(一)
    一:歷史Canny邊緣檢測算法是1986年有John F. Canny開發出來一種基於圖像梯度計算的邊緣檢測算法,同時Canny本人對計算圖像邊緣提取學科的發展也是做出了很多的貢獻。儘管至今已經許多年過去,但是該算法仍然是圖像邊緣檢測方法經典算法之一。
  • 在OpenCV中基於深度學習的邊緣檢測
    在這篇文章中,我們將學習如何在OpenCV中使用基於深度學習的邊緣檢測,它比目前流行的canny邊緣檢測器更精確。邊緣檢測在許多用例中是有用的,如視覺顯著性檢測,目標檢測,跟蹤和運動分析,結構從運動,3D重建,自動駕駛,圖像到文本分析等等。什麼是邊緣檢測?
  • 基於matlab邊緣提取的幾種方法的比較
    在邊緣點集合中剔除某些邊界點或填補邊界間斷點,並將這些邊緣連接成完整的線常用的檢測算子有微分算子、拉普拉斯高斯算子和canny算子。在Matlab圖像處理工具箱中,提供了edge函數利用以上算子來檢測灰度圖像的邊緣。
  • 分享 | 數字圖像處理:邊緣檢測(Edge detection)
    邊緣檢測算法,其目標是找到一個最優的邊緣,其最優邊緣的定義是:1.好的檢測 --算法能夠儘可能多地標示出圖像中的實際邊緣;2.好的定位 --標識出的邊緣要與實際圖像中的實際邊緣儘可能接近;3.最小響應 --圖像中的邊緣只能標識一次,並且可能存在的圖像噪聲不應該標識為邊緣。
  • 邊緣和輪廓檢測——計算機視覺的應用
    其標題是「使用計算機視覺進行邊緣和輪廓檢測」。對於此項目,你還將看到描述、原始碼和圖像分類。邊緣檢測邊緣檢測是一種用於定位圖像中對象邊界的圖像處理技術。最流行和廣泛使用的算法之一是 Canny 邊緣檢測器。Canny 邊緣檢測器是一種立足點檢測算子,它使用多階段算法來檢測圖像中的各種邊緣。在 Sobel 濾波器的幫助下,找出邊緣的強度和方向。
  • 【從零學習OpenCV 4】邊緣檢測原理
    函數的計算原理如式(5.15)所示。圖像的邊緣包含X方向的邊緣和Y方向的邊緣,因此分別求取兩個方向的邊緣後,對兩個方向的邊緣求取併集就是整幅圖像的邊緣,即將圖像兩個方向邊緣結果相加得到整幅圖像的邊緣信息。
  • 基於OpenCV的車輛變道檢測
    大家一定聽說過使用OpenCV 的haar級聯文件可以檢測到面部、眼睛等,但是如果目標是汽車,公共汽車呢?我們將道路上汽車的視頻文件用作數據集。當然可以使用圖像數據集檢測來汽車,但是由於汽車在變道時我們需要通過彈出窗口提供警報,因此對於這些動態情況,視頻輸入更為可行。
  • OpenCV中的快速直線檢測
    第6行創建FastLineDetectors檢測實例,這裡使用的是默認參數,其參數順序及意義如下:retval = cv.ximgproc.createFastLineDetector( [, _length_threshold[, _distance_threshold[, _canny_th1[, _canny_th2[, _canny_aperture_size
  • 基於 FPGA 的邊緣檢測
    本方案利用 HLS 功能創建圖像處理解決方案,在可編程邏輯中實現邊緣檢測 (Sobel)。
  • 基於Python的智能車道線檢測的Android開發(免費PDF kivy實戰開發電子書下載)
    首先基於OpenCV實現實時車道線檢測,其次基於Kivy實現UI界面和圖像車道線檢測、調用手機攝像頭的車道線檢測的程序開發,最後基於Pyinstaller,SetupFactory和Buildozer將程序打包成Windows安裝包和Android APK安裝包,經測試可以正常在Windows系統和Android系統正常安裝使用。
  • OpenCV矩形檢測
    點擊我愛計算機視覺標星,更快獲取CVML新技術今天在52CV交流群裡有朋友問到矩形檢測的問題,恰好前幾天做了一個與此相關的項目,調研了一下相關的算法
  • 圖像處理之Canny邊緣檢測(二)
  • 關於利用傳統圖像處理方法進行瑕疵檢測的總結
    傳統算法方向的選擇最近做圖像處理與識別相關的事情,先從OpenCV/Matlab入手,看傳統算法在瑕疵檢測方向能做到什麼程度。瑕疵檢測關注的兩個問題瑕疵的標註對瑕疵的標註是為了更直觀的展示,主要是給人看的瑕疵的量化真正機器關心的是怎麼量化,是用數量表示還是百分比是個值得考慮的問題歷程1.圖像去噪->灰度化->二值化二值化之後就可以看到絕大部分的瑕疵點已經凸顯出來了,但是有三個問題:1. 黑點瑕疵與白點瑕疵是二值化的兩個極端,故無法同時出現。2.