经典的阈值分割


(1)otsu :最大类间方差

记t为前景与背景的分割阈值,前景点数占图像比例为w0, 平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。
则图像的总平均灰度为:u=w0*u0+w1*u1。
前景和背景图象的方差:g=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u)。

 当方差g最大时,可以认为此时前景和背景差异最大,此时的灰度t是最佳阈值。

int otsu(IplImage *image)  
{  
   
cvNamedWindow("kanxia",1);
cvShowImage("kanxia",image);
    assert(NULL != image);  

    int width = image->width;  
    int height = image->height;  
    int x=0,y=0;  
    int pixelCount[256]={0};  
    float pixelPro[256]={0};  
    int i, j, pixelSum = width * height, threshold = 0;  
    uchar* data = (uchar*)image->imageData;  

   
    //统计灰度级中每个像素在整幅图像中的个数  
    for(i = y; i < height; i++)  
    {  
        for(j = x;j <width;j++)  
        {  
            pixelCount[data[i * image->widthStep + j]]++;  
        }  
    }  


    //计算每个像素在整幅图像中的比例  
    for(i = 0; i < 256; i++)  
    {  
        pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);  
    }  



    //经典ostu算法,得到前景和背景的分割  
    //遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值  
    float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;  
    for(i = 0; i < 256; i++)  
    {  
        w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;  

        for(j = 0; j < 256; j++)  
        {  
            if(j <= i) //背景部分  
            {  
                //以i为阈值分类,第一类总的概率  
                w0 += pixelPro[j];        
                u0tmp += j * pixelPro[j];  
            }  
            else       //前景部分  
            {  
                //以i为阈值分类,第二类总的概率  
                w1 += pixelPro[j];        
                u1tmp += j * pixelPro[j];  
            }  
        }  

        u0 = u0tmp / w0;        //第一类的平均灰度  
        u1 = u1tmp / w1;        //第二类的平均灰度  
        u = u0tmp + u1tmp;      //整幅图像的平均灰度  
        
//计算类间方差  


        deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);  


        //找出最大类间方差以及对应的阈值  
        if(deltaTmp > deltaMax)  
        {     
            deltaMax = deltaTmp;  
            threshold = i;  
        }  
    }  
cout<<"阈值为:"<<threshold<<endl;
    //返回最佳阈值;  
    return threshold; 

}


(2)迭代阈值分割

         迭代阈值分割就是通过迭代方法计算阈值,求取阈值的具体步骤为:假定一个初始阈值T1,T1一般取图像中灰度值的最大值和最小值的中间值;
        使用T1分割图像,得到两个数组H1和H2,H1是由灰度值大于等于T1的所有像素点组成,H2由灰度值小于T1的所有像素组成;
         计算H1和H_2两个数组的平均值μ1和μ2;计算新阈值
T2=(μ1+ μ2)/2         (2-5)

如果|T2-T1 |≤T0(T_0为一个很小的数),即两次阈值的值很接近时,迭代终止,否则T1=T2,重复上述步骤。最后的T2就是所求的阈值。

        int height = img->height;  
int width  = img->width;  
int step      = img->widthStep;  
int channels  = img->nChannels;  
uchar* data  = (uchar*)img->imageData;  
double tempg = -1;//临时类间方差  
double Histogram[256]={0};// = new double[256];//灰度直方图  
for(int i=0;i<height;i++)  
{//计算直方图  
for(int j=0;j<width;j++)  
{  
double temp =data[i*step + j * 3] * 0.114 + data[i*step + j * 3+1] * 0.587 + data[i*step + j * 3+2] * 0.299;  
temp = temp<0? 0:temp;  
temp = temp>255? 255:temp;  
Histogram[(int)temp]++;  
}   
}  
//迭代阈值分割
double k1,k2;
double t=0,u=0,u1,u2;
for (i=0;i<255;i++) 
{
t+=Histogram[i]; 
u+=i*Histogram[i];
}
k2= (u/t);
//迭代,知道k1=K2;
 do 
 {
k1=k2;
     t=u=0.0;
for (i=0;i<k2;i++)//K2将图像分成2部分,低灰度区域的灰度平均值

         {
                t+=Histogram[i]; 
u+=i*Histogram[i];
}
  u1=u/t;
  t=u=0.0;
for(i=(int)k2;i<255;i++)//高灰度区域的灰度平均值
{
t+=Histogram[i]; 
        u+=i*Histogram[i];

}
u2=u/t;
k2=(u1+u2)/2;//取平均

 } while (fabs(k1-k2)<0.000000001);//知道二次的平均一致,不在改变!

cvThreshold(m_pImage, m_pImage, k2+10, 255, CV_THRESH_BINARY_INV);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值