Canny邊緣檢測

2021-07-08 14:34:36 字數 3564 閱讀 8905

canny運算元是邊緣檢測運算元中最常用的一種,是公認效能優良的一種運算元,常被其它邊緣檢測運算元作為標準運算元進行優劣分析。

canny演算法基本可以分為3個步驟:平滑、梯度計算、基於梯度值及梯度方向的候選點過濾

(1)平滑

影象梯度的計算對雜訊很敏感,因此必須首先對其進行低通濾波。在這裡使用5*5的高斯濾波器,為了提高濾波效率,使用近似的高斯模板(圖1-1)

圖1-1. 5*5的高斯模板

(2)梯度計算

這一步主要通過計算每個畫素x、y方向的梯度,獲得該點的梯度值和梯度方向。在這裡使用一階邊緣檢測微分運算元sobel(圖1-2)

圖1-2. sobel邊緣檢測運算元

對每個點,由公式

具體處理的時候,將角度歸併到0、45、90、135這4個方向

(3)候選點過濾

這一步主要包含2塊內容:基於梯度方向的非最大值抑制基於雙閾值的候選點剔除及斷點連線

基於梯度方向的非最大值抑制

非最大值抑制主要考慮這種情況:處於邊緣上的點,其鄰域內梯度方向上(正方向和負方向)的點的梯度響應應該比該點小

然而實際中由梯度方向得到的鄰域點的座標往往是浮點值,因此需要對該值進行處理,對映到整數值

在這裡介紹3種處理辦法:

1. 將角度近似處理到0,45,90,135這4個方向,這樣只需要對當前點向左、右、上、下移動就可以了。這種方式計算簡單,但誤差較大

2. 對浮點座標進行插值(圖1-3)

圖1-3. 通過g1,g2 和g3,g4的加權和分別得到兩個浮點座標的梯度值(來自

考慮圖示的情況,有dtemp1 = g1*weight + g2*(1-weight),dtemp2 = g3*weight + g4*(1-weight)。其中weight由x和y方向的梯度值確定:

基於雙閾值的候選點剔除及斷點連線

為了進一步過濾雜訊的影響,非極大值抑制後,canny使用一高一低兩個閾值處理梯度響應矩陣。

1.對響應值大於高閾值的點,直接標記為邊緣點

2.對響應值小於高閾值,但大於低閾值的點,考察其8鄰域,如果存在已被標記的邊緣點,則也標記該點為邊緣點

關於高低閾值的設定,文章統計邊緣點的數目,將邊緣點按梯度響應從小到大排列,取位於第79%的那個點對應的梯度響應值作為高閾值,取其一半為低閾值

typedef struct mysize

_size;

#define _max(a,b) ((a)>(b)?(a):(b))

#define _min(a,b) ((a)

void _edgecanny(unsigned char* img, unsigned char* out, _size imgsize, int lowthreshold, int highthreshold);

templatevoid convolution(unsigned char* srcimg, t1* dstimg, _size imgsize, int* kernel, _size kersize, bool div);

void calcgradangle(int* mx, int* my, float* grad, float* angle, _size imgsize);

void depress(int* mx, int* my, float* grad, float* angle, unsigned char* out, _size imgsize);

void depress_(float* grad, float* angle, unsigned char* out, _size imgsize, int radius);

void doublethreshold(unsigned char* src, float* grad, _size imgsize, int low, int high);

void getthresholds(unsigned char* src, float* grad, _size imgsize, int* high, int* low);

void connectlow(unsigned char* src, float* grad, _size imgsize, int y, int x, int low);

void main()

else if((angle[index]>=135 && angle[index]<180) ||

(angle[index]>=315 && angle[index]<360))

else if((angle[index]>=45 && angle[index]<90) ||

(angle[index]>=225 && angle[index]<270))

else if((angle[index]>=0 && angle[index]<45) ||

(angle[index]>=180 && angle[index]<225))

if(grad[index]>=v12 && grad[index]>=v34)

out[index] = 128;

else

out[index] = 0;

}} }

}void depress_(float* grad, float* angle, unsigned char* out, _size imgsize, int radius)

} }}void doublethreshold(unsigned char* src, float* grad, _size imgsize, int low, int high)

} }for(int i=0; i=pos)

}*low = int(0.5*(*high)+0.5);

}void connectlow(unsigned char* src, float* grad, _size imgsize, int y, int x, int low)

; int ynum[8] = ;

for(int i=0; i<8; i++)}}}

效果((a)為opencv函式結果(閾值取140,70), (b)為對浮點座標插值的效果,(c)和(d)為在浮點座標周圍取4個整數值的效果,前者半徑為1,後者為4)

Canny邊緣檢測

1.canny邊緣檢測基本原理 1 圖象邊緣檢測必須滿足兩個條件 一能有效地抑制雜訊 二必須盡量精確確定邊緣的位置。2 根據對訊雜比與定位乘積進行測度,得到最優化逼近運算元。這就是canny邊緣檢測運算元。3 類似與marr log 邊緣檢測方法,也屬於先平滑後求導數的方法。2.canny邊緣檢測演...

Canny邊緣檢測

canny邊緣檢測是一種非常流行的邊緣檢測演算法,是john canny在1986年提出的。它是乙個多階段的演算法,即由多個步驟構成。1.影象降噪 2.計算影象梯度 3.非極大值抑制 4.閾值篩選 我們就事後諸葛亮,分析下這個步驟的緣由。首先,影象降噪。我們知道梯度運算元可以用於增強影象,本質上是通...

Canny邊緣檢測

canny邊緣檢測演算法 五個步驟 1.高斯模糊 gaussianblur 2.灰度轉換 cvtcolor 3.計算梯度 sobel scharr 4.非最大訊號抑制 5.高低閾值連線輸出二值影象 import cv2 def edge demo image blurred cv2.gaussian...