首页 > 技术文章 > 基于c++的ostu算法的实现

Daringoo 2015-04-07 19:37 原文

图像二值化算法是图像处理的基础。一般来说,二值化算法可以分为两个类别:全局二值化和局部二值化。全局二值化是指通过某种算法找到一个全局的阈值T,对图像中坐标为(x,y)的像素值做如下处理:

Ostu就是这样一种全局二值化算法,又叫最大类间方差。因为该算法会遍历图像中任意一个像素值i,计算当其为阈值时,图像的前景和背景图像(并不一定是真正的前景和背景,只是我们把当前小于i的记做背景,大于i的记做前景)的方差值。当方差值达到最大时,我们认为此时的i是该图像的全局阈值。

符号说明:

前景点数占图像比例:w0;平均灰度:u0

背景点数占图像比例:w1,平局灰度:u1

图像平均灰度:

前景和背景图像方差:

C++代码:

int ostu(Mat image)
{
    cvtColor(image.clone(),image,CV_RGB2GRAY);
    int width = image.cols;
    int height = image.rows;
    int x=0,y=0;
    float ip1,ip2,is1,is2,w0,w1,mean1,mean2,mean,deltaTmp,deltaMax;
    int pixelCount[256];
    int i, j, pixelSum = width * height, thres = 0;
    for(i = 0; i < 256; i++)
    {
        pixelCount[i] = 0;
    }
    int pixel=0;
    for(i = 0; i < height; i++)
    {
        for(j = 0;j <width;j++)
        {
            pixel=image.at<uchar>(i,j);
            pixelCount[pixel]++;
    
        }
    }
//经典ostu算法,得到前景和背景的分割
//遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值
    deltaMax=0;
    for(i = 0; i < 256; i++)
    {
        ip1=ip2=is1=is2=w0=w1=mean1=mean2=mean=deltaTmp=0;
        for(j = 0; j < 256; j++)
        {
            if(j <= i) //背景部分
            {
                ip1+=pixelCount[j]*j;
                is1+=pixelCount[j];
            }
        
            else     
            {
                 ip2+=pixelCount[j]*j;
                is2+=pixelCount[j];
            }
            
        }

        mean1=ip1/is1;     //第一类像素平均灰度值
        w0=(float)is1/(float)pixelSum;//第一类像素占整个图像比例
        mean2=ip2/is2;
        w1=1-w0;
        mean=w0*mean1+w1*mean2;
        deltaTmp=w0*w1*(mean1-mean2)*(mean1-mean2);//灰度值为i的阈值的类间方差
        if (deltaTmp>deltaMax)
        {
            deltaMax=deltaTmp;
            thres=i;
        }
    }    
    return thres;
}

 

 

    

推荐阅读