颜色匹配与腐蚀中心

时间:2020-12-07 04:54:05

一、腐蚀中心
腐蚀与膨胀,二值图像的腐蚀和膨胀图像数字处理中应用相当广泛,代码处理也很简单。为看懂本文的关键。
相应的代码及原理在此处省略,或另外开文。

二、颜色匹配中几个重要的函数算法

//搜索腐蚀中心

/*函数引入目标条件,和搜索的区域 从而返回了腐蚀中心x,y */
static int SearchCentre(unsigned int *x,unsigned int *y,const TARGET_CONDI *Condition,const SEARCH_AREA *Area)
{
    unsigned int SpaceX,SpaceY,i,j,k,FailCount=0;
    COLOR_RGB Rgb;
    COLOR_HSL Hsl;

    SpaceX = Condition->WIDTH_MIN/3;  //X间隔
    SpaceY = Condition->HIGHT_MIN/3;//Y间隔,将区域矩形化,方便表示腐蚀中心

    for(i=Area->Y_Start;i<Area->Y_End;i+=SpaceY)
    {
        for(j=Area->X_Start;j<Area->X_End;j+=SpaceX)
        {                                       //遍历区域搜索
            FailCount=0;
            for(k=0;k<SpaceX+SpaceY;k++)
            {
                if(k<SpaceX)       //每一分块进行横扫
                    ReadColor(j+k,i+SpaceY/2,&Rgb);
                else     //每一分块进行竖扫
                    ReadColor(j+SpaceX/2,i+(k-SpaceX),&Rgb);
                RGBtoHSL(&Rgb,&Hsl);//将读取的颜色格式转换

                if(!ColorMatch(&Hsl,Condition))//颜色范围匹配
                    FailCount++;
                if(FailCount>((SpaceX+SpaceY)>>ALLOW_FAIL_PER))
                    break;
            }
            if(k==SpaceX+SpaceY)
            {
                *x = j+SpaceX/2;
                *y = i+SpaceY/2;//腐蚀中心的确认,假设矩形,
                               //则得腐蚀中心的表达式
                return 1;
            }
        }
    }
    return 0;
}

//从腐蚀中心向外腐蚀,得到新的腐蚀中心

static int Corrode(unsigned int oldx,unsigned int oldy,const TARGET_CONDI *Condition,RESULT *Resu)
{
    unsigned int Xmin,Xmax,Ymin,Ymax,i,FailCount=0;
    COLOR_RGB Rgb;
    COLOR_HSL Hsl;

    for(i=oldx;i>IMG_X;i--)
    {
        ReadColor(i,oldy,&Rgb);
        RGBtoHSL(&Rgb,&Hsl);
        if(!ColorMatch(&Hsl,Condition))
            FailCount++;
        if(FailCount>(((Condition->WIDTH_MIN+Condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
            break;  
    }
    Xmin=i;
    FailCount=0;

    for(i=oldx;i<IMG_X+IMG_W;i++)
    {
        ReadColor(i,oldy,&Rgb);
        RGBtoHSL(&Rgb,&Hsl);
        if(!ColorMatch(&Hsl,Condition))
            FailCount++;
        if(FailCount>(((Condition->WIDTH_MIN+Condition->WIDTH_MAX)>>2)>>ALLOW_FAIL_PER))
            break;  
    }
    Xmax=i;
    FailCount=0;

    for(i=oldy;i>IMG_Y;i--)
    {
        ReadColor(oldx,i,&Rgb);
        RGBtoHSL(&Rgb,&Hsl);
        if(!ColorMatch(&Hsl,Condition))
            FailCount++;
        if(FailCount>(((Condition->HIGHT_MIN+Condition->HIGHT_MAX)>>2)>>ALLOW_FAIL_PER))
            break;  
    }
    Ymin=i;
    FailCount=0;

    for(i=oldy;i<IMG_Y+IMG_H;i++)
    {
        ReadColor(oldx,i,&Rgb);
        RGBtoHSL(&Rgb,&Hsl);
        if(!ColorMatch(&Hsl,Condition))
            FailCount++;
        if(FailCount>(((Condition->HIGHT_MIN+Condition->HIGHT_MAX)>>2)>>ALLOW_FAIL_PER))
            break;  
    }
    Ymax=i;
    FailCount=0;

    Resu->x = (Xmin+Xmax)/2;
    Resu->y = (Ymin+Ymax)/2;
    Resu->w = Xmax-Xmin;
    Resu->h = Ymax-Ymin;

    if(((Xmax-Xmin)>(Condition->WIDTH_MIN)) && ((Ymax-Ymin)>(Condition->HIGHT_MIN)) &&\
       ((Xmax-Xmin)<(Condition->WIDTH_MAX)) && ((Ymax-Ymin)<(Condition->HIGHT_MAX)) )
        return 1;   
    else
        return 0;   
}

//将识别条件写入Condition指向的结构体中,该函数将返回目标的x,y坐标和长宽
//返回1识别成功,返回1识别失败

int Trace(const TARGET_CONDI *Condition,RESULT *Resu)
{
    unsigned int i;
    static unsigned int x0,y0,flag=0;
    static SEARCH_AREA Area={IMG_X,IMG_X+IMG_W,IMG_Y,IMG_Y+IMG_H};
    RESULT Result; 


    if(flag==0)
    {
        if(SearchCentre(&x0,&y0,Condition,&Area))
            flag=1;
        else
        {
            Area.X_Start= IMG_X ;
            Area.X_End  = IMG_X+IMG_W  ;
            Area.Y_Start= IMG_Y     ;
            Area.Y_End  = IMG_Y+IMG_H;

            if(SearchCentre(&x0,&y0,Condition,&Area))   
            {
                flag=0;
                return 0;
            }   
        }
    }
    Result.x = x0;
    Result.y = y0;

    for(i=0;i<ITERATE_NUM;i++)
        Corrode(Result.x,Result.y,Condition,&Result);

    if(Corrode(Result.x,Result.y,Condition,&Result))
    {
        x0=Result.x;
        y0=Result.y;
        Resu->x=Result.x;
        Resu->y=Result.y;
        Resu->w=Result.w;
        Resu->h=Result.h;
        flag=1;

        Area.X_Start= Result.x - ((Result.w)>>1);
        Area.X_End  = Result.x + ((Result.w)>>1);
        Area.Y_Start= Result.y - ((Result.h)>>1);
        Area.Y_End  = Result.y + ((Result.h)>>1);


        return 1;
    }

下面为最主要的主函数代码片段

#define ALLOW_FAIL_PER 3 //容错率,,容错率越大越容易识别,但错误率越大
#define ITERATE_NUM 8 //迭代次数,迭代次数越多识别越精确,但计算量越大
typedef struct{
    unsigned int x;//目标的x坐标
    unsigned int y;//目标的y坐标
    unsigned int w;//目标的宽度
    unsigned int h;//目标的高度
}RESULT;//识别结果

typedef struct{
    unsigned char  H_MIN;//目标最小色调
    unsigned char  H_MAX;//目标最大色调

    unsigned char  S_MIN;//目标最小饱和度 

    unsigned char  L_MIN;//目标最小亮度 
    unsigned char  L_MAX;//目标最大亮度

    unsigned int  WIDTH_MIN;//目标最小宽度
    unsigned int  HIGHT_MIN;//目标最小高度

    unsigned int  WIDTH_MAX;//目标最大宽度
    unsigned int  HIGHT_MAX;//目标最大高度


int main(){
    unsigned short c_data;
    RESULT Resu; //识别结果
    TARGET_CONDI Condition={50,80,20,250,20,200,40,40,320,240};//识别颜色条件

if(Trace(&Condition,&Resu)){   //Trace函数返回1,0及结果坐标
GUI_Fill(Resu.x-Resu.w/2,Resu.y-Resu.h/2,Resu.w,1,0xf800);
GUI_Fill(Resu.x-Resu.w/2,Resu.y-Resu.h/2,1,Resu.h,0xf800);
GUI_Fill(Resu.x-Resu.w/2,Resu.y+Resu.h/2,Resu.w,1,0xf800);
GUI_Fill(Resu.x+Resu.w/2,Resu.y-Resu.h/2,1,Resu.h,0xf800);
GUI_Fill(Resu.x-2,Resu.y-2,4,4,0xf800);
}

}   

以上便可实现颜色的匹配,关于腐蚀和膨胀,可搜索相关的图示加深理解。