【OpenCV】如何判断两条线段是否有交点

【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;
}

测试结果

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要寻找多条线段交点及其坐标,可以使用OpenCV中的`cv2.HoughLinesP()`函数进行Hough变换,该函数可以将线段表示为(x1, y1)和(x2, y2)的形式。 以下是一个基本的示例代码,该代码从图像中找到线段,然后使用Hough变换找到线段交点的坐标: ``` python import cv2 import numpy as np # 读取图像 img = cv2.imread('image.jpg') # 转换为灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3) # 使用Hough变换检测线段 lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=100, maxLineGap=10) # 找到线段交点的坐标 points = [] for i in range(len(lines)): for j in range(i+1, len(lines)): line1 = lines[i][0] line2 = lines[j][0] x1, y1 = line1[0], line1[1] x2, y2 = line1[2], line1[3] x3, y3 = line2[0], line2[1] x4, y4 = line2[2], line2[3] # 计算线段交点 px = int((x1*y2-y1*x2)*(x3-x4)-(x1-x2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)) py = int((x1*y2-y1*x2)*(y3-y4)-(y1-y2)*(x3*y4-y3*x4))/((x1-x2)*(y3-y4)-(y1-y2)*(x3-x4)) points.append((px, py)) # 在图像上绘制线段交点 for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2) for point in points: cv2.circle(img, point, 5, (0, 0, 255), -1) # 显示图像 cv2.imshow('Result', img) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在上面的代码中,我们首先读取图像,然后将其转换为灰度图像,并进行边缘检测。接下来,我们使用Hough变换检测线段,并找到线段交点的坐标。最后,我们在图像上绘制线段交点,并显示结果。 需要注意的是,这种方法只能找到两条线段交点。如果要找到多条线段交点,需要进行组合,将每条线段与其他线段进行组合,找到所有交点。这可能会导致算法的时间复杂度较高。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

shanhedian2013

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值