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

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

计算轮廓点的最小凸包像素面积和求解最小外接圆的方法有很多,本文各举出一种比较简单且快速的方法,读者可根据实际情况定义返回值精度,本文采用的是整型精度,代码如下:
  1. typedef struct Contours  
  2. {//轮廓点结构体,通过malloc来分配  
  3.     int height;//bmp Y坐标  
  4.     int width;//bmp X坐标  
  5.     int stateFlag;//点类型标志位  
  6. } contour;  
  7.   
  8. typedef struct ContourInfo  
  9. {//轮廓信息结构体,通过malloc来分配  
  10.     int position;//记录单个轮廓在轮廓点序列中的起始位置  
  11.     int count;//记录单个轮廓的点个数  
  12. } contourInfo;  
typedef struct Contours
{//轮廓点结构体,通过malloc来分配
    int height;//bmp Y坐标
    int width;//bmp X坐标
    int stateFlag;//点类型标志位
} contour;

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

  1. int contourConvexArea( const contour* _rContours, const contourInfo* _ContoursInfo, const int _Contour_I )  
  2. {  
  3.     int i = 0, j = 0;//计数器i为全部点,j为凸包点  
  4.     int start_h = 0, start_w = 0;//用于保存起点坐标  
  5.     int contour_First_Point = 0;//用于保存指定轮廓点的计数位置  
  6.     int contour_This_Count = 0;//用于保存指定轮廓中点的总数(计数点数)  
  7.     int convex_Area = 0;//用于返回的凸多变形的面积  
  8.     int vector_1[2] = {0}, vector_2[2] = {0};//记录计算三角形面积的临时逆时针向量  
  9.     contour* convex_Points = NULL;  
  10.   
  11.   
  12.     convex_Points = ( contour*)malloc( 100 * sizeof( contour) );  
  13.     convex_Points[0] = _rContours[0];//先将头两个点压入凸包点栈  
  14.     convex_Points[1] = _rContours[1];  
  15.     j = 1;//栈顶元素位置  
  16.     contour_First_Point = _ContoursInfo[ _Contour_I].position;  
  17.     contour_This_Count = contour_First_Point + _ContoursInfo[ _Contour_I].count;  
  18.     for ( i = contour_First_Point+2; i < contour_This_Count; i ++ )  
  19.     {  
  20.         //在convex_Points栈中用栈顶三个元素组成向量  
  21.         vector_1[0] = convex_Points[j].width - convex_Points[j-1].width;  
  22.         vector_1[1] = convex_Points[j].height - convex_Points[j-1].height;  
  23.         vector_2[0] = _rContours[i].width - convex_Points[j].width;  
  24.         vector_2[1] = _rContours[i].height - convex_Points[j].height;  
  25.         if ( vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0] >= 0 )  
  26.         {  
  27.             convex_Points[j+1] = _rContours[i];//将下一个点压入栈顶  
  28.             j ++;  
  29.         }  
  30.         else  
  31.         {  
  32.             convex_Points[j] = _rContours[i];  
  33.             if ( j > 1 )  
  34.             {  
  35.                 vector_1[0] = convex_Points[j-1].width - convex_Points[j-2].width;  
  36.                 vector_1[1] = convex_Points[j-1].height - convex_Points[j-2].height;  
  37.                 vector_2[0] = convex_Points[j].width - convex_Points[j-1].width;  
  38.                 vector_2[1] = convex_Points[j].height - convex_Points[j-1].height;  
  39.                 while ( vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0] < 0 )  
  40.                 {  
  41.                     j –;  
  42.                     convex_Points[j] = _rContours[i];  
  43.                     vector_1[0] = convex_Points[j-1].width - convex_Points[j-2].width;  
  44.                     vector_1[1] = convex_Points[j-1].height - convex_Points[j-2].height;  
  45.                     vector_2[0] = convex_Points[j].width - convex_Points[j-1].width;  
  46.                     vector_2[1] = convex_Points[j].height - convex_Points[j-1].height;  
  47.                 }  
  48.             }     
  49.         }  
  50.     }  
  51.       
  52.     memset( convex_Points+j, 0, 2*sizeof( contour) );  
  53.   
  54.     start_w = convex_Points[0].width;//记录起点坐标用于计算面积  
  55.     start_h = convex_Points[0].height;  
  56.     for ( i = 1; i < j-1; i ++ )  
  57.     {  
  58.         vector_1[0] = convex_Points[i].width - start_w;  
  59.         vector_1[1] = convex_Points[i].height - start_h;  
  60.         vector_2[0] = convex_Points[i+1].width - convex_Points[i].width;  
  61.         vector_2[1] = convex_Points[i+1].height - convex_Points[i].height;  
  62.         convex_Area += (vector_1[0]*vector_2[1] - vector_1[1]*vector_2[0]);  
  63.     }  
  64.       
  65.     return convex_Area*0.5;  
  66. }  
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;
}

  1. int contourMinCircle( const contour* _rContours, const contourInfo* _ContoursInfo, const int _Contour_I )  
  2. {  
  3.     int max_Distance = 0;//用于保存两点的最大距离  
  4.     int one_I = 0;//用于一次遍历计数  
  5.     int N_I = 0;//用于N次遍历计数  
  6.     int one_Width = 0, one_Height = 0;//用于一次遍历保存坐标  
  7.     int N_Width = 0, N_Height = 0;//用于N次遍历保存坐标  
  8.     int contour_Count = 0;//用于保存指定轮廓中点的总数(计数点数)  
  9.   
  10.       
  11.     one_I = _ContoursInfo[_Contour_I].position;//首点为起始点  
  12.     contour_Count = _ContoursInfo[_Contour_I].count + one_I - 1;  
  13.     for ( ; one_I < contour_Count; one_I ++ )  
  14.     {  
  15.         for ( N_I = one_I + 1; N_I <= contour_Count; N_I ++ )  
  16.         {  
  17.             one_Width = _rContours[one_I].width;  
  18.             one_Height = _rContours[one_I].height;  
  19.             N_Width = _rContours[N_I].width;  
  20.             N_Height = _rContours[N_I].height;  
  21.             if ( (one_Width-N_Width)*(one_Width-N_Width) +  
  22.                  (one_Height-N_Height)*(one_Height-N_Height) > max_Distance )  
  23.             {  
  24.                 max_Distance = (one_Width-N_Width)*(one_Width-N_Width) +  
  25.                                (one_Height-N_Height)*(one_Height-N_Height);  
  26.             }  
  27.         }  
  28.     }  
  29.     return max_Distance*0.7854;  
  30. }  
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;
}


猜你喜欢

转载自blog.csdn.net/qq_28713863/article/details/78443294