1. 程式人生 > >OpenCV3檢測直線或圓:霍夫線變換,霍夫圓變換合輯

OpenCV3檢測直線或圓:霍夫線變換,霍夫圓變換合輯

霍夫變換(Hough Transform)是影象處理中的一種特徵提取技術,該過程在一個引數空間中通過計算累計結果的區域性最大值得到一個符合該特定形狀的集合作為霍夫變換結果。
霍夫變換於1962年由PaulHough首次提出,最初的Hough變換是設計用來檢測直線和曲線,起初的方法要求知道物體邊界線的解析方程,但不需要有關區域位置的先驗知識。這種方法的一個突出優點是分割結果的Robustness,即對資料的不完全或噪聲不是非常敏感。然而,要獲得描述邊界的解析表達常常是不可能的。 後於1972年由Richard Duda & Peter Hart推廣使用,經典霍夫變換用來檢測影象中的直線,後來霍夫變換擴充套件到任意形狀物體的識別,多為圓和橢圓。霍夫變換運用兩個座標空間之間的變換將在一個空間中具有相同形狀的曲線或直線對映到另一個座標空間的一個點上形成峰值,從而把檢測任意形狀的問題轉化為統計峰值問題。

OpenCV支援三種不同的霍夫線變換,它們分別是:標準霍夫變換(Standard Hough Transform,SHT)和多尺度霍夫變換(Multi-Scale Hough Transform,MSHT)累計概率霍夫變換(Progressive Probabilistic Hough Transform ,PPHT)。

其中,多尺度霍夫變換(MSHT)為經典霍夫變換(SHT)在多尺度下的一個變種。累計概率霍夫變換(PPHT)演算法是標準霍夫變換(SHT)演算法的一個改進,它在一定的範圍內進行霍夫變換,計算單獨線段的方向以及範圍,從而減少計算量,縮短計算時間。之所以稱PPHT為“概率”的,是因為並不將累加器平面內的所有可能的點累加,而只是累加其中的一部分,該想法是如果峰值如果足夠高,只用一小部分時間去尋找它就夠了。這樣猜想的話,可以實質性地減少計算時間。

在OpenCV中,我們可以用HoughLines函式來呼叫標準霍夫變換SHT和多尺度霍夫變換MSHT。
而HoughLinesP函式用於呼叫累計概率霍夫變換PPHT。累計概率霍夫變換執行效率很高,所有相比於HoughLines函式,我們更傾向於使用HoughLinesP函式。
總結一下,OpenCV中的霍夫線變換有如下三種:
<1>標準霍夫變換(StandardHough Transform,SHT),由HoughLines函式呼叫。
<2>多尺度霍夫變換(Multi-ScaleHough Transform,MSHT),由HoughLines函式呼叫。
<3>累計概率霍夫變換

(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函式呼叫。

霍夫圓變換的基本原理和上面講的霍夫線變化大體上是很類似的,只是點對應的二維極徑極角空間被三維的圓心點x, y還有半徑r空間取代。說“大體上類似”的原因是,如果完全用相同的方法的話,累加平面會被三維的累加容器所代替:在這三維中,一維是x,一維是y,另外一維是圓的半徑r。這就意味著需要大量的記憶體而且執行效率會很低,速度會很慢。

示例:

//-----------------------------------【標頭檔案包含部分】---------------------------------------
//		描述:包含程式所依賴的標頭檔案
//---------------------------------------------------------------------------------------------- 
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

//-----------------------------------【名稱空間宣告部分】--------------------------------------
//		描述:包含程式所使用的名稱空間
//----------------------------------------------------------------------------------------------- 
using namespace std;
using namespace cv;


//-----------------------------------【全域性變數宣告部分】--------------------------------------
//		描述:全域性變數宣告
//-----------------------------------------------------------------------------------------------
Mat g_srcImage, g_dstImage, g_midImage;//原始圖、中間圖和效果圖
vector<Vec4i> g_lines;//定義一個向量結構g_lines用於存放得到的線段向量集合
//變數接收的TrackBar位置引數
int g_nthreshold = 100;

//-----------------------------------【全域性函式宣告部分】--------------------------------------
//		描述:全域性函式宣告
//-----------------------------------------------------------------------------------------------

static void on_HoughLines(int, void*);//回撥函式
static void ShowHelpText();


//-----------------------------------【main( )函式】--------------------------------------------
//		描述:控制檯應用程式的入口函式,我們的程式從這裡開始
//-----------------------------------------------------------------------------------------------
int main()
{
	ShowHelpText();

	//載入原始圖和Mat變數定義   
	Mat g_srcImage = imread("gonglu.jpg");  //工程目錄下應該有一張名為gonglu.jpg的素材圖

	//顯示原始圖  
	imshow("【原始圖】", g_srcImage);

	//建立滾動條
	namedWindow("【效果圖】", 1);
	createTrackbar("值", "【效果圖】", &g_nthreshold, 200, on_HoughLines);

	//進行邊緣檢測和轉化為灰度圖
	Canny(g_srcImage, g_midImage, 50, 200, 3);//進行一次canny邊緣檢測
	cvtColor(g_midImage, g_dstImage, CV_GRAY2BGR);//轉化邊緣檢測後的圖為灰度圖

	//呼叫一次回撥函式,呼叫一次HoughLinesP函式
	on_HoughLines(g_nthreshold, 0);
	HoughLinesP(g_midImage, g_lines, 1, CV_PI / 180, 80, 50, 10);

	//顯示效果圖  
	imshow("【效果圖】", g_dstImage);


	waitKey(0);

	return 0;

}


//-----------------------------------【on_HoughLines( )函式】--------------------------------
//		描述:【頂帽運算/黑帽運算】視窗的回撥函式
//----------------------------------------------------------------------------------------------
static void on_HoughLines(int, void*)
{
	//定義區域性變數儲存全域性變數
	Mat dstImage = g_dstImage.clone();
	Mat midImage = g_midImage.clone();

	//呼叫HoughLinesP函式
	vector<Vec4i> mylines;
	HoughLinesP(midImage, mylines, 1, CV_PI / 180, g_nthreshold + 1, 50, 10);

	//迴圈遍歷繪製每一條線段
	for (size_t i = 0; i < mylines.size(); i++)
	{
		Vec4i l = mylines[i];
		line(dstImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(23, 180, 55), 1, CV_AA);
	}
	//顯示影象
	imshow("【效果圖】", dstImage);
}

//-----------------------------------【ShowHelpText( )函式】----------------------------------
//		描述:輸出一些幫助資訊
//----------------------------------------------------------------------------------------------
static void ShowHelpText()
{
	//輸出一些幫助資訊
	printf("\n\n\n\t請調整滾動條觀察影象效果~\n\n");
}