Canny算法主要包括4步:
- 利用高斯算子對圖像進行平滑;
- 由於對圖像求一階或二階導數很容易放大噪聲,將噪聲判斷爲邊緣,因此預先要做一次平滑來減少其影響,canny算法採用的是高斯算子與源圖像卷積,其中高斯算子在之前圖像濾波中有過介紹。
找尋圖像的強度梯度; 採用Sobel算子來計算X和Y方向上的梯度值,並將它們的二範數及幾何平均值作爲梯度的強度信息,將它們和向量的夾角作爲梯度的方向信息。 - 應用非最大抑制方式來消除誤檢;
保留每個像素點梯度方向的極值,將模糊的邊界變得清晰,具體做法是先將梯度方向近似爲上下左右和45度方向中的一個(0,45,90,135,180,225,270,315),再比較該像素點與其梯度方向上的像素點的梯度強度,若最大則保留,否則抑制。 - 採用雙閾值方式來判斷邊緣。
Canny算法採用雙閾值的方法,若梯度強度大於閾值上界則必認爲是邊界,若梯度強度小於閾值下界則必然認爲不是邊界,兩者之間者需要進一步判斷,若若邊界周圍存在強邊界則認爲是邊界,不存在則認爲該弱邊界需要被抑制。
Opencv函數
CVAPI(void) cvCanny( const CvArr* image, CvArr* edges, double threshold1, double threshold2, int aperture_size CV_DEFAULT(3) );
參數一:源圖像
參數二:輸出邊界圖像
參數三:下邊界閾值
參數四:上邊界閾值
參數五:Sobel算子的模板大小,默認爲3
注:使用canny算法需要先將源圖像轉化爲單通道圖像。
代碼如下:
IplImage *g_src, *dst;
g_src = cvCreateImage(cvGetSize(m_ipl), IPL_DEPTH_8U, 1);
cvCvtColor(m_ipl, g_src, CV_RGB2GRAY);
dst = cvCreateImage(cvGetSize(g_src), IPL_DEPTH_8U, 1);
CEdit *m_edit_thre = (CEdit*)GetDlgItem(IDC_THRE);
CString th;
m_edit_thre->GetWindowTextA(th);
int t = atoi(th);
cvCanny(g_src,dst,t,t*1.2,3);
cvNamedWindow(_T("邊緣檢測後的圖像"));
cvShowImage(_T("邊緣檢測後的圖像"), dst);
cvReleaseImage(&g_src);
cvReleaseImage(&dst);