opencv中的直线拟合函数 cvFitLine

    opencv中 2D 或 3D 点集的直线拟合

#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include <math.h>
int _tmain(int argc, _TCHAR* argv[])
{
	IplImage* img = cvCreateImage( cvSize( 500, 500 ), 8, 3 );
	CvRNG rng = cvRNG(-1); //cvRNG()跟一般的C语言srand()使用方法一样,要先给它一个种子,
	//但srand()用到的是unsigned int的32位种子范围,而cvRNG()用的是64位长整数种子。
	//初始化CvRNG资料结构,假如seed给0,它将会自动转成-1	cvRNG(64位种子)
	cvNamedWindow( "fitline", 1 );

	for(;;)
	{
		char key;
		int i;
		int	count = cvRandInt(&rng)%100 + 1; //产生1-100 之间的数
		int outliers = count/5; // 奇异点的个数。0--20 之间的数
		printf("count = %d", count);
		float a = cvRandReal(&rng)*200;  // 0~ 199 之间的浮点数 [cvRandReal 浮点型随机数并更新 RNG ,范围在 0..1 之间,不包括 。
		float b = cvRandReal(&rng)*40; //返回0 ~ 39之间的数
		float angle = cvRandReal(&rng)*CV_PI;  
		printf("count = %f", angle);
		float cos_a = cos(angle), sin_a = sin(angle);
		printf("cos_a = %f", cos_a);

		CvPoint pt1, pt2; //直线的两个端点
		CvPoint* points = (CvPoint*)malloc( count * sizeof(points[0])); //存放随机产生的点点,数目为count
		CvMat pointMat = cvMat( 1, count, CV_32SC2, points ); //点集, 存储count个随机点points
		float line[4]; //输出的直线参数。2D 拟合情况下,它是包含 4 个浮点数的数组 (vx, vy, x0, y0)
		               //其中 (vx, vy) 是线的单位向量而 (x0, y0) 是线上的某个点
		float d, t;
		b = MIN(a*0.3, b);

		// generate some points that are close to the line
		for( i = 0; i < count - outliers; i++ )
		{
			float x = (cvRandReal(&rng)*2-1)*a;
			float y = (cvRandReal(&rng)*2-1)*b;
			points[i].x = cvRound(x*cos_a - y*sin_a + img->width/2);
			points[i].y = cvRound(x*sin_a + y*cos_a + img->height/2);
		}
		// generate "completely off" points
		for( ; i < count; i++ )
		{
			points[i].x = cvRandInt(&rng) % img->width;
			points[i].y = cvRandInt(&rng) % img->height;
		}

		// find the optimal line 曲线拟合
		cvFitLine( &pointMat, CV_DIST_L1, 1, 0.001, 0.001, line ); 
		cvZero( img );
		

		//画出产生的随机分布的点点
		for( i = 0; i < count; i++ )
			cvCircle( img, points[i], 2, i < count - outliers ? CV_RGB(255, 0, 0) :CV_RGB(255,255,0), CV_FILLED, CV_AA, 0 );

		// ... and the long enough line to cross the whole image
		d = sqrt((double)line[0]*line[0] + (double)line[1]*line[1]);  //line[0 & 1]存储的是单位向量,所以d=1
		//printf("\n %f\n", d);
		line[0] /= d;
		line[1] /= d;

		//画出线段的两个端点(避免线太短,以线上一个随机点向两侧延伸line[0]*t )
		t = (float)(img->width + img->height) ;
		pt1.x = cvRound(line[2] - line[0]*t);
		pt1.y = cvRound(line[3] - line[1]*t);
		pt2.x = cvRound(line[2] + line[0]*t);
		pt2.y = cvRound(line[3] + line[1]*t);
		cvLine( img, pt1, pt2, CV_RGB(0,255,0), 3, CV_AA, 0 );

		cvShowImage( "fitline", img );
		key = (char) cvWaitKey(0);
		if( key == 27 || key == 'q' || key == 'Q' ) // 'ESC'
			break;
		free( points );
	}

	cvDestroyWindow( "fitline" );
	return 0;
}

关于函数 FitLine ,参考自 opencv手册。

FitLine

2D 或 3D 点集的直线拟合 
void  cvFitLine ( const CvArr* points,    int dist_type,    double param,  double reps,   double aeps,   float* line );

points 
2D 或 3D 点集,32-比特整数或浮点数坐标 

dist_type 
拟合的距离类型 (见讨论). 

param 
对某些距离的数字参数,如果是 0, 则选择某些最优值 

reps, aeps 
半径 (坐标原点到直线的距离) 和角度的精度,一般设为0.01。 

line 
输出的直线参数。2D 拟合情况下,它是包含 4 个浮点数的数组 (vx, vy, x0, y0),其中 (vx, vy) 是线的单位向量而 (x0, y0) 是线上的某个点. 

对 3D 拟合,它是包含 6 个浮点数的数组 (vx, vy, vz, x0, y0, z0), 其中 (vx, vy, vz) 是线的单位向量,而 (x0, y0, z0) 是线上某点。 


函数 cvFitLine 通过求 sumi:ρ(ri) 的最小值方法,用 2D 或 3D 点集拟合直线,其中 ri 是第 i 个点到直线的距离, ρ(r) 是下面的距离函数之一: 

dist_type=CV_DIST_L2 (L2): ρ(r)=r2/2 (最简单和最快的最小二乘法) 
dist_type=CV_DIST_L1 (L1): ρ(r)=r 
dist_type=CV_DIST_L12 (L1-L2): ρ(r)=2?[sqrt(1+r2/2) - 1] 
dist_type=CV_DIST_FAIR (Fair): ρ(r)=C2?[r/C - log(1 + r/C)], C=1.3998 
dist_type=CV_DIST_WELSCH (Welsch): ρ(r)=C2/2?[1 - exp(-(r/C)2)], C=2.9846 
dist_type=CV_DIST_HUBER (Huber): ρ(r)= r2/2, if r < C; C?(r-C/2), otherwise; C=1.345 


opencv中随机数的生成

=参考自:http://www.cnblogs.com/uestc-wxp/archive/2012/08/09/2630586.html

产生标准正态分布的随机数或矩阵的函数
概念
    1. 一般计算机的随机数都是伪随机数,以一个真随机数(种子)作为初始条件,然后用一定的算法迭代产生随机数序列。

    2. 随机数的“种子”就是产生随机数的第一次使用值,机制是通过一个比较复杂函数,将这个种子的值映射到随机数空间的某一个点上,并且产生的随机数均匀地(或者符合正态分布等)散步在空间中,以后产生的随机数都与前一个随机数有关。

    3. RNG : random number generation   随机数生成

二、opencv中的函数

1. CvRNG cvRNG(int64 seed);

   使用64位长整形种子,初始化随机数生成器状态。

   cvGetTickCount();

   返回64位长整形的时间数据,在opencv中是为CvRNG设置的专用种子。

2.  unsigned cvRandInt(CvRNG* rng);

   返回均匀分布的随机32位无符号整型值,并更新RNG的状态 ; 使用模操作可以获得确定边界的整形数值。

3.  double cvRandReal(CvRNG* rng);

   返回均匀分布的随即浮点数,范围在0-1(不含1),并更新RNG的状态。

4.  void cvRandArr( CvRNG* rng, CvArr* arr, int dist_type, CvScalar param1, CvScalar param2 );

   用随机数填充数组,并更新RNG的状态

   arr  输出数组

   dist_type  分布类型:   CV_RAND_UNI - 均匀分布  ; CV_RAND_NORMAL - 正态分布 或者 高斯分布

   param1  分布的第一个参数。如果是均匀分布它是随机数范围的闭下边界。如果是正态分布它是随机数的平均值。

   param2  分布的第二个参数。如果是均匀分布它是随机数范围的开上边界。如果是正态分布它是随机数的标准差。



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、付费专栏及课程。

余额充值