當前位置:首頁 » 操作系統 » canny邊緣檢測演算法

canny邊緣檢測演算法

發布時間: 2023-08-23 03:24:42

1. canny演算法的演算法的實現步驟

Canny邊緣檢測演算法可以分為以下5個步驟: 應用高斯濾波來平滑圖像,目的是去除雜訊 找尋圖像的強度梯度(intensity gradients) 應用非最大抑制(non-maximum suppression)技術來消除邊誤檢(本來不是但檢測出來是) 應用雙閾值的方法來決定可能的(潛在的)邊界 利用滯後技術來跟蹤邊界 1. 圖像平滑(去雜訊)
任何邊緣檢測演算法都不可能在未經處理的原始數據上很好地工作,所以第一步是對原始數據與高斯 mask 作卷積,得到的圖像與原始圖像相比有些輕微的模糊(blurred)。這樣,單獨的一個像素雜訊在經過高斯平滑的圖像上變得幾乎沒有影響。以下為一個5X5高斯濾波器(高斯核,標准差delta=1.4),其中A為原始圖像,B為平滑後的圖像。


2. 尋找圖像中的強度梯度
Canny演算法的基本思想是找尋一幅圖相中灰度強度變化最強的位置。所謂變化最強,即指梯度方向。平滑後的圖像中每個像素點的梯度可以由Sobel運算元(一種卷積運算)來獲得(opencv中有封裝好的函數,可以求圖像中每個像素點的n階導數)。首先,利用如下的核來分別求得沿水平(x)和垂直(y)方向的梯度G_X和G_Y。
K_{GX} = [-1 0 1 ; -2 0 2 ; -1 0 1], K_{GY} = {1 2 1 ; 0 0 0 ; -1 -2 -1}
之後便可利用公式來求得每一個像素點的梯度度量值(gradient magnitude,可能翻譯得不準確)。
,有時為了計算簡便,也會使用G_X和G_Y的無窮大范數來代替二范數。把平滑後的圖像中的每一個點用G代替,可以獲得如下圖像。從下圖可以看出,在變化劇烈的地方(邊界處),將獲得較大的梯度度量值G,對應的顏色為白色。然而,這些邊界通常非常粗,難以標定邊界的真正位置。為了做到這一點(參考非極大抑制Non-maximum suppression一節),還必須存儲梯度方向,其公式如下圖所示。也就是說在這一步我們會存數兩塊數據,一是梯度的強度信息,另一個是梯度的方向信息。

3. 非極大抑制Non-maximum suppression
這一步的目的是將模糊(blurred)的邊界變得清晰(sharp)。通俗的講,就是保留了每個像素點上梯度強度的極大值,而刪掉其他的值。對於每個像素點,進行如下操作:
a) 將其梯度方向近似為以下值中的一個(0,45,90,135,180,225,270,315)(即上下左右和45度方向)
b) 比較該像素點,和其梯度方向正負方向的像素點的梯度強度
c) 如果該像素點梯度強度最大則保留,否則抑制(刪除,即置為0)
為了更好的解釋這個概念,看下圖。

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

上圖中,可以想像,邊界處的梯度方向總是指向垂直於邊界的方向,即最後會保留一條邊界處最亮的一條細線。
4.雙閾值(Double Thresholding)
經過非極大抑制後圖像中仍然有很多雜訊點。Canny演算法中應用了一種叫雙閾值的技術。即設定一個閾值上界和閾值下界(opencv中通常由人為指定的),圖像中的像素點如果大於閾值上界則認為必然是邊界(稱為強邊界,strong edge),小於閾值下界則認為必然不是邊界,兩者之間的則認為是候選項(稱為弱邊界,weak edge),需進行進一步處理。經過雙閾值處理的圖像如下圖所示

上圖中右側強邊界用白色表示,弱邊界用灰色表示。
5.利用滯後的邊界跟蹤
這里就不細作解釋了。大體思想是,和強邊界相連的弱邊界認為是邊界,其他的弱邊界則被抑制。
以上內容均翻譯自參考文獻【4】
上一個網路版本:
圖像中的邊緣可能會指向不同的方向,所以 Canny 演算法使用 4 個 掩模(mask) 檢測水平、垂直以及對角線方向的邊緣。原始圖像與每個 mask 所作的卷積都存儲起來。對於每個點我們都標識在這個點上的最大值以及生成的邊緣的方向。這樣我們就從原始圖像生成了圖像中每個點亮度梯度圖以及亮度梯度的方向。以下兩個公式分別求取高斯濾波後圖像的梯度幅值及其方向的表達式。這一步,也叫稱為非極大抑制(Non-maximum suppression)。


3. 在圖像中跟蹤邊緣
較高的亮度梯度比較有可能是邊緣,但是沒有一個確切的值來限定多大的亮度梯度是邊緣多大又不是,所以 Canny 使用了滯後閾值。
滯後閾值(Hysteresis thresholding) 需要兩個閾值,即高閾值與低閾值。假設圖像中的重要邊緣都是連續的曲線,這樣我們就可以跟蹤給定曲線中模糊的部分,並且避免將沒有組成曲線 的雜訊像素當成邊緣。所以我們從一個較大的閾值開始,這將標識出我們比較確信的真實邊緣,使用前面導出的方向信息,我們從這些真正的邊緣開始在圖像中跟蹤 整個的邊緣。在跟蹤的時候,我們使用一個較小的閾值,這樣就可以跟蹤曲線的模糊部分直到我們回到起點。
一旦這個過程完成,我們就得到了一個二值圖像,每點表示是否是一個邊緣點。
一個獲得亞像素精度邊緣的改進實現是在梯度方向檢測二階方向導數的過零點,它在梯度方向的三階方向導數滿足符號條件。
滯後閾值也可以用於亞像素邊緣檢測。

2. 3種python3的canny邊緣檢測之靜態,可調節和自適應

先看高級版的python3的canny的自適應邊緣檢測:

內容:

1 canny的邊緣檢測的介紹。

2 三種方法的canny的邊緣檢測,由淺入深地介紹:固定值的靜態,可自調節的,自適應的。

說明:

1 環境:python3.8、opencv4.5.3和matplotlib3.4.3。

2 圖片:來自品閱網正版免費圖庫。

3 實現自適應閾值的canny邊緣檢測的參考代碼和文章:

上述的代碼,本機均有報錯,故對代碼進行修改,注釋和運行。

初級canny:

1 介紹:opencv中給出了canny邊緣檢測的介面,直接調用:

即可得到邊緣檢測的結果ret,其中,t1,t2是需要人為設置的閾值。

2 python的opencv的一行代碼即可實現邊緣檢測。

3 Canny函數及使用:

4 Canny邊緣檢測流程:

去噪 --> 梯度 --> 非極大值抑制 --> 滯後閾值

5 代碼:

6 操作和過程:

7 原圖:

8 疑問:

ret = cv2.canny(img,t1,t2),其中,t1,t2是需要人為設置的閾值,一般人怎麼知道具體數值是多少,才是最佳的呀?所以,這是它的缺點。

中級canny:

1 中級canny,就是可調節的閾值,找到最佳的canny邊緣檢測效果。

2 採用cv2.createTrackbar來調節閾值。

3 代碼:

4 操作和效果:

5 原圖:

高級canny:

1 自適應canny的演算法:

ret = cv2.canny(img,t1,t2)

即演算法在運行過程中能夠自適應地找到較佳的分割閾值t1,t2。

2 文件結構:

3 main.py代碼:

4 dog.py代碼:

5 bilateralfilt.py代碼:

6 原圖:

7 效果圖:本文第一個gif圖,此處省略。

小結:

1 本文由淺入深,總結的很好,適合收藏。

2 對於理解python的opencv的canny的邊緣檢測,很有幫助。

3 本文高級版canny自適應的演算法參考2篇文章,雖然我進行代碼的刪除,注釋,修改,優化等操作,故我不標注原創,對原作者表達敬意。

4 自己總結和整理,分享出來,希望對大家有幫助。

3. canny演算法的最優邊緣准則

Canny 的目標是找到一個最優的邊緣檢測演算法,最優邊緣檢測的含義是:
(1)最優檢測:演算法能夠盡可能多地標識出圖像中的實際邊緣,漏檢真實邊緣的概率和誤檢非邊緣的概率都盡可能小;
(2)最優定位準則:檢測到的邊緣點的位置距離實際邊緣點的位置最近,或者是由於雜訊影響引起檢測出的邊緣偏離物體的真實邊緣的程度最小;
(3)檢測點與邊緣點一一對應:運算元檢測的邊緣點與實際邊緣點應該是一一對應。
為了滿足這些要求 Canny 使用了變分法(calculus of variations),這是一種尋找優化特定功能的函數的方法。最優檢測使用四個指數函數項表示,但是它非常近似於高斯函數的一階導數。

4. Canny運算元的介紹

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

5. 如何利用opencv實現彩色圖像邊緣檢測演算法

在opencv中顯示邊緣檢測很簡單,只需調用一個cvCanny函數,其使用的是Canny演算法來實現對圖像的邊緣檢測.
函數原型為:
void cvCanny( const CvArr* image,CvArr* edges,double threshold1,double threshold2, int aperture_size=3 );
第一個參數為待檢測的圖像,注意一點,其必須是灰度圖.
第二個參數為輸出的邊緣圖,其也是一個灰度圖.
後三個參數與Canny演算法直接相關,threshold1和threshold2 當中的小閾值用來控制邊緣連接,大的閾值用來控制強邊緣的初始分割,aperture_size運算元內核大小,可以去看看Canny演算法.
從彩色圖到灰度圖需要使用到cvCvtColor函數,其接受三個參數,第一為輸入,第二為輸出,第三個為轉換的標識,我們這邊是RGB到GRAY,使用的是CV_RGB2GRAY.
參考demo代碼如下:

#include <iostream>

#include <string>
#include <sstream>
#include <opencv/cv.h>
#include <opencv/highgui.h>

using namespace std;

int String2int(const string& str_)
{
int _nre = 0;
stringstream _ss;
_ss << str_;
_ss >> _nre;
return _nre;
}

void DoCanny(const string& strFileName_)
{
//原彩色圖片
IplImage* _pIplImageIn = cvLoadImage(strFileName_.data());

if (_pIplImageIn == NULL)
{
return;
}
//彩色圖片轉換成灰度圖放置的圖片
IplImage* _pIplImageCanny = cvCreateImage(cvGetSize(_pIplImageIn), _pIplImageIn->depth, 1);
cvCvtColor(_pIplImageIn, _pIplImageCanny, CV_RGB2GRAY);//CV_RGB2GRAY將rgb圖轉成灰度圖
//只有邊緣路徑的圖片
IplImage* _pIplImageOut = cvCreateImage(cvGetSize(_pIplImageIn), IPL_DEPTH_8U, 1);

//邊緣檢測只能作用於灰度圖
if (_pIplImageCanny->nChannels != 1)
{
return;
}

//邊緣檢測操作
cvCanny(_pIplImageCanny, _pIplImageOut, 1, 110, 3);

cvNamedWindow("Src");
cvShowImage("Src", _pIplImageIn);
cvNamedWindow("Canny");
cvShowImage("Canny", _pIplImageOut);

cvWaitKey(0);

cvReleaseImage(&_pIplImageIn);
cvReleaseImage(&_pIplImageCanny);
cvReleaseImage(&_pIplImageOut);

cvDestroyWindow("Src");
cvDestroyWindow("Canny");

}

int main(int argc, char* argv[])
{
if (argc < 2)
{
cout << "You should give the filename of picture!" << endl;
return -1;
}
DoCanny(argv[1]);
return 0;
}

熱點內容
大數據與資料庫的關系 發布:2025-03-07 08:48:20 瀏覽:288
取冪C語言 發布:2025-03-07 08:43:10 瀏覽:488
高考解壓性 發布:2025-03-07 08:43:10 瀏覽:690
搜狐廣告伺服器是什麼 發布:2025-03-07 08:36:45 瀏覽:147
csgo穩定fps要什麼配置 發布:2025-03-07 08:35:01 瀏覽:404
matlab粒子群優化演算法 發布:2025-03-07 08:13:49 瀏覽:249
編譯原理翻譯 發布:2025-03-07 08:08:01 瀏覽:592
安卓光遇測試服為什麼伺服器錯誤 發布:2025-03-07 08:05:53 瀏覽:550
火狐緩存文件夾 發布:2025-03-07 08:05:51 瀏覽:113
代碼編程庫 發布:2025-03-07 08:05:09 瀏覽:182