Bootstrap

OpenCV图像处理——获取穿过圆的直线与圆相交的两个点

在OpenCV中,没有直接的函数来计算直线与圆的交点,但可以通过数学方法来实现这一功能。以下是计算直线与圆交点的步骤,以及相应的C++代码示例:

  1. 确定直线方程:使用直线上的两个点 P 1 ( x 1 , y 1 ) P1(x1, y1) P1(x1,y1) P 2 ( x 2 , y 2 ) P2(x2, y2) P2(x2,y2)来确定直线的斜率 m m m和截距 b b b。直线方程可以表示为 y = m x + b y = mx + b y=mx+b

  2. 代入圆的方程:将直线方程 y = m x + b y = mx + b y=mx+b代入圆的方程 ( x − c x ) 2 + ( y − c y ) 2 = r 2 (x - cx)^2 + (y - cy)^2 = r^2 (xcx)2+(ycy)2=r2

  3. 解二次方程:将上述方程转换为关于 x x x的二次方程,然后使用求根公式求解。

  4. 计算交点:对于二次方程的每个根,计算相应的 y y y值,得到交点的坐标。

  5. 验证交点:确保每个计算出的点都在圆的边界内,并且位于直线上。

C++ 代码示例

#include <opencv2/opencv.hpp>
#include <iostream>
#include <cmath>

using namespace cv;
using namespace std;

bool findLineCircleIntersections(cv::Point2f center, float redius,
	Point2f P1, Point2f P2, Point2f& c1, Point2f& c2)
{
	// 圆心和半径
	float x1 = P1.x;
	float y1 = P1.y;
	float x2 = P2.x;
	float y2 = P2.y;

	// 直线的斜率和截距
	float k, b;
	if (x1 == x2) {
		k = std::numeric_limits<float>::infinity();  // 垂直线
		b = x1;  // x = b
	}
	else {
		k = (y2 - y1) / (x2 - x1);  // 斜率
		b = y1 - k * x1;  // 截距
	}

	// 方程: (x - cx)^2 + (kx + b - cy)^2 = r^2
	// 展开并合并同类项得到二次方程 ax^2 + bx + c = 0
	float A = 1 + k * k;
	float B = 2 * (k * (b - center.y) - center.x);
	float C = center.x * center.x + (b - center.y) * (b - center.y) - redius * redius;

	// 计算判别式
	float delta = B * B - 4 * A * C;
	if (delta < 0) {
		// 没有交点
		return false;
	}

	// 解二次方程
	float sqrtDelta = sqrt(delta);
	float x1_intersect = (-B + sqrtDelta) / (2 * A);
	float x2_intersect = (-B - sqrtDelta) / (2 * A);
	float y1_intersect = k * x1_intersect + b;
	float y2_intersect = k * x2_intersect + b;

	c1 = Point2f(x1_intersect, y1_intersect);
	c2 = Point2f(x2_intersect, y2_intersect);
	return true;
}

int main()
{
	cv::Mat cv_src(cv::Size(640, 640), CV_8UC3, cv::Scalar(255,255,255));
	float cx = 100.0, cy = 100.0, r = 50.0;  // 圆心和半径
	Point2f P1(10, 120.0);  // 直线上的点1
	Point2f P2(120.0, 50.0);  // 直线上的点2
	Point2f c1, c2;

	cv::circle(cv_src, cv::Point2f(100.0, 100.0), 50, cv::Scalar(0,0,0), 1, cv::LINE_AA);
	cv::line(cv_src, P1, P2, cv::Scalar(0,255,0), 1, cv::LINE_AA);

	cv::imshow("src", cv_src);

	cv::Mat cv_dst = cv_src.clone();

	if (findLineCircleIntersections(cv::Point2f(cx, cy), r, P1, P2, c1, c2))
	{
		cv::circle(cv_dst, c1, 10, cv::Scalar(0,0,255),1, cv::LINE_AA);
		cv::circle(cv_dst, c2, 10, cv::Scalar(0,0,255),1,cv::LINE_AA);
		cout << "Intersection points: (" << c1.x << ", " << c1.y << ") and ("
			<< c2.x << ", " << c2.y << ")" << endl;
	}
	else
	{
		cout << "No intersection points found." << endl;
	}

	cv::imshow("dst", cv_dst);
	cv::waitKey(0);

	return 0;
}

在这里插入图片描述
实现的效果:
在这里插入图片描述

;