[OpenCV]直线拟合
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;
}
调用的函数
![](/assets/blank.gif)
![](/assets/blank.gif)
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;
}
调用的方法
![](/assets/blank.gif)
![](/assets/blank.gif)
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]直线拟合相关推荐
- OpenCV直线拟合检测
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:opencv学堂 OpenCV直线拟合检测 霍夫直线检测 ...
- OpenCV 直线拟合及应用
直线拟合顾名思义就是根据多个有限个数的点确定一条直线.依据为: 其中为第i个点到直线的距离,p(d)则为确定最小值的函数.而不同的p(d)对应着不同的直线拟合方法: OpenCV提供了7种(-1为用户 ...
- OpenCV | 直线拟合fitline函数(Python)
简介 之前做直线拟合时,自己写了一个利用最小二乘做直线拟合的程序,但是由于直线检测的误差比较大,拟合的效果并不好.个人不知道是什么原因,因此想尝试更改一下直线拟合的算法,后来找到了OpenCV中的fi ...
- OpenCV—直线拟合fitLine
本文的主要参考为官方文档OpenCV249-fitLine和博客-OpenCV 学习(直线拟合) 以及<Learning OpenCV 3>page425-426 OpenCV中提供的直线 ...
- OpenCV——直线拟合
相比于直线检测,直线拟合的最大特点是将所有数据只拟合出一条直线 void fitLine( InputArray points, OutputArray line, int distType,doub ...
- opencv 直线拟合
一.话说直线拟合 霍夫直线检测容易受到线段形状与噪声的干扰而失真,这个时候我们需要另辟蹊径,通过对图像进行二值分析,提取骨架,对骨架像素点拟合生成直线,这种做法在一些场景下非常有效,而且效果还比较好. ...
- OpenCV | 直线拟合fitline函数
学习目标: 学习掌握OpenCV的fitline函数 学习内容: cv::fitLine()的具体调用形式如下: void cv::fitLine( cv::InputArray points, // ...
- opencv直线拟合cv::fitLine()
通过2D或者2D点集拟合直线 void fitLine( InputArray points, OutputArray line, int distType,double param, double ...
- OpenCV fitline直线拟合函数学习
下图是OpenCV官方文档中,对直线拟合函数的详细介绍: fitLine()函数用于,对二维或三维空间中的点集进行直线拟合.共有六个参数: param 1:输入的点集,可以是Mat或者vector&l ...
最新文章
- [转]Mysql中的SQL优化与执行计划
- ML基石_56_TheoryOfGeneralization
- python代码示例下载-Python下载网易云歌单歌曲的示例代码
- 动态规划-最长回文子串
- php-cgi导致的502 Bad Gateway错误
- linux vscode配置spring boot开发环境
- oracle插入数据语句实例,oracle Insert 用法总结
- 计算机准考证打印山东省招生教育,山东省教育招生考试院2020高考准考证打印入口:wsbm.sdzk.cn...
- mybatis一次可以执行多个sql语句
- opencv+Java+android 灰度图像
- html 显示文本字段,HTML文本框和文本字段样式_五五站长网
- 华为鸿蒙系统首发设备,鸿蒙首发设备包装曝光:安卓已成过去式,鸿蒙正式走上舞台...
- 计算机操作系统 第一章:操作系统引论(知识梳理+脑图)
- php 怎么把数组按拼音,php实现数组按拼音顺序排序的方法
- 数据增强_炼丹笔记三:数据增强
- 一款优秀的IT资产管理系统-Snipe-IT 安装及用户手册中文版(一安装部署篇)
- 关于Windows 7与Ubuntu启动的一些注记(win7屏蔽ubuntu的启动项)
- 三菱FX5U系列PLC电池安装方法以及GX Works3内相关参数设置
- 宏基掠夺者圣盾5000、圣盾3000 评测
- 电脑开不了机 ,怎么解决?