OpenCV实现了直线的拟合。

CV_IMPL void
cvFitLine( const CvArr* array, int dist, double param,
double reps, double aeps, float *line )
{
cv::AutoBuffer<schar> buffer; schar* points = 0;
union { CvContour contour; CvSeq seq; } header;
CvSeqBlock block;
CvSeq* ptseq = (CvSeq*)array;
int type; if( !line )
CV_Error( CV_StsNullPtr, "NULL pointer to line parameters" ); if( CV_IS_SEQ(ptseq) )
{
type = CV_SEQ_ELTYPE(ptseq);
if( ptseq->total == 0 )
CV_Error( CV_StsBadSize, "The sequence has no points" );
if( (type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
CV_ELEM_SIZE(type) != ptseq->elem_size )
CV_Error( CV_StsUnsupportedFormat,
"Input sequence must consist of 2d points or 3d points" );
}
else
{
CvMat* mat = (CvMat*)array;
type = CV_MAT_TYPE(mat->type);
if( !CV_IS_MAT(mat))
CV_Error( CV_StsBadArg, "Input array is not a sequence nor matrix" ); if( !CV_IS_MAT_CONT(mat->type) ||
(type!=CV_32FC2 && type!=CV_32FC3 && type!=CV_32SC2 && type!=CV_32SC3) ||
(mat->width != 1 && mat->height != 1))
CV_Error( CV_StsBadArg,
"Input array must be 1d continuous array of 2d or 3d points" ); ptseq = cvMakeSeqHeaderForArray(
CV_SEQ_KIND_GENERIC|type, sizeof(CvContour), CV_ELEM_SIZE(type), mat->data.ptr,
mat->width + mat->height - 1, &header.seq, &block );
} if( reps < 0 || aeps < 0 )
CV_Error( CV_StsOutOfRange, "Both reps and aeps must be non-negative" ); if( CV_MAT_DEPTH(type) == CV_32F && ptseq->first->next == ptseq->first )
{
/* no need to copy data in this case */
points = ptseq->first->data;
}
else
{
buffer.allocate(ptseq->total*CV_ELEM_SIZE(type));
points = buffer;
cvCvtSeqToArray( ptseq, points, CV_WHOLE_SEQ ); if( CV_MAT_DEPTH(type) != CV_32F )
{
int i, total = ptseq->total*CV_MAT_CN(type);
assert( CV_MAT_DEPTH(type) == CV_32S ); for( i = 0; i < total; i++ )
((float*)points)[i] = (float)((int*)points)[i];
}
} if( dist == CV_DIST_USER )
CV_Error( CV_StsBadArg, "User-defined distance is not allowed" ); if( CV_MAT_CN(type) == 2 )
{
IPPI_CALL( icvFitLine2D( (CvPoint2D32f*)points, ptseq->total,
dist, (float)param, (float)reps, (float)aeps, line ));
}
else
{
IPPI_CALL( icvFitLine3D( (CvPoint3D32f*)points, ptseq->total,
dist, (float)param, (float)reps, (float)aeps, line ));
}
}

  

二维的直线拟合?

/* Takes an array of 2D points, type of distance (including user-defined
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, where (A, B) is the normalized direction vector,
(C, D) is the point that belongs to the line. */ static CvStatus icvFitLine2D( CvPoint2D32f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
{
double EPS = count*FLT_EPSILON;
void (*calc_weights) (float *, int, float *) = 0;
void (*calc_weights_param) (float *, int, float *, float) = 0;
float *w; /* weights */
float *r; /* square distances */
int i, j, k;
float _line[6], _lineprev[6];
float rdelta = reps != 0 ? reps : 1.0f;
float adelta = aeps != 0 ? aeps : 0.01f;
double min_err = DBL_MAX, err = 0;
CvRNG rng = cvRNG(-1); memset( line, 0, 4*sizeof(line[0]) ); switch (dist)
{
case CV_DIST_L2:
return icvFitLine2D_wods( points, count, 0, line ); case CV_DIST_L1:
calc_weights = icvWeightL1;
break; case CV_DIST_L12:
calc_weights = icvWeightL12;
break; case CV_DIST_FAIR:
calc_weights_param = icvWeightFair;
break; case CV_DIST_WELSCH:
calc_weights_param = icvWeightWelsch;
break; case CV_DIST_HUBER:
calc_weights_param = icvWeightHuber;
break; /*case CV_DIST_USER:
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/ default:
return CV_BADFACTOR_ERR;
} w = (float *) cvAlloc( count * sizeof( float ));
r = (float *) cvAlloc( count * sizeof( float )); for( k = 0; k < 20; k++ )
{
int first = 1;
for( i = 0; i < count; i++ )
w[i] = 0.f; for( i = 0; i < MIN(count,10); )
{
j = cvRandInt(&rng) % count;
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
i++;
}
} icvFitLine2D_wods( points, count, w, _line );
for( i = 0; i < 30; i++ )
{
double sum_w = 0; if( first )
{
first = 0;
}
else
{
double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1];
t = MAX(t,-1.);
t = MIN(t,1.);
if( fabs(acos(t)) < adelta )
{
float x, y, d; x = (float) fabs( _line[2] - _lineprev[2] );
y = (float) fabs( _line[3] - _lineprev[3] ); d = x > y ? x : y;
if( d < rdelta )
break;
}
}
/* calculate distances */
err = icvCalcDist2D( points, count, _line, r );
if( err < EPS )
break; /* calculate weights */
if( calc_weights )
calc_weights( r, count, w );
else
calc_weights_param( r, count, w, _param ); for( j = 0; j < count; j++ )
sum_w += w[j]; if( fabs(sum_w) > FLT_EPSILON )
{
sum_w = 1./sum_w;
for( j = 0; j < count; j++ )
w[j] = (float)(w[j]*sum_w);
}
else
{
for( j = 0; j < count; j++ )
w[j] = 1.f;
} /* save the line parameters */
memcpy( _lineprev, _line, 4 * sizeof( float )); /* Run again... */
icvFitLine2D_wods( points, count, w, _line );
} if( err < min_err )
{
min_err = err;
memcpy( line, _line, 4 * sizeof(line[0]));
if( err < EPS )
break;
}
} cvFree( &w );
cvFree( &r );
return CV_OK;
}

调用的函数

 static CvStatus icvFitLine2D_wods( CvPoint2D32f * points, int _count, float *weights, float *line )
{
double x = , y = , x2 = , y2 = , xy = , w = ;
double dx2, dy2, dxy;
int i;
int count = _count;
float t; /* Calculating the average of x and y... */ if( weights == )
{
for( i = ; i < count; i += )
{
x += points[i].x;
y += points[i].y;
x2 += points[i].x * points[i].x;
y2 += points[i].y * points[i].y;
xy += points[i].x * points[i].y;
}
w = (float) count;
}
else
{
for( i = ; i < count; i += )
{
x += weights[i] * points[i].x;
y += weights[i] * points[i].y;
x2 += weights[i] * points[i].x * points[i].x;
y2 += weights[i] * points[i].y * points[i].y;
xy += weights[i] * points[i].x * points[i].y;
w += weights[i];
}
} x /= w;
y /= w;
x2 /= w;
y2 /= w;
xy /= w; dx2 = x2 - x * x;
dy2 = y2 - y * y;
dxy = xy - x * y; t = (float) atan2( * dxy, dx2 - dy2 ) / ;
line[] = (float) cos( t );
line[] = (float) sin( t ); line[] = (float) x;
line[] = (float) y; return CV_NO_ERR;
}

icvFitLine2D_wods

权重计算方法

 static void icvWeightL1( float *d, int count, float *w )
{
int i; for( i = ; i < count; i++ )
{
double t = fabs( (double) d[i] );
w[i] = (float)(. / MAX(t, eps));
}
} static void icvWeightL12( float *d, int count, float *w )
{
int i; for( i = ; i < count; i++ )
{
w[i] = 1.0f / (float) sqrt( + (double) (d[i] * d[i] * 0.5) );
}
} static void icvWeightHuber( float *d, int count, float *w, float _c )
{
int i;
const float c = _c <= ? 1.345f : _c; for( i = ; i < count; i++ )
{
if( d[i] < c )
w[i] = 1.0f;
else
w[i] = c/d[i];
}
} static void icvWeightFair( float *d, int count, float *w, float _c )
{
int i;
const float c = _c == ? / 1.3998f : / _c; for( i = ; i < count; i++ )
{
w[i] = / ( + d[i] * c);
}
} static void icvWeightWelsch( float *d, int count, float *w, float _c )
{
int i;
const float c = _c == ? / 2.9846f : / _c; for( i = ; i < count; i++ )
{
w[i] = (float) exp( -d[i] * d[i] * c * c );
}
}

三维的直线拟合?

/* Takes an array of 3D points, type of distance (including user-defined
distance specified by callbacks, fills the array of four floats with line
parameters A, B, C, D, E, F, where (A, B, C) is the normalized direction vector,
(D, E, F) is the point that belongs to the line. */ static CvStatus
icvFitLine3D( CvPoint3D32f * points, int count, int dist,
float _param, float reps, float aeps, float *line )
{
double EPS = count*FLT_EPSILON;
void (*calc_weights) (float *, int, float *) = 0;
void (*calc_weights_param) (float *, int, float *, float) = 0;
float *w; /* weights */
float *r; /* square distances */
int i, j, k;
float _line[6]={0,0,0,0,0,0}, _lineprev[6]={0,0,0,0,0,0};
float rdelta = reps != 0 ? reps : 1.0f;
float adelta = aeps != 0 ? aeps : 0.01f;
double min_err = DBL_MAX, err = 0;
CvRNG rng = cvRNG(-1); switch (dist)
{
case CV_DIST_L2:
return icvFitLine3D_wods( points, count, 0, line ); case CV_DIST_L1:
calc_weights = icvWeightL1;
break; case CV_DIST_L12:
calc_weights = icvWeightL12;
break; case CV_DIST_FAIR:
calc_weights_param = icvWeightFair;
break; case CV_DIST_WELSCH:
calc_weights_param = icvWeightWelsch;
break; case CV_DIST_HUBER:
calc_weights_param = icvWeightHuber;
break; /*case CV_DIST_USER:
_PFP.p = param;
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/ default:
return CV_BADFACTOR_ERR;
} w = (float *) cvAlloc( count * sizeof( float ));
r = (float *) cvAlloc( count * sizeof( float )); for( k = 0; k < 20; k++ )
{
int first = 1;
for( i = 0; i < count; i++ )
w[i] = 0.f; for( i = 0; i < MIN(count,10); )
{
j = cvRandInt(&rng) % count;
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
i++;
}
} icvFitLine3D_wods( points, count, w, _line );
for( i = 0; i < 30; i++ )
{
double sum_w = 0; if( first )
{
first = 0;
}
else
{
double t = _line[0] * _lineprev[0] + _line[1] * _lineprev[1] + _line[2] * _lineprev[2];
t = MAX(t,-1.);
t = MIN(t,1.);
if( fabs(acos(t)) < adelta )
{
float x, y, z, ax, ay, az, dx, dy, dz, d; x = _line[3] - _lineprev[3];
y = _line[4] - _lineprev[4];
z = _line[5] - _lineprev[5];
ax = _line[0] - _lineprev[0];
ay = _line[1] - _lineprev[1];
az = _line[2] - _lineprev[2];
dx = (float) fabs( y * az - z * ay );
dy = (float) fabs( z * ax - x * az );
dz = (float) fabs( x * ay - y * ax ); d = dx > dy ? (dx > dz ? dx : dz) : (dy > dz ? dy : dz);
if( d < rdelta )
break;
}
}
/* calculate distances */
if( icvCalcDist3D( points, count, _line, r ) < FLT_EPSILON*count )
break; /* calculate weights */
if( calc_weights )
calc_weights( r, count, w );
else
calc_weights_param( r, count, w, _param ); for( j = 0; j < count; j++ )
sum_w += w[j]; if( fabs(sum_w) > FLT_EPSILON )
{
sum_w = 1./sum_w;
for( j = 0; j < count; j++ )
w[j] = (float)(w[j]*sum_w);
}
else
{
for( j = 0; j < count; j++ )
w[j] = 1.f;
} /* save the line parameters */
memcpy( _lineprev, _line, 6 * sizeof( float )); /* Run again... */
icvFitLine3D_wods( points, count, w, _line );
} if( err < min_err )
{
min_err = err;
memcpy( line, _line, 6 * sizeof(line[0]));
if( err < EPS )
break;
}
} // Return...
cvFree( &w );
cvFree( &r );
return CV_OK;
}

  

调用的方法

 static CvStatus icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line )
{
int i;
float w0 = ;
float x0 = , y0 = , z0 = ;
float x2 = , y2 = , z2 = , xy = , yz = , xz = ;
float dx2, dy2, dz2, dxy, dxz, dyz;
float *v;
float n;
float det[], evc[], evl[]; memset( evl, , *sizeof(evl[]));
memset( evc, , *sizeof(evl[])); if( weights )
{
for( i = ; i < count; i++ )
{
float x = points[i].x;
float y = points[i].y;
float z = points[i].z;
float w = weights[i]; x2 += x * x * w;
xy += x * y * w;
xz += x * z * w;
y2 += y * y * w;
yz += y * z * w;
z2 += z * z * w;
x0 += x * w;
y0 += y * w;
z0 += z * w;
w0 += w;
}
}
else
{
for( i = ; i < count; i++ )
{
float x = points[i].x;
float y = points[i].y;
float z = points[i].z; x2 += x * x;
xy += x * y;
xz += x * z;
y2 += y * y;
yz += y * z;
z2 += z * z;
x0 += x;
y0 += y;
z0 += z;
}
w0 = (float) count;
} x2 /= w0;
xy /= w0;
xz /= w0;
y2 /= w0;
yz /= w0;
z2 /= w0; x0 /= w0;
y0 /= w0;
z0 /= w0; dx2 = x2 - x0 * x0;
dxy = xy - x0 * y0;
dxz = xz - x0 * z0;
dy2 = y2 - y0 * y0;
dyz = yz - y0 * z0;
dz2 = z2 - z0 * z0; det[] = dz2 + dy2;
det[] = -dxy;
det[] = -dxz;
det[] = det[];
det[] = dx2 + dz2;
det[] = -dyz;
det[] = det[];
det[] = det[];
det[] = dy2 + dx2; /* Searching for a eigenvector of det corresponding to the minimal eigenvalue */
#if 1
{
CvMat _det = cvMat( , , CV_32F, det );
CvMat _evc = cvMat( , , CV_32F, evc );
CvMat _evl = cvMat( , , CV_32F, evl );
cvEigenVV( &_det, &_evc, &_evl, );
i = evl[] < evl[] ? (evl[] < evl[] ? : ) : (evl[] < evl[] ? : );
}
#else
{
CvMat _det = cvMat( , , CV_32F, det );
CvMat _evc = cvMat( , , CV_32F, evc );
CvMat _evl = cvMat( , , CV_32F, evl ); cvSVD( &_det, &_evl, &_evc, , CV_SVD_MODIFY_A+CV_SVD_U_T );
}
i = ;
#endif
v = &evc[i * ];
n = (float) sqrt( (double)v[] * v[] + (double)v[] * v[] + (double)v[] * v[] );
n = (float)MAX(n, eps);
line[] = v[] / n;
line[] = v[] / n;
line[] = v[] / n;
line[] = x0;
line[] = y0;
line[] = z0; return CV_NO_ERR;
}

icvFitLine3D_wods

参考文献:

OpenCV 学习(直线拟合)

[OpenCV]直线拟合的更多相关文章

  1. (原)opencv直线拟合fitLine

    转载请注明出处 http://www.cnblogs.com/darkknightzh/p/5486234.html 参考网址: http://blog.csdn.net/thefutureisour ...

  2. opencv: 线性拟合

    opencv提供了fitline函数用于直线拟合,原型为: C++: void fitLine(InputArray points, OutputArray line, int distType, d ...

  3. OpenCV2马拉松第25圈——直线拟合与RANSAC算法

    计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g/article/details/28118095 收入囊中 最小二乘法(least ...

  4. opencv直线检测在c#、Android和ios下的实现方法

    opencv直线检测在c#.Android和ios下的实现方法 本文为作者原创,未经允许,不得转载 :原文由作者发表在博客园:http://www.cnblogs.com/panxiaochun/p/ ...

  5. 基于EM的多直线拟合

    作者:桂. 时间:2017-03-22  06:13:50 链接:http://www.cnblogs.com/xingshansi/p/6597796.html 声明:欢迎被转载,不过记得注明出处哦 ...

  6. 基于EM的多直线拟合实现及思考

    作者:桂. 时间:2017-03-22  06:13:50 链接:http://www.cnblogs.com/xingshansi/p/6597796.html 声明:欢迎被转载,不过记得注明出处哦 ...

  7. 2d-Lidar 点云多直线拟合算法

    具体步骤: EM+GMM(高斯模糊模型) 点云分割聚类算法的实现. 基于RANSAC单帧lidar数据直线拟合算法实现. 多帧lidar数据实时直线优化算法实现. 算法实现逻辑: Struct lin ...

  8. OpenCV 最小二乘拟合方法求取直线倾角

    工业相机拍摄的图像中,由于摄像质量的限制,图像中的直线经过处理后,会表现出比较严重的锯齿.在这种情况下求取直线的倾角(其实就是直线的斜率),如果是直接选取直线的开始点和结束点来计算,或是用opencv ...

  9. OpenCV:直线拟合——cv::fitLine()详解

    实现目的:有一系列的点,需要拟合出一条直线. cv::fitLine()的具体调用形式如下: void cv::fitLine( cv::InputArray points, // 二维点的数组或ve ...

随机推荐

  1. mysql(5.7)配置文件示例

    # For advice on how to change settings please see# http://dev.mysql.com/doc/refman/5.6/en/server-con ...

  2. idea 使用正则表达式 进行匹配替换

    关于正则表达式 可以参考相应的笔记 另外 如果要提取正则表达式中匹配到的内容,使用$1 - $... 按顺序取(第一个表达式 到 第N个表达式匹配到的数据),  这点和linux正则获取的方式是一样的

  3. 2018铁三测评题write以及一些想送给你们的话

    一..前言 此文献给实验室的萌新们,以及刚刚接触CTF的同学们,希望能对你们的成长起到一些帮助. 二.关于CTF 可能你已经接触过CTF或者对它有所了解,这里我再简单介绍一下. 1.什么是CTF? C ...

  4. ffmpeg转码器移植VC的project:ffmpeg for MFC

    本文介绍一个自己做的FFMPEG移植到VC下的开源project:ffmpeg for MFC.本project将ffmpegproject中的ffmpeg转码器(ffmpeg.c)移植到了VC环境下 ...

  5. C语言 · 8皇后问题改编

    8皇后问题(改编) 问题描述 规则同8皇后问题,但是棋盘上每格都有一个数字,要求八皇后所在格子数字之和最大. 输入格式 一个8*8的棋盘. 输出格式 所能得到的最大数字和 样例输入 1 2 3 4 5 ...

  6. python pyenv

    使用pyenv安装多个版本的python 管理多个python环境使用 virtualenv 请看  http://www.cnblogs.com/juandx/p/5357518.html 安装py ...

  7. Android中使用BufferedReader.readline阻塞读取不到数据,但是ready返回true

    通过socket测试工具在电脑上发送消息,Android真机可以收到响应BufferedReader.ready()返回true,但是readline却一直阻塞. 原因:readline()只有在遇到 ...

  8. 【目录】Docker 基本操作

    1 容器基本操作 : https://www.cnblogs.com/defineconst/p/9990611.html 2 容器启动退出 : https://www.cnblogs.com/def ...

  9. javascript变量作用域 全局及局部

    $("#inStartTime").datetimepicker({ format: 'yyyy-mm-dd hh:ii', autoclose: true, todayBtn: ...

  10. codeforces-707 C. Pythagorean Triples

    C. Pythagorean Triples time limit per test 1 second memory limit per test 256 megabytes input standa ...