原创 (原创)图像处理学习5:阈值化

2009-3-14 14:31 4686 6 6 分类: 软件与OS

阈值化在图像分割和形态学操作,图像增强方面都有很多的用处,操作简单,速度快。
最一般的就是设个值大于某个值的时候把这个像素变为255,小于这个值就是0,但是在实际操作的时候这种方法有个问题就是:太主观了,你怎么知道那个阈值好,那个阈值坏,图片的信息丢掉丢失了多少。所以后来在使用阈值进行图像的分割的时候就提出大律法阈值化大津法又称最大类间方差法。对图像,记t为前景与背景的分割阈值,前景点数占图像比例为w0,
平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,当t使
得值g=w0*(u0-u)2+w1*(u1-u)2
最大时t即为分割的最佳阈值。阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为w0,背景取值u1,概率为w1,总均值为u,根据
方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大,当部分目标错分为背景或部分背景错分为目标都会导致
两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0-
u1)2

不管怎么说,图片的信息变幻多端,到底该怎么处理,具体的时候有具体的方法。现在越来越觉得对于图片信息的分析能力,是很重要的,知道如何去分析,才知道如何让去使用程序来达到最好的效果。

阈值化的代码:
/*************************************************************
阈值化处理函数
图片信息
图片数据
最大值
阈值处理的类型
IMG_THRESHOLD_BINARY      0 二值化,大于阈值设定为max_value,否则为0
IMG_THRESHOLD_BINARY_INV  1 二值化,小于阈值设定为max_value,否则为0
IMG_THRESHOLD_TOZERO      2 二值化,大于阈值设定为0,否则为原来的数据
IMG_THRESHOLD_TOZERO_INV  3 二值化,小于阈值设定为max_value,否则为原数据
IMG_THRESHOLD_TRUNCATE    4 二值化,大于阈值设定为threhold,否则为0
****************************************************************/
BOOL ImgThreshold(BITMAPINFO* pbmpinfo,BYTE* pbmpdata,UINT threhold,UINT max_value , int threshold_type)
{
    LONG  imagewidth=pbmpinfo->bmiHeader.biWidth;                  
    LONG  imageheigth=pbmpinfo->bmiHeader.biHeight;
    LONG  Linebyte =( pbmpinfo->bmiHeader.biBitCount * imagewidth + 31)/32*4;
    LONG  ImageSize=Linebyte * imageheigth;
   
        LONG i=0,j=0,k=0,heigth=0,width=0;
   
    //data is not null
    if (pbmpdata == NULL)
    {
        return FALSE;
    }
    //color must be gray
    if (pbmpinfo->bmiHeader.biBitCount != 8)
    {
        AfxMessageBox("只对灰度图像进行操作!");
        return FALSE;
    }
   
    //分配空间
    BYTE *pNewbmpdata=(BYTE*)malloc(ImageSize);
   
    //copy data
    if (pNewbmpdata == NULL)
    {
        return FALSE;
    }

    memcpy(pNewbmpdata,pbmpdata,ImageSize);
   
    BYTE *psrc=NULL;
    BYTE *pdest=NULL;
   
    BYTE  result=0;
    //计算区域是:begin~image-begin-1    1~image-2
    for (heigth = 0 ; heigth < imageheigth ;heigth++  )
    {
       
        for ( width = 0 ; width < imagewidth ; width++)
        {
            psrc  = pbmpdata+(ImageSize-Linebyte-heigth*Linebyte)+width;
           
            pdest = pNewbmpdata+(ImageSize-Linebyte-
                heigth*Linebyte)+width;

            switch (threshold_type)
            {
                //小于阈值设定为max_value,否则为0
            case  IMG_THRESHOLD_BINARY_INV:
                if (*psrc >= threhold)
                {
                    result = 0;
                }
                else
                {
                    result = max_value;
                }
                break;
                //大于阈值设定为原数据,否则为0
            case IMG_THRESHOLD_TRUNCATE :
                if (*psrc >= threhold)
                {
                    result = threhold;
                }
                else
                {
                    result = 0;
                }
                break;
                //大于阈值设定为0,否则为原来的数据
            case IMG_THRESHOLD_TOZERO :
                if (*psrc >= threhold)
                {
                    result =0;
                }
                else
                {
                    result =*psrc;
                }
                break;
                //小于阈值设定为0,否则为原来的数据
            case IMG_THRESHOLD_TOZERO_INV :
                if (*psrc >= threhold)
                {
                    result =*psrc;
                }
                else
                {
                    result = 0;
                }
                break;
                //大于阈值设定为max_value,否则为0
               default :
                if (*psrc >= threhold)
                {
                    result = max_value;
                }
                else
                {
                    result =0 ;
                }
                break;

            }
            *pdest=(unsigned char)result;
           
        }
    }
   
    memcpy(pbmpdata,pNewbmpdata,ImageSize);
    free(pNewbmpdata);
    return TRUE;
}

打律法阈值化的代码:
/*************************************************************
大律法发取阈值
图片信息
图片数据
直方图统计数据
是否是直方图统计数据

返回得到的阈值,如果失败返回-1
/////
原理:设定一个阈值,将图像分为2个部分,分别求出2个部分的灰度均值,
利用函数 W(I)= N(<)*N(>)*(V(<) - V(>))^2 中的最大值来决定阈值
************************l****************************************/
int ImgOtsu(BITMAPINFO* pbmpinfo,BYTE* pbmpdata)
{
    long total_pixel =0;
    long total_num =0;

    long num_below = 0;    
    long pixel_below =0;

    float percentage_below  = 0;
    float percentage_up     = 0;
       
    float avarage_below =0;
    float avarage_up =0;

    int i,j;
    int threhold=0,threhold1=0,threhold2=0;

    //直方图统计
    long hist[256]={0};
    //color must be gray
    if (pbmpinfo->bmiHeader.biBitCount != 8)
    {
        AfxMessageBox("只对灰度图像进行操作!");
        return -1;
    }
    ImgHist(pbmpinfo,pbmpdata,hist,NULL);
    //统计总数
    for (j=0;j < 256;j++)
    {
        total_num += hist[j];
        total_pixel += hist[j]*j;
    }
     ///////////////////
    for (i=0 ;    i<256;    i++ )
    {  
       num_below =0;
       pixel_below =0;

       percentage_below=0;
       percentage_up =0;
       avarage_up  =0;
       avarage_below =0;
      /////////////////////
       for (j=0;j < i+1; j++)
       {
               num_below += hist[j];
               pixel_below += hist[j]*j;
       }
      ///////////////
       if (pixel_below)
       {
           percentage_below=(float)num_below /(float)total_num ;
           avarage_below   =(float)pixel_below /(float)num_below;

       }
       else
       {
           pixel_below =0;
       }
     
       if (total_pixel - pixel_below)
       {
               percentage_up=(float)( 1 - (float)num_below /(float)total_num ); //小于阈值的像素占总数的概率
               avarage_up   =(float)(total_pixel - pixel_below )/(float)(total_num - num_below); //小于阈值的部分的均值
       }
       else
       {
                avarage_up = 0;
       }
       /////////////
       threhold1 =(int)( percentage_up * percentage_below * (avarage_up - avarage_below) *(avarage_up - avarage_below) );
       if (threhold1 > threhold2)
       {
               threhold2 = threhold1;
               threhold = i;
       }       
                           
    }

   return threhold;
}


文章评论0条评论)

登录后参与讨论
我要评论
0
6
关闭 站长推荐上一条 /2 下一条