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:简单计算曲线弧度-弓形弧度的主要内容,如果未能解决你的问题,请参考以下文章