『OpenCV3』濾波器邊緣檢測


一、原理簡介

邊緣檢測原理 - Sobel, Laplace, Canny算子

X方向Sobel算子

-1 -2 -1
0 0 0
1 2 1

Y方向Sobel算子

-1 0 1
-2 0 2
-1 0 1

Laplace算子

1 1 1
1 -8 1
1 1 1

Canny 邊緣檢測算子

高斯濾波器平滑圖像

一階差分偏導計算梯度值和方向

對梯度值不是極大值的地方進行抑制

用雙閾值連接圖上的聯通點

通俗說一下,
1.用高斯濾波主要是去掉圖像上的噪聲。
2.計算一階差分,OpenCV 源碼中也是用 sobel 算子來算的。
3.算出來的梯度值,把不是極值的點,全部置0,去掉了大部分弱的邊緣。所以圖像邊緣會變細。
4.雙閾值 t1, t2, 是這樣的,t1 <= t2
大於 t2 的點肯定是邊緣
小於 t1 的點肯定不是邊緣
在 t1, t2 之間的點,通過已確定的邊緣點,發起8領域方向的搜索(廣搜),圖中可達的是邊緣,不可達的點不是邊緣。
最后得出 canny 邊緣圖。

二、代碼演示

有關函數 convertScaleAbs,文檔解釋如下,不過這里不使用其放縮功能

1、Sobel 邊緣檢測算子

由於需要指定橫向縱向,所以分兩步進行,最后組合即可,

	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原圖", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;	
        cv::Mat sobelX, sobelY;
	cv::Sobel(
		image,
		sobelX,
		CV_16S,  // 圖像depth,輸入8U,輸出16S防止外溢
		1, 0,   // xorder, yorder
		3,		// 內核尺寸
		1, 1	// 輸出結果乘alpha加beta
	);
	cv::convertScaleAbs(sobelX, sobelX);
	cv::imshow("Sobel_X", sobelX);
	cv::Sobel(
		image,
		sobelY,
		CV_8U,
		0, 1,
		3,
		1, 1
	);
	cv::convertScaleAbs(sobelY, sobelY);
	cv::imshow("Sobel_Y", sobelY);
	cv::addWeighted(sobelX, 0.5, sobelY, 0.5, 0, contours);
	cv::imshow("Sobel", contours);    

 XY單方向輸出如下,

兩這合並如下,

2、Laplace 邊緣檢測算子

	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原圖", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
        cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Laplacian(
		gray,
		contours,
		CV_16S,
		3,  // 內核尺寸
		1, 0 // 放縮因子
	);
	
	cv::convertScaleAbs(contours, contours);
	cv::imshow("Laplacian", contours);

3、Canny 邊緣檢測算子

	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原圖", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
	cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Canny(
		gray,
		contours,
		10,  // 低閾值
		150   // 高閾值
	);
	cv::imshow("Canny", contours);

高低閾值參數的設定對於檢測效果影響很大,一般來說低閾值檢測出十分瑣碎的邊緣,且設置的越低檢測出來的越多,而高閾值這決定了保留多少邊緣,對於上圖,我們將高閾值下調至50查看一下效果,會發現保留細節數目增加了

附錄、函數總覽

void edge() {
	// cv::Mat image = cv::imread("skin.jfif");
	cv::Mat image = cv::imread("test.jpg");
	cv::imshow("原圖", image);
	cv::Mat gray;
	cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);

	cv::Mat contours;
	cv::GaussianBlur(gray, gray, cv::Size(5, 5), 1.5);
	cv::Canny(
		gray,
		contours,
		10,  // 低閾值
		150   // 高閾值
	);
	cv::imshow("Canny", contours);

	cv::Laplacian(
		gray,
		contours,
		CV_16S,
		3,  // 內核尺寸
		1
	);
	cv::Mat abs_dst;
	cv::convertScaleAbs(contours, contours);
	cv::imshow("Laplacian", contours);

	cv::Mat sobelX, sobelY;
	cv::Sobel(
		image,
		sobelX,
		CV_16S,  // 圖像depth,輸入8U,輸出16S防止外溢
		1, 0,   // xorder, yorder
		3,		// 內核尺寸
		1, 1	// 輸出結果乘alpha加beta
	);
	cv::convertScaleAbs(sobelX, sobelX);
	cv::imshow("Sobel_X", sobelX);
	cv::Sobel(
		image,
		sobelY,
		CV_8U,
		0, 1,
		3,
		1, 1
	);
	cv::convertScaleAbs(sobelY, sobelY);
	cv::imshow("Sobel_Y", sobelY);
	cv::addWeighted(sobelX, 0.5, sobelY, 0.5, 0, contours);
	cv::imshow("Sobel", contours);
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM