• 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 
    #include 
    #include 
    
    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;
    }
    
    

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

  • 相关阅读:
    雷池社区WAF:保护您的网站免受黑客攻击 | 开源日报 0918
    四嗪活性基团修饰PROTACTetrazine-Ph-PEG5-Ph-tetrazine/acid/NHS ester/SS-amine性质研究
    关于Python中math 和 decimal 模块的解析与实践
    重新认识下JVM级别的本地缓存框架Guava Cache(2)——深入解读其容量限制与数据淘汰策略
    电子数据取证-流程与技术
    C++ AVL树手撕代码实现
    特殊要求!2023年初级会计考试报名需要这些材料!
    VScode platformio的使用
    2021 ICPC澳门题解(8/11)
    基于android的网络考试系统APP(ssm+uinapp+Mysql)
  • 原文地址:https://blog.csdn.net/matt45m/article/details/140398750