计算轮廓点的最小凸包像素面积,最小外接圆的快速方法

计算轮廓点的最小凸包像素面积,最小外接圆的快速方法

计算轮廓点的最小凸包像素面积和求解最小外接圆的方法有很多,本文各举出一种比较简单且快速的方法,读者可根据实际情况定义返回值精度,本文采用的是整型精度,代码如下:
typedef struct Contours
{//轮廓点结构体,通过malloc来分配
	int height;//bmp Y坐标
	int width;//bmp X坐标
	int stateFlag;//点类型标志位
} contour;

typedef struct ContourInfo
{//轮廓信息结构体,通过malloc来分配
	int position;//记录单个轮廓在轮廓点序列中的起始位置
	int count;//记录单个轮廓的点个数
} contourInfo;

int contourConvexArea( const contour* _rContours, const contourInfo* _ContoursInfo, const int _Contour_I )
{
	int i = 0, j = 0;//计数器i为全部点,j为凸包点
	int start_h = 0, start_w = 0;//用于保存起点坐标
	int contour_First_Point = 0;//用于保存指定轮廓点的计数位置
	int contour_This_Count = 0;//用于保存指定轮廓中点的总数(计数点数)
	int convex_Area = 0;//用于返回的凸多变形的面积
	int vector_1[2] = {0}, vector_2[2] = {0};//记录计算三角形面积的临时逆时针向量
	contour* convex_Points = NULL;


	convex_Points = ( contour*)malloc( 100 * sizeof( contour) );
	convex_Points[0] = _rContours[0];//先将头两个点压入凸包点栈
	convex_Points[1] = _rContours[1];
	j = 1;//栈顶元素位置
	contour_First_Point = _ContoursInfo[ _Contour_I].position;
	contour_This_Count = contour_First_Point + _ContoursInfo[ _Contour_I].count;
	for ( i = contour_First_Point+2; i < contour_This_Count; i ++ )
	{
		//在convex_Points栈中用栈顶三个元素组成向量
		vector_1[0] = convex_Points[j].width - convex_Points[j-1].width;
		vector_1[1] = convex_Points[j].height - convex_Points[j-1].height;
		vector_2[0] = _rContours[i].width - convex_Points[j].width;
		vector_2[1] = _rContours[i].height - convex_Points[j].height;
		if ( vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0] >= 0 )
		{
			convex_Points[j+1] = _rContours[i];//将下一个点压入栈顶
			j ++;
		}
		else
		{
			convex_Points[j] = _rContours[i];
			if ( j > 1 )
			{
				vector_1[0] = convex_Points[j-1].width - convex_Points[j-2].width;
				vector_1[1] = convex_Points[j-1].height - convex_Points[j-2].height;
				vector_2[0] = convex_Points[j].width - convex_Points[j-1].width;
				vector_2[1] = convex_Points[j].height - convex_Points[j-1].height;
				while ( vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0] < 0 )
				{
					j --;
					convex_Points[j] = _rContours[i];
					vector_1[0] = convex_Points[j-1].width - convex_Points[j-2].width;
					vector_1[1] = convex_Points[j-1].height - convex_Points[j-2].height;
					vector_2[0] = convex_Points[j].width - convex_Points[j-1].width;
					vector_2[1] = convex_Points[j].height - convex_Points[j-1].height;
				}
			}	
		}
	}
	
	memset( convex_Points+j, 0, 2*sizeof( contour) );

	start_w = convex_Points[0].width;//记录起点坐标用于计算面积
	start_h = convex_Points[0].height;
	for ( i = 1; i < j-1; i ++ )
	{
		vector_1[0] = convex_Points[i].width - start_w;
		vector_1[1] = convex_Points[i].height - start_h;
		vector_2[0] = convex_Points[i+1].width - convex_Points[i].width;
		vector_2[1] = convex_Points[i+1].height - convex_Points[i].height;
		convex_Area += (vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0]);
	}
	
	return convex_Area*0.5;
}

int contourMinCircle( const contour* _rContours, const contourInfo* _ContoursInfo, const int _Contour_I )
{
	int max_Distance = 0;//用于保存两点的最大距离
	int one_I = 0;//用于一次遍历计数
	int N_I = 0;//用于N次遍历计数
	int one_Width = 0, one_Height = 0;//用于一次遍历保存坐标
	int N_Width = 0, N_Height = 0;//用于N次遍历保存坐标
	int contour_Count = 0;//用于保存指定轮廓中点的总数(计数点数)

	
	one_I = _ContoursInfo[_Contour_I].position;//首点为起始点
	contour_Count = _ContoursInfo[_Contour_I].count + one_I - 1;
	for ( ; one_I < contour_Count; one_I ++ )
	{
		for ( N_I = one_I + 1; N_I <= contour_Count; N_I ++ )
		{
			one_Width = _rContours[one_I].width;
			one_Height = _rContours[one_I].height;
			N_Width = _rContours[N_I].width;
			N_Height = _rContours[N_I].height;
			if ( (one_Width-N_Width)*(one_Width-N_Width) +
				 (one_Height-N_Height)*(one_Height-N_Height) > max_Distance )
			{
				max_Distance = (one_Width-N_Width)*(one_Width-N_Width) +
							   (one_Height-N_Height)*(one_Height-N_Height);
			}
		}
	}
	return max_Distance*0.7854;
}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值