OpenCV邊緣檢測算子原理總結及實現

 

1. 拉普拉斯算子html

    原理:是一種基於圖像導數運算的高通線性濾波器。它經過二階導數來度量圖像函數的曲率。編程

        拉普拉斯算子是最簡單的各向同性微分算子,它具備旋轉不變性。一個二維圖像函數的拉普拉斯變換是各向同性的二階導數,定義爲:函數

                                        

用更加形象的圖像來解釋,假設咱們有一張一維圖形。下圖(a)中灰度值的」躍升」表示邊緣的存在.若是使用一階微分求導咱們能夠更加清晰的看到邊緣」躍升」的存在(這裏顯示爲高峯值)圖(b); 若是在邊緣部分求二階導數會出現什麼狀況?,圖(c)所示。(其圖片和定義公式來源於http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/imgtrans/laplace_operator/laplace_operator.html)。3d

  

(a)                                                                                                          (b)code

(c)htm

你會發如今一階導數的極值位置,二階導數爲0。因此咱們也能夠用這個特色來做爲檢測圖像邊緣的方法。 可是, 二階導數的0值不單單出如今邊緣(它們也可能出如今無心義的位置),可是咱們能夠過濾掉這些點。blog

爲了更適合於數字圖像處理,將該方程表示爲離散形式:圖片

另外,拉普拉斯算子還能夠表示成模板的形式,以便更好編程須要。如圖1所示。ci

圖1(a)表示離散拉普拉斯算子的模板,圖1(b)表示其擴展模板,圖1(c)則分別表示其餘兩種拉普拉斯的實現模板。從模板形式容易看出,若是在圖像中一個較暗的區域中出現了一個亮點,那麼用拉普拉斯運算就會使這個亮點變得更亮。由於圖像中的邊緣就是那些灰度發生跳變的區域,因此拉普拉斯銳化模板在邊緣檢測中頗有用。通常加強技術對於陡峭的邊緣和緩慢變化的邊緣很難肯定其邊緣線的位置。但此算子卻可用二次微分正峯和負峯之間的過零點來肯定,對孤立點或端點更爲敏感,所以特別適用於以突出圖像中的孤立點、孤立線或線端點爲目的的場合。同梯度算子同樣,拉普拉斯算子也會加強圖像中的噪聲,有時用拉普拉斯算子進行邊緣檢測時,可將圖像先進行平滑處理。get

圖像銳化處理的做用是使灰度反差加強,從而使模糊圖像變得更加清晰。圖像模糊的實質就是圖像受到平均運算或積分運算,所以能夠對圖像進行逆運算,如微分運算可以突出圖像細節,使圖像變得更爲清晰。因爲拉普拉斯是一種微分算子,它的應用可加強圖像中灰度突變的區域,減弱灰度的緩慢變化區域。所以,銳化處理可選擇拉普拉斯算子對原圖像進行處理,產生描述灰度突變的圖像,再將拉普拉斯圖像與原始圖像疊加而產生銳化圖像。拉普拉斯銳化的基本方法能夠由下式表示:

這種簡單的銳化方法既能夠產生拉普拉斯銳化處理的效果,同時又能保留背景信息,將原始圖像疊加到拉普拉斯變換的處理結果中去,可使圖像中的各灰度值獲得保留,使灰度突變處的對比度獲得加強,最終結果是在保留圖像背景的前提下,突現出圖像中小的細節信息。但其缺點是對圖像中的某些邊緣產生雙重響應。

    代碼實現:

class LaplacianZC
{
public:

	LaplacianZC() :aperture(3){}
	// 設置內核孔徑大小
	void setAperture(int a){
		aperture = a;
	}
	// 計算浮點類型的laplace算子
	cv::Mat computeLaplacian(const cv::Mat& image){
		cv::Laplacian(image, laplace, CV_32F, aperture);
		return laplace;
	}

	// 獲取拉普拉斯結果,存在8爲圖像中
	cv::Mat getLaplacianImage(double scale = -1.0){
		if (scale < 0){
			double lapmin, lapmax;
			// 取得最小和最大拉普拉斯值
			cv::minMaxLoc(laplace, &lapmin, &lapmax);
			// 縮放拉普拉斯算子到127
			scale = 127 / std::max(-lapmin, lapmax);
		}

		// 生成灰度圖像
		cv::Mat laplaceImage;
		laplace.convertTo(laplaceImage, CV_8U, scale, 128);
		return laplaceImage;

	}

private:
	//拉普拉斯算子
	cv::Mat laplace;
	// 拉普拉斯內核的孔徑大小
	int aperture;

};


函數調用:
	LaplacianZC laplacian;
	laplacian.setAperture(7);  // 7*7的拉普拉斯算子
	cv::Mat flap = laplacian.computeLaplacian(img);
	cv::Mat laplace = laplacian.getLaplacianImage();

	namedWindow("raw");
	imshow("raw", img);
	namedWindow("laplace");
	imshow("laplace", laplace);

    效果圖:

 

 

2. Canny算子檢測圖像輪廓

    原理:**

    代碼實現:

// Canny算子檢測圖像輪廓
void canny(cv::Mat& img, cv::Mat& out) {
	// Convert to gray  
	if (img.channels() == 3)
		cv::cvtColor(img, out, CV_BGR2GRAY);
	// Compute Canny edges  
	cv::Canny(out, out, 100, 200);
	// Invert the image  
	cv::threshold(out, out, 128, 255, cv::THRESH_BINARY_INV);

	namedWindow("raw");
	imshow("raw", img);
	namedWindow("canny");
	imshow("canny", out);
}
相關文章
相關標籤/搜索