1. 程式人生 > >影象處理(七)——Canny邊緣檢測

影象處理(七)——Canny邊緣檢測

Canny邊緣檢測運算元是John F. Canny於 1986 年開發出來的一個多級邊緣檢測演算法。更為重要的是 Canny 創立了邊緣檢測計算理論(Computational theory of edge detection)解釋這項技術如何工作。
通常情況下邊緣檢測的目的是在保留原有影象屬性的情況下,顯著減少影象的資料規模。目前有多種演算法可以進行邊緣檢測,雖然Canny演算法年代久遠,但可以說它是邊緣檢測的一種標準演算法,而且仍在研究中廣泛使用。

Canny演算法是實現可以分為六步:

  1. 灰度化影象
    較為簡單,不多說

  2. 高斯濾波
    高斯濾波是為了平滑影象,消除噪聲。高斯濾波是實現之前的實驗已經做過。

  3. 計算梯度之和方向
    影象灰度值的梯度一般使用一階有限差分來進行近似,這樣就可以得影象在x和y方向上偏導數的兩個矩陣。
    在這裡插入圖片描述
    其中f為影象灰度值,P代表X方向梯度幅值,Q代表Y方向 梯度幅值,M是該點幅值,Θ是梯度方向,也就是角度。

  4. 非極大值抑制
    非極大值抑制是進行邊緣檢測的一個重要步驟,簡單來說就是指尋找畫素點區域性最大值。
    在這裡插入圖片描述
    通過插值來計算dTemp1和dTemp2的畫素值(亞畫素 )。

  5. 雙閾值的選取
    雙閾值的選取是按照直方圖來選擇的,至於選取多少就要自己定義了,這裡我測試了幾種不同的取值,結果分別如下:
    (50,150)
    在這裡插入圖片描述
    (100,200)
    在這裡插入圖片描述
    (20,100)
    在這裡插入圖片描述
    如果邊緣畫素的梯度值高於高閾值,則將其標記為強邊緣畫素;如果邊緣畫素的梯度值小於高閾值並且大於低閾值,則將其標記為弱邊緣畫素;如果邊緣畫素的梯度值小於低閾值,則會被抑制。

  6. 邊緣檢測
    首先判斷該點是否超過高閾值,然後判斷該點的8鄰域點中尋找滿足超過低閾值的點,再根據此點收集新的邊緣,直到整個影象邊緣閉合。整個影象找完後,將非邊緣點剔除,即灰度值置0.

完成了以上六步,Canny邊緣檢測演算法就完成了,實測效果也挺不錯的。


程式碼自取

// CVE7(2).cpp: 定義控制檯應用程式的入口點。
//

#include "stdafx.h"
#include "StdAfx.h"
#include "cv.h"
#include "cxcore.h"
#include "highgui.h"
int main(int argc, char** argv)
{
	//宣告IplImage指標
	IplImage* img = NULL;
	IplImage* cannyImg = NULL;
	//char *filename;
	//filename = "圖片1.png";
	img = cvLoadImage("E:/C++/CVE7(2)/圖片1.png", 1);
	//載入影象,強制轉化為Gray
	if ((img = cvLoadImage("E:/C++/CVE7(2)/圖片2.jpg", 0)) != 0)
	{
		//為canny邊緣影象申請空間
		cannyImg = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
		//canny邊緣檢測
		cvCanny(img, cannyImg, 20, 100, 3);
		//建立視窗
		cvNamedWindow("src", 1);
		cvNamedWindow("canny", 1);
		//顯示影象
		cvShowImage("src", img);
		cvShowImage("canny", cannyImg);
		cvWaitKey(0); //等待按鍵
					  //銷燬視窗
		cvDestroyWindow("src");
		cvDestroyWindow("canny");
		//釋放影象
		cvReleaseImage(&img);
		cvReleaseImage(&cannyImg);
		return 0;
	}
	return -1;
}