假设现在有一个点集,需要拟合出最能够表达点集轮廓的几条直线,并求直线之间的交点。
从点集中拟合直线可以采用的方法:随机抽样一致性(RANSAC),霍夫变换(though transform)

思路1

利用点斜式表达直线,然后求解两条直线组成的方程组。
{y=k1∗x+b1y=k2∗x+b2\begin{cases} y = k1 * x + b1 \\ y = k2 * x + b2 \end{cases} {y=k1∗x+b1y=k2∗x+b2​

  • 缺点
    通过比较两条直线的斜率来判断两条直线是否平行,但是直线垂直时,斜率无穷大,无法比较两条直线。
 /** @brief 计算直线的交点@param lines 直线:Vec4d=(vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line.@param crossPoints 保存直线的交点@param mask 掩膜*/void crossPointsOfLines(std::vector<cv::Vec4d>& lines, std::vector<cv::Point2f> &crossPoints, int nPoints, cv::Mat& mask){crossPoints.clear();for (int i = 0; i < lines.size() && crossPoints.size() < nPoints; i++){for (int j = i + 1; j < lines.size() && crossPoints.size() < nPoints; j++){float ka = (float)lines.at(i)[1] / float(lines.at(i)[0] + 0.000001f);//slope of LineA float kb = (float)lines.at(j)[1] / float(lines.at(j)[0] + 0.000001f);//slope of LineB//if (std::abs(std::abs(ka) - std::abs(kb)) > 1.0) //two lines are not probably parallelif ((std::abs(ka) > 1) && (std::abs(kb) < 1) || (std::abs(ka) < 1) && (std::abs(kb) > 1))//two lines are not probably parallel{cv::Point2d ptA(lines.at(i)[2], lines.at(i)[3]);cv::Point2d ptB(lines.at(j)[2], lines.at(j)[3]);cv::Point2f crossPoint;crossPoint.x = float(ka*ptA.x - ptA.y - kb*ptB.x + ptB.y) / float(ka - kb);crossPoint.y = float(ka*kb*(ptA.x - ptB.x) - kb*ptA.y + ka*ptB.y) / float(ka - kb);crossPoints.push_back(crossPoint);
#ifdef _DEBUGcv::circle(mask, crossPoint, 2, cv::Scalar(0, 0, 255), -1, cv::FILLED);
#endif}}}if (crossPoints.size() < nPoints){LOG(ERROR) << type() << "::crossPointsOfLines: " << "cross points is less than parameter nPoints.";}}

本函数使用的直线是opencv函数fitline从点集中拟合出来的直线,通过平行向量(vx,vy)和一个点(x,y)来表示直线。
本函数主要应用于两条直线平行或者垂直的情况,所以我通过斜率是否大于1,判断是否平行。严格来说并不正确,所有没有复用性。

思路2

使用通用的直线表达方法,然后求解方程组。
{a1∗x+b1∗y=c1a2∗x+b2∗y=c2\begin{cases} a1 * x + b1 *y = c1 \\ a2 * x + b2 *y = c2 \end{cases} {a1∗x+b1∗y=c1a2∗x+b2∗y=c2​

输入直线为:Vec4d=(vx, vy, x0, y0), 即 x−x0y−y0=VxVy\frac{x - x0}{y-y0} =\frac{ Vx}{Vy}y−y0x−x0​=VyVx​ ,求解方程组可得交点。
通过方向向量判断直线是否垂直,避免斜率无穷大的情况。

  • 缺点
    提前判断,代码比较乱;
 /** @brief 计算直线的交点@param lines 直线:Vec4d=(vx, vy, x0, y0), where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is a point on the line.@param crossPoints 保存直线的交点@param mask 掩膜*/
bool crossPointsOfLines(std::vector<cv::Vec4d>& lines, std::vector<cv::Point2f> &crossPoints, int nPoints, cv::Mat& mask)
{crossPoints.clear();for (int i = 0; i < lines.size() && crossPoints.size() < nPoints; i++){const cv::Vec4d lineA = lines.at(i);bool isVecticalA = std::abs(lineA[0]) < 0.02;bool isHorizontalA = std::abs(lineA[1]) < 0.02;for (int j = i + 1; j < lines.size() && crossPoints.size() < nPoints; j++){const cv::Vec4d lineB = lines.at(j);bool isVecticalB = std::abs(lineB[0]) < 0.02;bool isHorizontalB = std::abs(lineB[1]) < 0.02;if ((isVecticalA && isVecticalB) || (isHorizontalA && isHorizontalB) )//两条线都垂直,或者平行{continue;}cv::Point2f crossPoint;auto calcB = [&lines](int index)->double {return  lines.at(index)[0] * lines.at(index)[3] - lines.at(index)[1] * lines.at(index)[2];// B = Vx * Y - Vy * X};//auto calcCrossPoint = [&](int vIndex)->cv::Point2f { //};if (isVecticalA ){crossPoint.x = lineA[2];  // x = -( Vx * Y - Vy * X)= Xif (isHorizontalB){crossPoint.y = lineB[3];  // y = Vx * Y - Vy * X = Y}else{crossPoint.y = (calcB(j) + lineB[1] * crossPoint.x) / lineB[0]; // y = (B + Vy * x)/ Vx}crossPoints.push_back(crossPoint);}else if (isVecticalB){crossPoint.x = lineB[2];  // x = -( Vx * Y - Vy * X) = Xif (isHorizontalA){crossPoint.y = lineA[3];  // y = Vx * Y - Vy * X = Y}else{crossPoint.y = (calcB(i) + lineA[1] * crossPoint.x) / lineA[0]; // y = (B + Vy * x)/ Vx}crossPoints.push_back(crossPoint);}else{float det = (lineA[0] * lineB[1] - lineB[0] * lineA[1]);crossPoint.x = (lineB[0] * calcB(i) - lineA[0] * calcB(j)) / det;crossPoint.y = (lineB[1] * calcB(i) - lineA[1] * calcB(j)) / det;crossPoints.push_back(crossPoint);}
#ifdef _DEBUGcv::circle(mask, crossPoint, 2, cv::Scalar(0, 0, 255), -1, cv::FILLED);
#endif}}if (crossPoints.size() < nPoints){return false;}return true;
}

思路三

使用矩阵来表达直线组成的方程组,矩阵无解的情况就对应直线平行。
两条直线组成方程组
{a1∗x+b1∗y=c1a2∗x+b2∗y=c2\begin{cases} a1 * x + b1 *y = c1 \\ a2 * x + b2 *y = c2 \end{cases} {a1∗x+b1∗y=c1a2∗x+b2∗y=c2​
求解得
{x=c1∗b2−c2∗b1a1∗b2−a2∗b1y=a1∗c2−a2∗c1a1∗b2−a2∗b1\begin{cases} x = \frac{c1*b2 - c2*b1}{a1*b2-a2*b1} \\ y = \frac{a1*c2 - a2*c1}{a1*b2-a2*b1} \end{cases} {x=a1∗b2−a2∗b1c1∗b2−c2∗b1​y=a1∗b2−a2∗b1a1∗c2−a2∗c1​​


D=∣a1b1a2b2∣D1=∣c1b1c2b2∣D2=∣a1c1a2c2∣D = \left| \begin{array} {ccc} a1&b1\\ a2&b2 \end{array} \right| \\ D1 = \left| \begin{array} {ccc} c1&b1\\ c2&b2 \end{array} \right| \\ D2 = \left| \begin{array} {ccc} a1&c1\\ a2&c2 \end{array} \right| D=∣∣∣∣​a1a2​b1b2​∣∣∣∣​D1=∣∣∣∣​c1c2​b1b2​∣∣∣∣​D2=∣∣∣∣​a1a2​c1c2​∣∣∣∣​

x=D1Dy=D2Dx = \frac{D1}{D} y = \frac{D2}{D} x=DD1​y=DD2​

void crossPointsOfLines(std::vector<cv::Vec4d>& lines, std::vector<cv::Point2f> &crossPoints)
{for (int i = 0; i < lines.size(); i++){const cv::Vec4d& lineA = lines.at(i);for (int j=i+1;j < lines.size();j++){const cv::Vec4d& lineB = lines.at(j);//double cos = lineA[0] * lineB[0] + lineA[1] * lineB[1];// cos a = A^T * B ;A,B为单位向量 //if (std::abs(cos) > 0.99 ) // 两条直线几乎平行,没有交点//{// continue;//}// linaA: a1 * x + b1 * y = c1// linaB: a2 * x + b2 * y = c2float a1 = -lineA[1];float b1 = lineA[0];float c1 = lineA[0] * lineA[3] - lineA[1] * lineA[2];float a2 = -lineB[1];float b2 = lineB[0];float c2 = lineB[0] * lineB[3] - lineB[1] * lineB[2];/*        | a1 b1 |            | c1 b1 |       | a1 c1 |D = | a2 b2 |       D1 = | c2 b2 |  D2 = | a2 c2 |*/ float Det = a1*b2 - a2 *b1;float Det1 = c1*b2 - c2*b1;float Det2 = a1*c2 - a2*c1;if (std::abs(Det) < 0.001) //两条直线平行,方程组无解{continue;}cv::Point2f pt = { Det1 / Det, Det2 / Det };crossPoints.push_back(pt);}}
}

参考文献

OpenCV找任意两条直线的交点
OpenCV找直线及直线的交点
随机抽样一致性算法(ransac)

求取两条直线的交点坐标

谈谈"求线段交点"的几种算法(js实现,完整版)

在OpenCV中求解两条直线的交点

opencv求解两条直线的交点相关推荐

  1. java两条直线交点_求两条直线的交点坐标

    看UdaCity机器学习大纲,发现入门班中有一条:编写算法计算一组直线或平面的交点. 遂从最简单的直角坐标系两条直线的交点开始, 直线1的方程解析式: 2x-y=0; 直线2的方程解析式: 4x-5y ...

  2. 用矢量变换的方法求两条直线的交点

    求两条直线的交点,最常见的写法是列出两条直线的方程,联立求解.     但这种办法的弊端很大:     1 )算法是坐标系相关的,要考虑直线是水平还是垂直,写出很多判断条件,增加了程序的不稳定性    ...

  3. Java黑皮书课后题第8章:*8.31(几何:交点)编写一个方法,返回两条直线的交点。四个点存放在4*2的二维数组points中。编写一个程序,提示用户输入4个点,并显示交点

    *8.31(几何:交点)编写一个方法,返回两条直线的交点.四个点存放在4*2的二维数组points中.编写一个程序,提示用户输入4个点,并显示交点 题目 题目描述 破题 代码 本题运行实例 题目 题目 ...

  4. 两条直线求交点c语言,C§ 3.3.1两条直线的交点坐标(5页)-原创力文档

    § 3.1两条直线的交点坐标 学习目标 1.掌握判断两直线相交的方法:会求两直线交点坐标: 2.体会判断两直线相交中的数形结合思想. 学习过程 一.课前准备: (预习教材P112~ P114,找出疑 ...

  5. Revit 2011 二次开发之“取得两条直线的交点”

    Revit提供特殊的类和集合来完成这些操作,积累一下.     /// <summary>     /// Utility method for getting the intersect ...

  6. JAVA计算两条直线的交点(判断两条线段相交)

    //计算两条直线的交点 //输入四个点,前两个点确定线段1,后两个点确定线段2 //输出交点坐标 public class Main{public static void main(String ar ...

  7. 求空间中两条直线的交点

    求空间中两条直线的交点 求交点坐标的问题完全可以用数学的方法求得结果的表达公式来解决啊 设P1(x1,y1,z1),P2(x2,y2,z2) L2:P3(x3,y3,z3),P4(x4,y4,z4) ...

  8. 两条直线的交点 c语言,计算两条直线的交点(C#)

    PS:从其他地方看到的源码是有问题的.下面是修正后的 /// /// 计算两条直线的交点 /// /// L1的点1坐标 /// L1的点2坐标 /// L2的点1坐标 /// L2的点2坐标 /// ...

  9. 两条直线的交点(叉积)

    /*在两条直线相交时,求相交点方法1:可以直线方程来求解,但是效率低下,而且程序繁琐.方法2:使用叉积公式求交点,即高效又简便.介绍方法2:设mul(p1,p2,p0)为p1p0与p0p1的叉积,即m ...

最新文章

  1. 让Json更懂中文 JSON_UNESCAPED_UNICODE
  2. QT中树控件QTreeView开发实例
  3. 使用snoopy logger记录用户命令
  4. 昨天又写到个结构体排序,用多种cmp
  5. C/C++ atof函数 - C语言零基础入门教程
  6. linux 宽字符串,C语言中的多字节字符与宽字符
  7. 首次push本地代码到github上出现的问题及解决方案
  8. TCPip详解学习--广播,多播
  9. gbk字库音序对照表
  10. 反编译 - ILSpy的使用方法(看Unity源代码的方法)
  11. k8s mysql 弹性_k8s 弹性伸缩,基于prometheus自定义指标
  12. 如何压缩jpg图片的大小?
  13. 视频编码格式、视频码率、视频帧率、分辨率的概念
  14. 支持I2S数字音频接口;音频功放芯片NTP8835C
  15. 观 小楼老师Axure /得
  16. 利用多线程爬点dianying回家慢慢看【python爬虫入门进阶】(05)
  17. 99刀299刀 开发者账户 区别
  18. CH340国产USB转异步串口芯片替代CP2102对比CH340C与CH340G
  19. JQuery 动态设置setInterval定时器时间间隔
  20. 网上作业批改系统的设计与实现(JSP,MySQL)

热门文章

  1. linux pycharm无法输入中文,linux下idea、pycharm等输入中文拼音时满3个字母后无法继续拼音输入的问题...
  2. P2P暴雷后续 完善互联网金融大数据风控模型成为命门
  3. 解析IE6,IE7,火狐浏览器兼容性写法
  4. 计算机中级培训计划,2021年计算机操作员中级培训专项计划.doc
  5. 《Android 博客gif图片制作》
  6. 智慧多功能综合杆路灯承载城市文化新定义
  7. kaldi训练thchs30做在线识别
  8. v6!!!!!!!!!!!
  9. 【Python】Benewake(北醒) TF-LC02(TTL)基于Python运用说明
  10. Android ViewPager 垂直滑动 纵向滑动 VerticalViewPager