canny邊緣檢測是最好用的邊緣查詢,它的實現也不是很複雜,我們分四個階段來進行分析。
1、高斯模糊,這裡不多說,難度不大。
2、卷積
將影象同能夠得到x方向的梯度和y方向的梯度的核進行卷積,得出gx和gy以及梯度方向。這是整個程式的開端,雖然簡單,但是很重要。
這裡,我們介紹可以被作為核的運算元:
這裡我們可以看到,這樣的運算元有乙個特點:進行邊緣檢測的矩陣的各個元素之和為0。
在我們的canny實現中,我們採用另外乙個簡單的運算元:
這裡我們需要將x方向和y方向上的梯度轉換為灰度,再根據公式
來獲取最後的梯度大小。
這裡的內容與之前的sobel邊緣檢測並沒有什麼不同,但是,後面的內容應該說是比較有趣了。
canny演算法之所以說是最有效的邊緣檢測演算法,其中的特點:
(1) 低錯誤率:意味著對存在的邊緣有著很好的檢測
(2) 好的定位:將偵測到的邊緣畫素與真實邊緣畫素之間的距離最小化
(3) 最小響應:對乙個邊緣只有乙個偵測響應
這些特點對於邊緣檢測完成後的後續步驟的更好實現有一定的保障。
如何實現這些特點?我們應該採取以下措施:
3、進行非極大抑制
我們知道,在梯度方向上變化率最大,因此我們可以對已經過卷積的並且求出梯度的影象中進行最大值的查詢:對於影象中的任意點a,得出a的梯度以及梯度方向。因為我們已經得知在梯度方向上梯度的變化率最大,所以我們能夠輕易的在這個方向中找到最大的點。由於我們在影象處理這個條件下,所以要將梯度方向離散化,這裡,根據點a的8個鄰域,我們將梯度方向離散為四個大的區域,8個小區。因為我們已經知道最大值就在這裡,而且非極大抑制的作用就是將邊緣細化,所以將點a的梯度同其他兩點(8個鄰域,離散後的梯度方向過兩個點)進行比較,如果grad(a)最大,則保持grad(a)不變,否則將其設為0。
4、雙閾值法
我們進行了非極大抑制之後,再進行閾值操作,當grad(a)>th時,將grad(a)=255否則grad(a)=0。經過這一步之後,我們發現影象的邊緣並不連續,這對於我們之後的影象處理並沒有任何用處。因此,我們必須做一些操作來使邊緣連續。這裡我們提出了雙閾值法。這個方法能夠將真邊緣保留下來,剔除假邊緣。這裡的真邊緣有兩部分組成:強邊緣與弱邊緣。強邊緣就是那些grad(a)>th的點所構成,弱邊緣的定義如下:設有點b,在影象中存在符合(1) grad(b)>th1並且grad(b)<=th2(2)b點位於真邊緣的某點c的鄰域中;其中th1為小閾值,th2為大閾值。
對這個方法的實現,我們可以通過使用圖的相關遍歷法則進行。在下面的**中,我們是用的是圖的廣度優先遍歷。深度優先遍歷也是可以的,但是應當注意的是,由於影象中的畫素數量較多,容易引起棧溢位,因此在使用遞迴遍歷時,需要多加注意。
**如下:
卷積**
void getvalue(mat in,int **kernel,int pos_heigh,int pos_width,double&t)非極大抑制:x++;
}t=0.114*all1+0.587*all2+0.299*all3;
}
void dec(mat in,double **angel)雙閾值if(i-1>=0
)
}if((angel[i][j]>112.5&&angel[i][j]<=157.5)||(angel[i][j]>-67.5&&angel[i][j]<=-22.5
))
if(i+1
.cols)
}if((angel[i][j]>157.5&&angel[i][j]<=180)||(angel[i][j]>-22.5&&angel[i][j]<=22.5)||(angel[i][j]>-180&&angel[i][j]<=-157.5
))
if(j+1
.cols)
}if((angel[i][j]>-157.5&&angel[i][j]<=-112.5)||(angel[i][j]>22.5&&angel[i][j]<67.5
))
if(i-1>=0&&j+1
.cols)}}
}}
void canny_yuzhi(mat in,int min,intmax)
if(in.at(i,j)
in.at(i,j)=0
; }
}imshow("3
",in
);
while(!q.empty())
if(pos_can(pt.x-1,pt.y,in.rows,in.cols)&&value_can(in,pt.x-1
,pt.y,min,max))
if(pos_can(pt.x-1,pt.y+1,in.rows,in.cols)&&value_can(in,pt.x-1,pt.y+1
,min,max))
if(pos_can(pt.x,pt.y-1,in.rows,in.cols)&&value_can(in,pt.x,pt.y-1
,min,max))
if(pos_can(pt.x,pt.y+1,in.rows,in.cols)&&value_can(in,pt.x,pt.y+1
,min,max))
if(pos_can(pt.x+1,pt.y-1,in.rows,in.cols)&&value_can(in,pt.x+1,pt.y-1
,min,max))
if(pos_can(pt.x+1,pt.y,in.rows,in.cols)&&value_can(in,pt.x+1
,pt.y,min,max))
if(pos_can(pt.x+1,pt.y+1,in.rows,in.cols)&&value_can(in,pt.x+1,pt.y+1
,min,max))
q.pop();}}
Canny邊緣檢測的c OpenCV實現
canny邊緣檢測演算法是一種比較常見且效果較好的邊緣檢測演算法,其優點在於得到的邊緣為單畫素邊緣,但是速度較sobel等邊緣檢測演算法較慢。網上canny演算法的演算法介紹很多,此處不仔細寫了,主要分為五步,分別是 高斯去噪,梯度計算 梯度方向計算 非極大值抑制和雙閾值邊緣抑制。其中,非極大值抑制...
Canny邊緣檢測
1.canny邊緣檢測基本原理 1 圖象邊緣檢測必須滿足兩個條件 一能有效地抑制雜訊 二必須盡量精確確定邊緣的位置。2 根據對訊雜比與定位乘積進行測度,得到最優化逼近運算元。這就是canny邊緣檢測運算元。3 類似與marr log 邊緣檢測方法,也屬於先平滑後求導數的方法。2.canny邊緣檢測演...
Canny邊緣檢測
canny運算元是邊緣檢測運算元中最常用的一種,是公認效能優良的一種運算元,常被其它邊緣檢測運算元作為標準運算元進行優劣分析。canny演算法基本可以分為3個步驟 平滑 梯度計算 基於梯度值及梯度方向的候選點過濾 1 平滑 影象梯度的計算對雜訊很敏感,因此必須首先對其進行低通濾波。在這裡使用5 5的...