【opencv學習筆記】021之霍夫直線變換原理詳解

目錄

一、前言

二、霍夫變換

1、霍夫變換是個啥

2、常用霍夫變換

三、霍夫直線變換

1、講解

2、API

1.HoughLines

2.HoughLinesP

3、代碼展示

4、執行結果


一、前言

終於更新到霍夫直線變換了,跟以前寫的博客成功接軌。opencv基礎博客也即將更新完畢,感謝大家的支持,我們要再接再厲呀!

如果想看其他有關於OpenCV學習方法介紹、學習教程、代碼實戰、常見報錯及解決方案等相關內容,可以直接看我的OpenCV分類:

【OpenCV系列】:https://blog.csdn.net/shuiyixin/article/category/7581855

如果你想了解更多有關於計算機視覺、OpenCV、機器學習、深度學習等相關技術的內容,想與更多大佬一起溝通,那就掃描下方二維碼加入我們吧!

 

二、霍夫變換

1、霍夫變換是個啥

我們先來了解一下霍夫變換是個啥

霍夫變換是一種特徵檢測(feature extraction),被廣泛應用在圖像分析(image analysis)、計算機視覺(computer vision)以及數位影像處理(digital image processing)。

霍夫變換是用來辨別找出物件中的特徵,其流程大致如下:

給定一個物件、要辨別的形狀的種類,算法會在參數空間(parameter space)中執行投票來決定物體的形狀,而這是由累加空間(accumulator space)裏的局部最大值(local maximum)來決定。

 

2、常用霍夫變換

我們會經常使用到如下兩個霍夫變換:

1.霍夫直線變換:在圖像中尋找直線

2.霍夫圓變換:在圖像中尋找圓。

這個博客,我們一起來了解一下啥是霍夫直線變換,。如果你想了解霍夫圓變換,請轉移到:

【opencv學習筆記】022之霍夫圓變換:https://blog.csdn.net/shuiyixin/article/details/79898107

 

三、霍夫直線變換

1、講解

上面我們知道霍夫直線變換,就是用來檢測直線的,那怎麼知道一條線是直線呢?

假設我們有上圖這個紅色的直線,大家看到這個θ和r,學過極座標的同學應該就能知道了,我們要用極座標來表示直線了。

對於一條直線來說,我們首先要知道它的平面直角座標表示(只考慮二維平面):

而對於上圖,我們能知道:

根據上面的公式,我們能夠推導出如下公式:

推導過程可以如下:

得到這個公式,有什麼作用呢?

我們知道x和y是直線上的點,我們爲了方便講解,我們取一條直線來說明:

對於上面這條直線,有如下五個點是在直線上的:

所以我們可以得到五條直線:

如果我們以θ爲橫座標,r爲縱座標,當我們把這五條直線畫在同一個座標系中,我們能得到下面這幅圖:

我們發現,這五條直線交於同一點,這就是直線有的特點,我們就通過這個特點,將所有的直線累加,那交點處因爲是所有直線的累加,其像素值一定是最高的,我們知道,像素越高,在圖像上越亮,當達到255的時候,是最亮,即爲白色。所以我們可以通過這種方式來檢測到直線。

2、API

1.HoughLines

接下來我們講一下API。霍夫直線有兩個API,首先我們先講一個偏專業的

HoughLines( 
    InputArray image, 
    OutputArray lines,
    double rho, 
    double theta, 
    int threshold,                              
    double srn = 0, 
    double stn = 0,                              
    double min_theta = 0, 
    double max_theta = CV_PI 
);

函數參數含義如下:

(1)InputArray類型的src ,8位,單通道二進制源圖像。

(2)OutputArray類型的lines,直線的輸出向量。每一直線都由一個雙元素向量表示。rho是距座標原點的距離(0,0)(圖像左上角)。theta是以弧度爲單位的線旋轉角度。

(3)double類型的rho,累加器的距離分辨率(像素)

(4)double類型的theta,累加器的角度分辨率(弧度)。

(5)int類型的threshold,累加器閾值參數。只返回獲得足夠累加器數量的直線。

(6)double類型的srn,對於多尺度Hough變換,它是距離分辨率rho的除數,粗累加器距離分辨率爲rho,精確累加器分辨率爲rho/srn。如果srn=0和stn=0,則使用經典Hough變換。否則,這兩個參數都應爲正。

(7)double類型的sth,對於多尺度Hough變換,它是距離分辨率θ的除數。

(8)double類型的min_theta,用於標準和多尺度Hough變換,檢查直線的最小角度。必須介於0和maxθ之間。

(9)double類型的max_theta,用於標準和多尺度Hough變換,用於檢查線條的最大角度。必須介於最小θ和CVπ之間。

2.HoughLinesP

接下來我們先講一個實用性更高的

HoughLines( 
    InputArray image, 
    OutputArray lines,
    double rho, 
    double theta, 
    int threshold,                              
    double minLineLength = 0, 
    double maxLineGap = 0                             
);

函數參數含義如下:

(1)InputArray類型的src ,8位,單通道二進制源圖像。

(2)OutputArray類型的lines,直線的輸出向量。每一直線都由一個雙元素向量表示。rho是距座標原點的距離(0,0)(圖像左上角)。theta是以弧度爲單位的線旋轉角度。

(3)double類型的rho,累加器的距離分辨率(像素)

(4)double類型的theta,累加器的角度分辨率(弧度)。

(5)int類型的threshold,累加器閾值參數。只返回獲得足夠累加器數量的直線。

(6)double類型的minLineLength,最小直線長度。小於該值的線段將被拒絕。

(7)double類型的maxLineGap,同一行上的點之間鏈接它們所允許的最大間距。

 

3、代碼展示

如果我們使用HoughLines,代碼如下:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat src, src_gray, dst;
	src = imread("E:/image/HoughLines.bmp");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("【輸入圖像】", src);

	Canny(src, src_gray, 0, 255);
	cvtColor(src_gray, dst, CV_GRAY2BGR);
	imshow("【獲取邊緣】", src_gray);

	vector<Vec2f> lines;
	HoughLines(src_gray, lines, 1, CV_PI / 180, 100);

	for (size_t i = 0; i < lines.size(); i++) {
		float rho = lines[i][0]; // 極座標中的r長度
		float theta = lines[i][1]; // 極座標中的角度
		Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a*rho, y0 = b*rho;
		// 轉換爲平面座標的四個點
		pt1.x = cvRound(x0 + 1000 * (-b));
		pt1.y = cvRound(y0 + 1000 * (a));
		pt2.x = cvRound(x0 - 1000 * (-b));
		pt2.y = cvRound(y0 - 1000 * (a));
		line(dst, pt1, pt2, Scalar(0, 0, 255), 5, CV_AA);
	}


	imshow("【輸出圖像】", dst);

	waitKey(0);
	return 0;
}

如果我們使用HoughLinesP,代碼如下:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;
using namespace cv;

int main()
{
	Mat src, src_gray, dst;
	src = imread("E:/image/HoughLines.bmp");
	if (!src.data)
	{
		cout << "could not load image !";
		return -1;
	}
	imshow("【輸入圖像】", src);

	Canny(src, src_gray, 0, 255);
	cvtColor(src_gray, dst, CV_GRAY2BGR);

	imshow("【獲取邊緣】", src_gray);

	vector<Vec4f> plines;
	HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 0, 10);
	cout << plines.size() << endl;
	Scalar color = Scalar(0, 0, 255);
	for (size_t i = 0; i < plines.size(); i++) {
		Vec4f hline = plines[i];
		line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
	}

	imshow("【輸出圖像】", dst);

	waitKey(0);
	return 0;
}

4、執行結果

 

HoughLines

 

HoughLinesP

可以看到他把所有的直線全部都標註出來,大家也可以自己調整參數觀看效果哦。

大家也可以自己嘗試一下呀,一定要多做練習!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章