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 );elsecalc_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;
}

调用的函数

 1 static CvStatus icvFitLine2D_wods( CvPoint2D32f * points, int _count, float *weights, float *line )
 2 {
 3     double x = 0, y = 0, x2 = 0, y2 = 0, xy = 0, w = 0;
 4     double dx2, dy2, dxy;
 5     int i;
 6     int count = _count;
 7     float t;
 8
 9     /* Calculating the average of x and y... */
10
11     if( weights == 0 )
12     {
13         for( i = 0; i < count; i += 1 )
14         {
15             x += points[i].x;
16             y += points[i].y;
17             x2 += points[i].x * points[i].x;
18             y2 += points[i].y * points[i].y;
19             xy += points[i].x * points[i].y;
20         }
21         w = (float) count;
22     }
23     else
24     {
25         for( i = 0; i < count; i += 1 )
26         {
27             x += weights[i] * points[i].x;
28             y += weights[i] * points[i].y;
29             x2 += weights[i] * points[i].x * points[i].x;
30             y2 += weights[i] * points[i].y * points[i].y;
31             xy += weights[i] * points[i].x * points[i].y;
32             w += weights[i];
33         }
34     }
35
36     x /= w;
37     y /= w;
38     x2 /= w;
39     y2 /= w;
40     xy /= w;
41
42     dx2 = x2 - x * x;
43     dy2 = y2 - y * y;
44     dxy = xy - x * y;
45
46     t = (float) atan2( 2 * dxy, dx2 - dy2 ) / 2;
47     line[0] = (float) cos( t );
48     line[1] = (float) sin( t );
49
50     line[2] = (float) x;
51     line[3] = (float) y;
52
53     return CV_NO_ERR;
54 }

icvFitLine2D_wods

权重计算方法

 1 static void icvWeightL1( float *d, int count, float *w )
 2 {
 3     int i;
 4
 5     for( i = 0; i < count; i++ )
 6     {
 7         double t = fabs( (double) d[i] );
 8         w[i] = (float)(1. / MAX(t, eps));
 9     }
10 }
11
12 static void icvWeightL12( float *d, int count, float *w )
13 {
14     int i;
15
16     for( i = 0; i < count; i++ )
17     {
18         w[i] = 1.0f / (float) sqrt( 1 + (double) (d[i] * d[i] * 0.5) );
19     }
20 }
21
22
23 static void icvWeightHuber( float *d, int count, float *w, float _c )
24 {
25     int i;
26     const float c = _c <= 0 ? 1.345f : _c;
27
28     for( i = 0; i < count; i++ )
29     {
30         if( d[i] < c )
31             w[i] = 1.0f;
32         else
33             w[i] = c/d[i];
34     }
35 }
36
37
38 static void icvWeightFair( float *d, int count, float *w, float _c )
39 {
40     int i;
41     const float c = _c == 0 ? 1 / 1.3998f : 1 / _c;
42
43     for( i = 0; i < count; i++ )
44     {
45         w[i] = 1 / (1 + d[i] * c);
46     }
47 }
48
49 static void icvWeightWelsch( float *d, int count, float *w, float _c )
50 {
51     int i;
52     const float c = _c == 0 ? 1 / 2.9846f : 1 / _c;
53
54     for( i = 0; i < count; i++ )
55     {
56         w[i] = (float) exp( -d[i] * d[i] * c * c );
57     }
58 }

三维的直线拟合?

/* 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 );elsecalc_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;
}

  

调用的方法

  1 static CvStatus icvFitLine3D_wods( CvPoint3D32f * points, int count, float *weights, float *line )
  2 {
  3     int i;
  4     float w0 = 0;
  5     float x0 = 0, y0 = 0, z0 = 0;
  6     float x2 = 0, y2 = 0, z2 = 0, xy = 0, yz = 0, xz = 0;
  7     float dx2, dy2, dz2, dxy, dxz, dyz;
  8     float *v;
  9     float n;
 10     float det[9], evc[9], evl[3];
 11
 12     memset( evl, 0, 3*sizeof(evl[0]));
 13     memset( evc, 0, 9*sizeof(evl[0]));
 14
 15     if( weights )
 16     {
 17         for( i = 0; i < count; i++ )
 18         {
 19             float x = points[i].x;
 20             float y = points[i].y;
 21             float z = points[i].z;
 22             float w = weights[i];
 23
 24
 25             x2 += x * x * w;
 26             xy += x * y * w;
 27             xz += x * z * w;
 28             y2 += y * y * w;
 29             yz += y * z * w;
 30             z2 += z * z * w;
 31             x0 += x * w;
 32             y0 += y * w;
 33             z0 += z * w;
 34             w0 += w;
 35         }
 36     }
 37     else
 38     {
 39         for( i = 0; i < count; i++ )
 40         {
 41             float x = points[i].x;
 42             float y = points[i].y;
 43             float z = points[i].z;
 44
 45             x2 += x * x;
 46             xy += x * y;
 47             xz += x * z;
 48             y2 += y * y;
 49             yz += y * z;
 50             z2 += z * z;
 51             x0 += x;
 52             y0 += y;
 53             z0 += z;
 54         }
 55         w0 = (float) count;
 56     }
 57
 58     x2 /= w0;
 59     xy /= w0;
 60     xz /= w0;
 61     y2 /= w0;
 62     yz /= w0;
 63     z2 /= w0;
 64
 65     x0 /= w0;
 66     y0 /= w0;
 67     z0 /= w0;
 68
 69     dx2 = x2 - x0 * x0;
 70     dxy = xy - x0 * y0;
 71     dxz = xz - x0 * z0;
 72     dy2 = y2 - y0 * y0;
 73     dyz = yz - y0 * z0;
 74     dz2 = z2 - z0 * z0;
 75
 76     det[0] = dz2 + dy2;
 77     det[1] = -dxy;
 78     det[2] = -dxz;
 79     det[3] = det[1];
 80     det[4] = dx2 + dz2;
 81     det[5] = -dyz;
 82     det[6] = det[2];
 83     det[7] = det[5];
 84     det[8] = dy2 + dx2;
 85
 86     /* Searching for a eigenvector of det corresponding to the minimal eigenvalue */
 87 #if 1
 88     {
 89     CvMat _det = cvMat( 3, 3, CV_32F, det );
 90     CvMat _evc = cvMat( 3, 3, CV_32F, evc );
 91     CvMat _evl = cvMat( 3, 1, CV_32F, evl );
 92     cvEigenVV( &_det, &_evc, &_evl, 0 );
 93     i = evl[0] < evl[1] ? (evl[0] < evl[2] ? 0 : 2) : (evl[1] < evl[2] ? 1 : 2);
 94     }
 95 #else
 96     {
 97         CvMat _det = cvMat( 3, 3, CV_32F, det );
 98         CvMat _evc = cvMat( 3, 3, CV_32F, evc );
 99         CvMat _evl = cvMat( 1, 3, CV_32F, evl );
100
101         cvSVD( &_det, &_evl, &_evc, 0, CV_SVD_MODIFY_A+CV_SVD_U_T );
102     }
103     i = 2;
104 #endif
105     v = &evc[i * 3];
106     n = (float) sqrt( (double)v[0] * v[0] + (double)v[1] * v[1] + (double)v[2] * v[2] );
107     n = (float)MAX(n, eps);
108     line[0] = v[0] / n;
109     line[1] = v[1] / n;
110     line[2] = v[2] / n;
111     line[3] = x0;
112     line[4] = y0;
113     line[5] = z0;
114
115     return CV_NO_ERR;
116 }

icvFitLine3D_wods

参考文献:

OpenCV 学习(直线拟合)

转载于:https://www.cnblogs.com/yhlx125/p/9240548.html

[OpenCV]直线拟合相关推荐

  1. OpenCV直线拟合检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 OpenCV直线拟合检测 霍夫直线检测 ...

  2. OpenCV 直线拟合及应用

    直线拟合顾名思义就是根据多个有限个数的点确定一条直线.依据为: 其中为第i个点到直线的距离,p(d)则为确定最小值的函数.而不同的p(d)对应着不同的直线拟合方法: OpenCV提供了7种(-1为用户 ...

  3. OpenCV | 直线拟合fitline函数(Python)

    简介 之前做直线拟合时,自己写了一个利用最小二乘做直线拟合的程序,但是由于直线检测的误差比较大,拟合的效果并不好.个人不知道是什么原因,因此想尝试更改一下直线拟合的算法,后来找到了OpenCV中的fi ...

  4. OpenCV—直线拟合fitLine

    本文的主要参考为官方文档OpenCV249-fitLine和博客-OpenCV 学习(直线拟合) 以及<Learning OpenCV 3>page425-426 OpenCV中提供的直线 ...

  5. OpenCV——直线拟合

    相比于直线检测,直线拟合的最大特点是将所有数据只拟合出一条直线 void fitLine( InputArray points, OutputArray line, int distType,doub ...

  6. opencv 直线拟合

    一.话说直线拟合 霍夫直线检测容易受到线段形状与噪声的干扰而失真,这个时候我们需要另辟蹊径,通过对图像进行二值分析,提取骨架,对骨架像素点拟合生成直线,这种做法在一些场景下非常有效,而且效果还比较好. ...

  7. OpenCV | 直线拟合fitline函数

    学习目标: 学习掌握OpenCV的fitline函数 学习内容: cv::fitLine()的具体调用形式如下: void cv::fitLine( cv::InputArray points, // ...

  8. opencv直线拟合cv::fitLine()

    通过2D或者2D点集拟合直线 void fitLine( InputArray points, OutputArray line, int distType,double param, double ...

  9. OpenCV fitline直线拟合函数学习

    下图是OpenCV官方文档中,对直线拟合函数的详细介绍: fitLine()函数用于,对二维或三维空间中的点集进行直线拟合.共有六个参数: param 1:输入的点集,可以是Mat或者vector&l ...

最新文章

  1. [转]Mysql中的SQL优化与执行计划
  2. ML基石_56_TheoryOfGeneralization
  3. python代码示例下载-Python下载网易云歌单歌曲的示例代码
  4. 动态规划-最长回文子串
  5. php-cgi导致的502 Bad Gateway错误
  6. linux vscode配置spring boot开发环境
  7. oracle插入数据语句实例,oracle Insert 用法总结
  8. 计算机准考证打印山东省招生教育,山东省教育招生考试院2020高考准考证打印入口:wsbm.sdzk.cn...
  9. mybatis一次可以执行多个sql语句
  10. opencv+Java+android 灰度图像
  11. html 显示文本字段,HTML文本框和文本字段样式_五五站长网
  12. 华为鸿蒙系统首发设备,鸿蒙首发设备包装曝光:安卓已成过去式,鸿蒙正式走上舞台...
  13. 计算机操作系统 第一章:操作系统引论(知识梳理+脑图)
  14. php 怎么把数组按拼音,php实现数组按拼音顺序排序的方法
  15. 数据增强_炼丹笔记三:数据增强
  16. 一款优秀的IT资产管理系统-Snipe-IT 安装及用户手册中文版(一安装部署篇)
  17. 关于Windows 7与Ubuntu启动的一些注记(win7屏蔽ubuntu的启动项)
  18. 三菱FX5U系列PLC电池安装方法以及GX Works3内相关参数设置
  19. 宏基掠夺者圣盾5000、圣盾3000 评测
  20. 电脑开不了机 ,怎么解决?

热门文章

  1. abap选择屏幕上的button
  2. 阻止保存要求重新创建表的更改
  3. flash流媒体资料
  4. vs2010 SQL Server Compact 3.5出错
  5. Oracle教程之四招提高Oracle位图索引的使用效果
  6. 10年追逐技术潮流,差一点儿就两手空空,竹篮打水,留给我的只有经验
  7. Community Server系列之九:CS2中的用户管理1(MemberRole)
  8. Maven学习总结(九)——使用Nexus搭建Maven私服
  9. java并发订单号生成
  10. python模块学下urllib