OpenCV:简单计算曲线弧度-弓形弧度

Posted wishchin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OpenCV:简单计算曲线弧度-弓形弧度相关的知识,希望对你有一定的参考价值。

在判断曲线拟合度时候,需要进行曲线曲率计算。本文中使用根据弦的方法计算曲线弧度半径,得到曲率。

首先判定是否为弧:

简单判定:不要选取较多的点,若线段不是偏向一个方向,则不为弧

		bool  isArcCurve( std::vector<cv::Point> &curve )
		
			bool isArc = false;

			cv::Point ps, pe,vec;
			ps = cv::Point(curve[0]);
			pe = cv::Point(curve[curve.size() - 1]);
			double angle0 = colorWish::arccos(ps, pe);

			std::vector<double > rls;//左侧还是右侧
			for (int i = 1; i < curve.size() - 1; ++i) 
				double angle1 = colorWish::arccos( ps, curve[i] );
				rls.push_back( angle1 );
			

			//若出现一次反转,则判定为否,以此保证曲线的单方向
			std::vector<bool >  rlbs;
			for ( int i = 0; i < rls.size() ; ++i ) 
				bool isRight = false;
				if ( rls[i]>angle0 )
					isRight = true;
				 else
					isRight = false;
				
				rlbs.push_back( isRight );
			

			//若出现一次反转,则判定为否,以此保证曲线的单方向
			bool isSinVec = false;
			bool isRight = false;
			if ( rlbs.size()>0 )
				isRight = rlbs[0];
				for (int i = 1; i < rlbs.size(); ++i)
					if ( isRight!= rlbs[i])
						isSinVec = true;
					
				
			else
			
		
			isArc = isSinVec;
			return isArc;
		
	double colorWish::dis2(double x1, double y1, double x2, double y2) 
		return (x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1);
	
	// 计算两点的坐标夹角,360度余弦值
	double colorWish::arccos(double x0, double y0, double x1, double y1)
	
		double angle = 0;
		double l = dis2(x0, y0, x1, y1);
		l = sqrt(l);
		if (y1 - y0 > 0)  angle = acos((x1 - x0) / l); 
		else  angle = 3.141592653 + 3.141592653 - acos((x1 - x0) / l); 
		//std::cout << (angle) << " ";
		return angle;
	//arccos

	double colorWish::arccos(cv::Point cneter, cv::Point p) 
		return arccos(double(cneter.x), double(cneter.y), double(p.x), double(p.y));
	

计算弧度值:

计算弓形曲率,使用遍历方法找弓形高(曲线上任一点),根据海伦公式计算出高

		//计算弓形的曲率-此方法仍然只保证对连续点集确定有效
		//计算方法:两端长度为弦长,高度为弓形高,以此计算曲率
		double  getArcCurvity( std::vector<cv::Point> &curve )
		
			double curvity = 0;
			if ( curve.size()<4 )
				return 0;
			

			cv::Point ps, pe;
			ps = cv::Point( curve[0] );
			pe = cv::Point( curve[curve.size()-1] );
			double lArc = disCv( ps, pe );//弦长
			double hArc = 0;
			for ( int i=1;i<curve.size()-1;++i )
				double h = p2Line( curve[i],ps,pe );//点到直线的距离
				if (hArc<h)
					hArc = h;
				
			
		
			//曲率公式-使用R^2 = L^2 +(R-H)^2即 R= ( L^2/H +H)/2
			double R = 0.5*( lArc*lArc/hArc +hArc );
			curvity = 1 / R;

			return curvity;
		
		//点 p 到线段(p1,p2)的距离-只计算三角形情况,且只计算垂直距离
		//使用海伦公式
		double p2Line(const cv::Point &p0,const cv::Point &p1, const  cv::Point &p2)
		
			double dis = 0;
			double a, b, c,  p, S,h;
			a = disCv(p0, p1);
			b = disCv(p0, p2);
			c = disCv(p1, p2);
			p = (a + b + c)/2;
			S = sqrt(p*(p-a)*(p - b)*(p - c) );
			h = S * 2 / a;

			dis = h ;
			return dis;
		
		double disCv(const cv::Point2f &p1, const  cv::Point2f &p2)
		
			double dis = 0;
			dis = sqrt((p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y));
			return dis;
		

弓形弧度半径公式:

double R = 0.5*( lArc*lArc/hArc +hArc );
double  curvity = 1 / R;

此种方法,比使用houghCircle方法粗糙,但简单直观。

寻找结果图像:

 

 

 

 

 

以上是关于OpenCV:简单计算曲线弧度-弓形弧度的主要内容,如果未能解决你的问题,请参考以下文章

说说如何使用 Canvas 绘制弧线与曲线

输出弓形矩阵

感染弓形虫的人更愿意创业:4星|《环球科学》2018年09月号

canvas二:绘制圆和其他曲线

角度和弧度的转换

角度与弧度的换算公式?