2018.11.16:
代码已上传:https://download.csdn.net/download/qq_38269418/10788619
平台:
VS2017
C++
OPENCV3库
//边缘检测
Canny(srcImage, dstImage, 210, 250, 3);
//灰度化
cvtColor(midImage, dstImage, CV_GRAY2BGR);
// 定义矢量结构存放检测出来的直线
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"<
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);
}
很简单,横着的线theta>1.57, 竖着的0
if (theta > 0 && theta < 1.57)
{
y1 = pt1.y;
y2 = pt2.y;
x1 = pt1.x;
x2 = pt2.x;
}
if (theta >= 1.57 || theta == 0)
{
/*cout << pt1;
cout << pt2;
cout << pt2.x;*/
x3 = pt2.x;
x4 = pt1.x;
y3 = pt2.y;
y4 = pt1.y;
}
虽然是八个坐标,但我只用了其中四组,后面会讲到。
输入四组点,就可以返回交点了
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)
}
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);
理想状态是只有两条线,直接取得中点,但是有时候激光太粗了。每条激光有2条直线,我都取得最后一条,所以导致结果实际中点在这里(黑点处)
如果没有检测到直线,程序就崩了,想改进可以加一个没检测到直线后的操作就ok
如果要改进的画的精度有很多办法,比如:
1.找到四个交点,取四个交点的中心
2.或者去多条平行直线的中线再,剩2条直线再做计算
https://www.cnblogs.com/skyfsm/p/6881686.html
https://blog.csdn.net/Tron_future/article/details/77828665
博主只是选修课,就不继续费心改进了。
有问题可以评论区交流。
过几天放代码