计算轮廓点的最小凸包像素面积,最小外接圆的快速方法
计算轮廓点的最小凸包像素面积和求解最小外接圆的方法有很多,本文各举出一种比较简单且快速的方法,读者可根据实际情况定义返回值精度,本文采用的是整型精度,代码如下:
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;
}