【OpenCV】如何判断两条线段是否有交点
在图像处理中,有时需要判断两条线段是否相交,故将判断两条线段是否相交的方法总结如下,详细见代码。
方法一:
bool is_line_segments_intersect(std::pair<int, int> start_point1, std::pair<int, int> end_point1, std::pair<int, int> start_point2, std::pair<int, int> end_point2) {
// 解析坐标值
int x1 = start_point1.first;
int y1 = start_point1.second;
int x2 = end_point1.first;
int y2 = end_point1.second;
int x3 = start_point2.first;
int y3 = start_point2.second;
int x4 = end_point2.first;
int y4 = end_point2.second;
// 使用Cramer公式计算参数方程解
auto det = [](int a, int b, int c, int d) { return a * d - b * c; };
int d_value = det(x1 - x2, x4 - x3, y1 - y2, y4 - y3);
int p_value = det(x4 - x2, x4 - x3, y4 - y2, y4 - y3);
int q_value = det(x1 - x2, x4 - x2, y1 - y2, y4 - y2);
// 判断是否有交点
if (d_value != 0) {
double lam = static_cast<double>(p_value) / d_value;
double eta = static_cast<double>(q_value) / d_value;
if (0 <= lam && lam <= 1 && 0 <= eta && eta <= 1) {
return true;
}
return false;
}
if (p_value != 0 || q_value != 0) {
return false;
}
auto t1 = std::minmax(start_point1, end_point1);
auto t2 = std::minmax(start_point2, end_point2);
if (t1.second < t2.first || t2.second < t1.first) {
return false;
}
return true;
}
方法二:
bool isLineSegmentsIntersect(Point start1, Point end1, Point start2, Point end2) {
int ab_ac_cross_prod = crossProduct(start1, end1, start2);
int ab_ad_cross_prod = crossProduct(start1, end1, end2);
int cd_ca_cross_prod = crossProduct(start2, end2, start1);
int cd_cb_cross_prod = crossProduct(start2, end2, end1);
int ab_cd_cross_prod = crossProduct(start1, end1, start2);
int bc_cd_cross_prod = crossProduct(start2, end2, end1);
if (ab_ac_cross_prod * ab_ad_cross_prod <= 0 && cd_ca_cross_prod * cd_cb_cross_prod <= 0) {
if (ab_cd_cross_prod == 0) {
Point t1 = { min(start1.x, end1.x), min(start1.y, end1.y) };
Point t2 = { min(start2.x, end2.x), min(start2.y, end2.y) };
if (bc_cd_cross_prod == 0 && (t1.x <= t2.x && t2.x <= t1.y) && (t1.y <= t2.y && t2.y <= t1.y)) {
return true;
}
else {
return false;
}
}
else {
return true;
}
}
else {
return false;
}
}
测试如下
#include <algorithm>
#include <iostream>
using namespace std;
struct Point
{
int x, y;
};
int crossProduct(Point a, Point b, Point c){
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
int main()
{
Point start1 = { 1,1};
Point end1 = { 4, 4};
Point start2 = { 1, 0};
Point end2 = { 4, 0};
auto pair1= std::make_pair(1,1);
auto pair2 = std::make_pair(4,4);
auto pair3 = std::make_pair(1,4);
auto pair4 = std::make_pair(4,1);
if (is_line_segments_intersect(pair1, pair2,pair3,pair4))
{
cout << "The line1 segments intersect." << endl;
}
else
{
cout << "The line1 segments do not intersect." << endl;
}
if (isLineSegmentsIntersect(start1, end1, start2, end2))
{
cout << "The line2 segments intersect." << endl;
}
else
{
cout << "The line2 segments do not intersect." << endl;
}
system("pause");
return 0;
}