OpenCV下的直线拟合

出处: http://blog.csdn.net/Tangyongkang/

 

OpenCV中 CvSeq 对象由以下语句生成

  //创建 CvSeq的容器对象

   CvMemStorage* storage = cvCreateMemStorage(0);

   // 创建 CvSeq对象
  // 第一个参数   序列的符号标志
  // 第二个参数 队列(Sequence)头的Size,必须大于等于sizeof(CvSeq)
  // 第三个参数  节点的Size,元素的大小,以字节为单位,必须与序列类型一致
  // 第四个参数  存储CvSeq的容器对象,序列的位置
  CvSeq* point_seq = cvCreateSeq( CV_32FC2, sizeof(CvSeq), 
   sizeof(CvPoint2D32f), storage );
 

 

用完后,以下列形式释放内存

  cvClearSeq(point_seq);
  cvReleaseMemStorage(&storage);
 
向CvSeq中添加数据时:
cvSeqPush(point_seq, &cvPoint2D32f(x坐标,y坐标));
 
FitLine函数的用法:
// 二维空间点拟合时 是 float[4]
// 三位空间点拟合时 是 float[6]
float *line = new float[4];
 
 
// 第一个参数: 存储点序列
// 第二个参数: 拟合算法,其中 CV_DIST_L2 就是平常的最小二乘法
// 第三,第四,第五参数推荐值是 0,   0.01,  0.01,
// 第六参数: line中存储返回值
// 二维空间时: line[0--3] 分别为 (vx, vy, x0, y0)
//      其中 vx, vy 是正规化之后的斜率向量。 x0,y0 是直线经过的点。
  // 三维空间时: line[0--5]  分别是 (vx, vy, vz, x0,  y0, z0) 。意义同上
cvFitLine(point_seq,CV_DIST_L2,0,0.01,0.01,line);
 
 
拟合程序::
 
#include <cv.h>
#include <stdio.h>
#include <math.h>
float myLinearity(CvSeq *);
int main(void)
{
int i;
double fx[] = {0.0, 0.301, 0.477, 0.602, 0.699, 0.778, 0.845, 0.903, 0.954, 1.0};
double fy[] = {3.874, 3.202, 2.781, 2.49, 2.274, 2.156, 1.934, 1.74, 1.653, 1.662};
float *line = new float[4];
float linearity=0.0f;
//Sequence的容器
CvMemStorage* storage = cvCreateMemStorage(0);
//三维空间的话,把CV_32FC2改为CV_32FC3、 把CvPoint2D32f 改为 CvPoint3D32f
CvSeq* point_seq = cvCreateSeq( CV_32FC2, sizeof(CvSeq), sizeof(CvPoint2D32f), storage );
for (i=0; i<10; i++){
//向Sequence中追加元素
cvSeqPush(point_seq, &cvPoint2D32f(fx[i],fy[i]));
}
linearity = myLinearity(point_seq);
cvFitLine(point_seq,CV_DIST_L2,0,0.01,0.01,line);
fprintf(stdout,"v=(%f,%f),vy/vx=%f,(x,y)=(%f,%f), 
Linearity=%f/n",line[0],line[1],line[1]/line[0],
line[2],line[3],linearity);
cvClearSeq(point_seq);
cvReleaseMemStorage(&storage);
return 0;
}
 
//计算直线拟合度
float myLinearity(CvSeq *seq)
{
int i;
CvPoint2D32f *p;
float *x = new float[seq->total];
float *y = new float[seq->total];
float x_bar=0.0, y_bar=0.0;
float u11=0.0, u20=0.0, u02=0.0;
float linearity=0.0;
 
for (i=0; i < seq->total; i++)
{
p=(CvPoint2D32f*)cvGetSeqElem(seq,i);
x[i]=p->x;
y[i]=p->y;
}
//x_bar, y_bar
for (i=0; i < seq->total; i++)
{
x_bar+=x[i];
y_bar+=y[i];
}
x_bar/=seq->total;
y_bar/=seq->total;
 
for (i=0; i < seq->total; i++)
{
u11+=((x[i]-x_bar)*(y[i]-y_bar));
u20+=pow(x[i]-x_bar,2.0f);
u02+=pow(y[i]-y_bar,2.0f);
}
u11/=seq->total;
u20/=seq->total;
u02/=seq->total;
 
//计算直线度
linearity = sqrt(4*pow(u11,2.0f)+pow(u20-u02,2.0f))/(u20+u02);
return linearity;
}
 
 
**运行结果
v=(0.399377,-0.916787),vy/vx=-2.295543,(x,y)=(0.655900,2.376600), Linearity=0.999105
OpenCV提供了直线拟合函数fitLine,可以用于拟合多条直线。该函数的原型如下: void fitLine(InputArray points, OutputArray line, int distType, double param, double reps, double aeps); 其中,points是输入的坐标点集合,line是输出的拟合直线的参数,distType是距离类型,param是距离参数,reps是拟合精度,aeps是角度精度。 要进行多条直线拟合,可以将多组坐标点分别传入fitLine函数进行拟合,得到对应的直线参数。可以使用std::vector<cv::Point>来存储每组坐标点,然后循环调用fitLine函数进行拟合。 以下是一个示例代码,用于拟合多条直线: std::vector<std::vector<cv::Point>> pointSets; // 存储多组坐标点 std::vector<cv::Vec4f> lines; // 存储拟合直线的参数 // 循环拟合每组坐标点 for (int i = 0; i < pointSets.size(); i++) { cv::Mat pointsMat(pointSets\[i\]); cv::Vec4f line; cv::fitLine(pointsMat, line, cv::DIST_L2, 0, 0.01, 0.01); lines.push_back(line); } 这样,lines中就存储拟合得到的多条直线的参数。每个直线的参数是一个cv::Vec4f,其中前两个元素表示直线上的一个点,后两个元素表示直线的方向向量。 请注意,拟合直线的精度参数reps和aeps可以根据实际需求进行调整,以获得更好的拟合效果。 #### 引用[.reference_title] - *1* *2* *3* [OpenCV 学习(直线拟合)](https://blog.csdn.net/liyuanbhu/article/details/50193947)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值