当前位置:网站首页>OpenCV每日函数 结构分析和形状描述符(8) fitLine函数 拟合直线
OpenCV每日函数 结构分析和形状描述符(8) fitLine函数 拟合直线
2022-06-25 06:40:00 【坐望云起】
一、fitLine函数
1、函数原型
从 2D 或 3D 点集拟合到直线。函数 fitLine 通过最小化 将线拟合到 2D 或 3D 点集,其中
是第
个点之间的距离,线和
是距离函数,以下之一:
DIST_L2 | ![]() |
DIST_L1 | ![]() |
DIST_L12 | ![]() |
DIST_FAIR | ![]() |
DIST_WELSCH | ![]() |
DIST_HUBER | ![]() |
该算法基于 M-estimator技术,该技术使用加权最小二乘算法迭代拟合线。 在每次迭代之后,权重 被调整为与
成反比。
2、参数详解
points | 2D 或 3D 点的输入向量,存储在 std::vector<> 或 Mat. |
line | 输出线参数。 在 2D 拟合的情况下,它应该是 4 个元素的向量(如 Vec4f) - (vx, vy, x0, y0),其中 (vx, vy) 是与直线共线的归一化向量, (x0, y0) 是 线上的一个点。 在 3D 拟合的情况下,它应该是 6 个元素的向量(如 Vec6f) - (vx, vy, vz, x0, y0, z0),其中 (vx, vy, vz) 是与直线共线的归一化向量,并且 (x0, y0, z0) 是线上的一个点。 |
distType | M 估计器使用的距离,请参阅DistanceTypes |
param | 某些类型的距离的数值参数 ( C )。 如果为 0,则选择最优值。 |
reps | 足够的半径精度(坐标原点和直线之间的距离)。 |
aeps | 角度精确度。 对于 reps 和 aeps 来说,0.01 是一个很好的默认值。 |
二、OpenCV源码
1、源码路径
opencv\modules\imgproc\src\linefit.cpp
2、源码代码
static void fitLine2D( const Point2f * 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;
int i, j, k;
float _line[4], _lineprev[4];
float rdelta = reps != 0 ? reps : 1.0f;
float adelta = aeps != 0 ? aeps : 0.01f;
double min_err = DBL_MAX, err = 0;
RNG rng((uint64)-1);
memset( line, 0, 4*sizeof(line[0]) );
switch (dist)
{
case CV_DIST_L2:
return fitLine2D_wods( points, count, 0, line );
case CV_DIST_L1:
calc_weights = weightL1;
break;
case CV_DIST_L12:
calc_weights = weightL12;
break;
case CV_DIST_FAIR:
calc_weights_param = weightFair;
break;
case CV_DIST_WELSCH:
calc_weights_param = weightWelsch;
break;
case CV_DIST_HUBER:
calc_weights_param = weightHuber;
break;
/*case DIST_USER:
calc_weights = (void ( * )(float *, int, float *)) _PFP.fp;
break;*/
default:
CV_Error(CV_StsBadArg, "Unknown distance type");
}
AutoBuffer<float> wr(count*2);
float *w = wr.data(), *r = w + count;
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 = rng.uniform(0, count);
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
i++;
}
}
fitLine2D_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 = calcDist2D( points, count, _line, r );
if (err < min_err)
{
min_err = err;
memcpy(line, _line, 4 * sizeof(line[0]));
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... */
fitLine2D_wods( points, count, w, _line );
}
if( err < min_err )
{
min_err = err;
memcpy( line, _line, 4 * sizeof(line[0]));
if( err < EPS )
break;
}
}
}
/* 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 void fitLine3D( Point3f * 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;
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;
RNG rng((uint64)-1);
switch (dist)
{
case CV_DIST_L2:
return fitLine3D_wods( points, count, 0, line );
case CV_DIST_L1:
calc_weights = weightL1;
break;
case CV_DIST_L12:
calc_weights = weightL12;
break;
case CV_DIST_FAIR:
calc_weights_param = weightFair;
break;
case CV_DIST_WELSCH:
calc_weights_param = weightWelsch;
break;
case CV_DIST_HUBER:
calc_weights_param = weightHuber;
break;
default:
CV_Error(CV_StsBadArg, "Unknown distance");
}
AutoBuffer<float> buf(count*2);
float *w = buf.data(), *r = w + count;
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 = rng.uniform(0, count);
if( w[j] < FLT_EPSILON )
{
w[j] = 1.f;
i++;
}
}
fitLine3D_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 */
err = calcDist3D( points, count, _line, r );
if (err < min_err)
{
min_err = err;
memcpy(line, _line, 6 * sizeof(line[0]));
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, 6 * sizeof( float ));
/* Run again... */
fitLine3D_wods( points, count, w, _line );
}
if( err < min_err )
{
min_err = err;
memcpy( line, _line, 6 * sizeof(line[0]));
if( err < EPS )
break;
}
}
}
}
void cv::fitLine( InputArray _points, OutputArray _line, int distType,
double param, double reps, double aeps )
{
CV_INSTRUMENT_REGION();
Mat points = _points.getMat();
float linebuf[6]={0.f};
int npoints2 = points.checkVector(2, -1, false);
int npoints3 = points.checkVector(3, -1, false);
CV_Assert( npoints2 >= 0 || npoints3 >= 0 );
if( points.depth() != CV_32F || !points.isContinuous() )
{
Mat temp;
points.convertTo(temp, CV_32F);
points = temp;
}
if( npoints2 >= 0 )
fitLine2D( points.ptr<Point2f>(), npoints2, distType,
(float)param, (float)reps, (float)aeps, linebuf);
else
fitLine3D( points.ptr<Point3f>(), npoints3, distType,
(float)param, (float)reps, (float)aeps, linebuf);
Mat(npoints2 >= 0 ? 4 : 6, 1, CV_32F, linebuf).copyTo(_line);
}
三、示例参考
边栏推荐
- 单位转换-毫米转像素-像素转毫米
- SQL solve select basic statement
- Storage of Galileo broadcast ephemeris in rtklib-b33
- CPDA|数据分析师成长之路如何起步?
- Sichuan earth microelectronics ca-is1300 isolated operational amplifier for current detection is on the market
- 一次弄清楚 Handler 可能导致的内存泄漏和解决办法
- 【Qt】快捷键
- Summary of small problems in smartbugs installation
- Sichuan earth microelectronics high performance, high integration and low cost isolated 485 transceiver
- Sichuan Tuwei ca-if1051 can transceiver has passed aec-q100 grade 1 certification
猜你喜欢
ELK + filebeat日志解析、日志入库优化 、logstash过滤器配置属性
Find out what informatization is, and let enterprises embark on the right path of transformation and upgrading
Tupu software digital twin 3D wind farm, offshore wind power of smart wind power
(tool class) use SecureCRT as the communication medium
三年营收连续下滑,天地壹号困在醋饮料里
Application of point cloud intelligent drawing in intelligent construction site
Chuantu microelectronics 𞓜 subminiature package isolated half duplex 485 transceiver
海思3559 sample解析:vio
realsense d455 semantic_ Slam implements semantic octree mapping
[single chip microcomputer project training] multipoint temperature wireless acquisition system based on nRF905
随机推荐
对链表进行插入排序[dummy统一操作+断链核心--被动节点]
【批處理DOS-CMD命令-匯總和小結】-外部命令-cmd下載命令、抓包命令(wget)
[distillation] pointdistiller: structured knowledge distillationwards efficient and compact 3D detection
【Qt】快捷键
Distributed quorum NWR of the alchemy furnace of the Supreme Master
Introduction to Sichuan Tuwei ca-is3082w isolated rs-485/rs-422 transceiver
海思3559 sample解析:vio
VOCALOID笔记
“空间转换”显著提升陡崖点云的地面点提取质量
VectorDraw Web Library 10.10
数据可视化没有重点怎么办?
指南针可以开股票账户吗?安全吗?
Genuine photoshop2022 purchase experience sharing
Chuantuwei ca-is3720lw alternative material No. iso7820fdw
[single chip microcomputer project training] multipoint temperature wireless acquisition system based on nRF905
Selection of Hongmeng page menu
How to use printf of 51 single chip microcomputer
AttributeError: ‘Upsample‘ object has no attribute ‘recompute_ scale_ factor‘
Chuantu microelectronics breaks through the high-end isolator analog chip market with ca-is3062w
[batch dos-cmd command - summary and summary] - file and directory operation commands (MD, RD, xcopy, dir, CD, set, move, copy, del, type, sort)