1. 程式人生 > >霍夫變換鐳射線中心提取(基於opencv)

霍夫變換鐳射線中心提取(基於opencv)

平臺: VS2017 C++ OPENCV3庫

效果:

原圖 在這裡插入圖片描述 結果: 在這裡插入圖片描述 原圖: 在這裡插入圖片描述 結果: 在這裡插入圖片描述

步驟:

1.圖片預處理,引數可以自己調整

	//邊緣檢測
	Canny(srcImage, dstImage, 210, 250, 3);
	//灰度化
	cvtColor(midImage, dstImage, CV_GRAY2BGR);

在這裡插入圖片描述

2.霍夫變換,畫直線

// 定義向量結構存放檢測出來的直線
	vector<Vec2f> lines;
	//通過這個函式,我們就可以得到檢測出來的直線集合了
	HoughLines(midImage, lines, 1, CV_PI / 180, 300, 0, 0);
	//這裡注意第五個引數,表示閾值,閾值越大,表明檢測的越精準,速度越快,得到的直線越少(得到的直線都是很有把握的直線)
//這裡得到的lines是包含rho和theta的,而不包括直線上的點,所以下面需要根據得到的rho和theta來建立一條直線 //依次畫出每條線段 for (size_t i = 0; i < lines.size(); i++) { double rho = lines[i][0]; //就是圓的半徑r double theta = lines[i][1]; //就是直線的角度 Point pt1, pt2; double a = cos(theta), b = sin(theta); double x0 = a * rho, y0 = b * rho; /*cout << pt1.y << "asd" << pt2.y<<"jiaodu"<< theta<<"zhi"<<a;*/
pt1.x = cvRound(x0 + 800 * (-b)); // + - 800是為了我換下面的線 pt1.y = cvRound(y0 + 800 * (a)); pt2.x = cvRound(x0 - 800 * (-b)); pt2.y = cvRound(y0 - 800 * (a)); line(dstImage, pt1, pt2, Scalar(0, 100, 195), 2); }

在這裡插入圖片描述

3.獲取四個座標

很簡單,橫著的線theta>1, 豎著的0<theta<1 把值賦給座標

if (theta >= 0 && theta < 1)
{ y1 = pt1.y; y2 = pt2.y; x1 = pt1.x; x2 = pt2.x; } if (theta > 1) { /*cout << pt1; cout << pt2; cout << pt2.x;*/ x3 = pt2.x; x4 = pt1.x; y3 = pt2.y; y4 = pt1.y; }

在這裡插入圖片描述

4.計算交點

雖然是八個座標,但我只用了其中四組,後面會講到。 輸入四組點,就可以返回交點了

CvPoint CrossPoint(const CvPoint line1, const CvPoint line2, const CvPoint line3, const CvPoint line4) //交點
{
	double x_member, x_denominator, y_member, y_denominator;
	CvPoint cross_point;
	x_denominator = line4.x*line2.y - line4.x*line1.y - line3.x*line2.y + line3.x*line1.y
		- line2.x*line4.y + line2.x*line3.y + line1.x*line4.y - line1.x*line3.y;

	x_member = line3.y*line4.x*line2.x - line4.y*line3.x*line2.x - line3.y*line4.x*line1.x + line4.y*line3.x*line1.x
		- line1.y*line2.x*line4.x + line2.y*line1.x*line4.x + line1.y*line2.x*line3.x - line2.y*line1.x*line3.x;

	if (x_denominator == 0)
		cross_point.x = 0;
	else
		cross_point.x = x_member / x_denominator;

	y_denominator = line4.y*line2.x - line4.y*line1.x - line3.y*line2.x + line1.x*line3.y
		- line2.y*line4.x + line2.y*line3.x + line1.y*line4.x - line1.y*line3.x;

	y_member = -line3.y*line4.x*line2.y + line4.y*line3.x*line2.y + line3.y*line4.x*line1.y - line4.y*line3.x*line1.y
		+ line1.y*line2.x*line4.y - line1.y*line2.x*line3.y - line2.y*line1.x*line4.y + line2.y*line1.x*line3.y;
		+ line1.y*line2.x*line4.y - line1.y*line2.x*line3.y - line2.y*line1.x*line4.y + line2.y*line1.x*line3.y;

	if (y_denominator == 0)
		cross_point.y = 0;
	else
		cross_point.y = y_member / y_denominator;

	return cross_point;  //平行返回(0,0)
}

5.畫圓圈

	Point e1, e2, e3, e4, u;
	e1 = Point(x1, y1);
	e2 = Point(x2, y2);
	e3 = Point(x3, y3);
	e4 = Point(x4, y4);
	u = CrossPoint(e1, e2, e3, e4);
	circle(srcImage, u, 25, (53, 91, 233), 4, 3);
	imshow("result", srcImage);

在這裡插入圖片描述 完成

不足:

1.可以看到一些誤差

理想狀態是隻有兩條線,直接取得中點,但是有時候鐳射太粗了。每條鐳射有2條直線,我都取得最後一條,所以導致結果實際中點在這裡(黑點處)

2.無直線沒有判斷

如果沒有檢測到直線,程式就崩了,想改進可以加一個沒檢測到直線後的操作就ok 在這裡插入圖片描述 如果要改進的畫的精度有很多辦法,比如: 1.找到四個交點,取四個交點的中心 2.或者去多條平行直線的中線再,剩2條直線再做計算

參考部落格:

博主只是選修課,就不繼續費心改進了。 有問題可以評論區交流。 過幾天放程式碼