RANSAC之c语言实现

关于RANSAC算法已经写过两篇博文,本篇主要是基于前两篇的相关理论实现的,同时这里实现的RANSAC实现了定点化。前两篇博文请参考:matlab实现ransacopencv和c++实现ransac。若有不当之处,望指教,谢谢!

 

typedef struct
{
	int x;
	int y;
}point_t;

typedef struct LineModel
{
	int mSlope;
	int mIntercept;
	int flag;
}LineModel;

 

 

#ifndef _RANSAC_H_
#define _RANSAC_H_

#include "least_square.h"
#include "stack_pt.h"

void ransac_computeModel(point_t* points, point_t *consensusSet, point_t *maybeInliers, LineModel *mBestModel, const int n, const int mIterations, float mThreshold);

void interpolate_point(point_t *p, point_t p1, point_t p2, int step_size, int *count);

#endif;
#include "ransac.h"

int s = 0;

//获取点集中两个随机点
void getMaybeInliers(point_t* points,point_t *maybeInliers,const int n,int* count) 
{
	int randPointIndex_0 = (int)(n * rand() / RAND_MAX - 1.0);
	int randPointindex_1 = (int)(n * rand() / RAND_MAX - 1.0);

	if (randPointIndex_0 >= 0 && randPointIndex_0 < n && randPointindex_1 >= 0 && randPointindex_1 < n)
	{
		maybeInliers[0] = points[randPointIndex_0];
		maybeInliers[1] = points[randPointindex_1];
		*count = 2;
	}
}

//检测两个点之间的距离是否小于1
int isdegenerate(point_t p1, point_t p2)
{
	int norm = sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
	if (norm < 1.0)
		return TRUE;
	return FALSE;
}

//返回直线信息:斜率和截距
LineModel getModel(const point_t p1, const point_t p2)
{
	LineModel model;/* = xmalloc(sizeof(LineModel));*/
	if (p2.x != p1.x)
	{
		model.mSlope = (((p2.y - p1.y) << 10))/ (p2.x - p1.x);
		model.mIntercept = (p1.y <<10) - model.mSlope * p1.x;
	}
	else
	{
		model.mSlope = (1<<31) - 1;
		model.mIntercept =  - ((1 << 31) - 1);
	}

	return model;
}

//检测点是否相等
int isMember(point_t p, point_t* pList)
{
	int isMember = 0;

	for (int i = 0; i < 2; i++)
	{
		if (point_equal(p, pList[i]))
		{
			isMember = 1;
		}
	}

	return isMember;
}

int64_t getDistance(point_t p, LineModel model)
{
	int64_t distance = 10 << 10;

	if (fabs(model.mSlope) < 1000.)
	{
		int64_t k = (int64_t)((model.mSlope));
		int64_t b = (int64_t)((model.mIntercept));
		distance = (k * p.x - (p.y << 10) + b)*(k * p.x - (p.y << 10) + b) / (((k*k) >> 10) + (1 << 10));
	}

	return distance;
}

//检测点是否符合模型条件
int fitsModel(point_t p,LineModel model,int mThreshold)
{
	int fits = 0;

	//点到直线的距离
	int64_t distance = getDistance(p, model);

	if (distance < (mThreshold << 10))
		fits = 1;

	return fits;
}

void ransac_push(point_t* pt, point_t p0)
{
	pt[s++] = p0;
}

void ransac_pop(point_t* pt)
{
	pt[--s];
}

int getModelRank(point_t* points, LineModel model,const int n,float mThreshold)
{
	int count = 0;
	for (unsigned int i = 0; i < n; i++)
	{
		if (fitsModel(points[i], model, mThreshold))
			count++;
	}

	return count;
}

void ransac_computeModel(point_t* points, point_t *consensusSet, point_t *maybeInliers, LineModel *mBestModel, const int n, const int mIterations, float mThreshold)
{
	int foundModel = 0;
	int iterations = 0;
	int count = 0;
	int mRequiredInliers = 2;
	s = 0;
	int mBestRank = 0;
	mBestModel->flag = FALSE;

	while (iterations < mIterations)
	{
		s = 0;
		count = 0;
		getMaybeInliers(points, maybeInliers,n, &count);
		if (count == 2)
		{
			//两点之间的距离小于1,则跳过
			if (isdegenerate(maybeInliers[0], maybeInliers[1]))
			{
				iterations++;
				continue;
			}

			ransac_push(consensusSet,maybeInliers[0]);
			ransac_push(consensusSet, maybeInliers[1]);
			LineModel model = getModel(maybeInliers[0], maybeInliers[1]);

			for (int i = 0; i < n; i++)
			{
				//排除和随机取到的点相同的点
				if (!isMember(points[i], maybeInliers))
				{
					if (fitsModel(points[i],model,mThreshold))
						ransac_push(consensusSet, points[i]);
				}
			}

			if (s >= mRequiredInliers)
			{
				model = least_square(consensusSet,s);
				int rank = getModelRank(consensusSet, model, s, mThreshold);

				if (rank > mBestRank && model.mIntercept != -1024)
				{
					mBestModel->flag = TRUE;
					mBestModel -> mSlope = model.mSlope;
					mBestModel -> mIntercept = model.mIntercept;
					mBestRank = rank;
				}
			}

			iterations++;
		}
	}
}


void interpolate_point(point_t *p, point_t p1, point_t p2, int step_size,int *count)
{
	int steps = abs(p2.x - p1.x) / step_size + 1;
	p[*count] = p1;
	(*count)++;

	float start_x, end_x, start_y, end_y;

	if (p1.x < p2.x)
	{
		start_x = p1.x;
		start_y = p1.y;
		end_x = p2.x;
		end_y = p2.y;
	}
	else
	{
		start_x = p2.x;
		start_y = p2.y;
		end_x = p1.x;
		end_y = p1.y;
	}

	if (steps < 1)
		return;

	for (int i = 1; i <= steps; i++)
	{
		int new_x = start_x + i * step_size;
		int new_y = (end_y - start_y) / (end_x - start_x) * (new_x - start_x) + start_y;

		p[*count] = point_res(new_x,new_y);
		(*count)++;
	}

}

 

 

 

 

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值