数字图像处理之OSTU二值化

来源:互联网 发布:赵云武力知乎 编辑:程序博客网 时间:2024/05/17 07:09
#include<stdlib.h>
bool tobinary(unsigned char *pImage, int width, int height, int biBitCount)
{
    int i, j, k;
    int h[256]={0};
    unsigned int ip1, ip2, is1, is2=0; //存储前景和背景的灰度总和及像素个数
    double w0, w1=0; //前景和背景像素的比例
    double mean1, mean2=0; //前景和背景的平均灰度
    double g[245]={0}; //存储类间方差
    double gmax=0; //最大类间方差
    unsigned char th=0; //二值化阈值
    //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
    int lineByte=(width * biBitCount/8+3)/4*4;




    for(i=0; i<height; i++) //灰度直方图
    for(j=0; j<width; j++)
        {
            k = *(pImage+i*lineByte+j);
            h[k]++;
        }


    for(i=10; i<245; i++) //阈值一般不会超出这个范围
    {
        ip1=0; ip2=0; is1=0; is2=0;
        w0=0; w1=0;
        for(j=0; j<i; j++)
        {
            ip1+=h[j]*j; is1+=h[j];
        }
        mean1=ip1/is1;
        w0=double(is1)/double(width*height);


        for (j=i; j<256; j++)
        {
            ip2+=h[j]*j; is2+=h[j];
        }
        mean2=ip2/is2;
        w1=1-w0;


        g[i]=w0*w1*(mean1-mean2)*(mean1-mean2);
    }
    gmax=g[10];
    th=10;
    for(i=11; i<245; i++)
        if(g[i]>gmax)
        {
            gmax=g[i]; th=i;
        }


    for(i=0; i<height; i++)
        for(j=0; j<width; j++)
            *(pImage+i*lineByte+j)=*(pImage+i*lineByte+j)>th?255:0;
    return 1;

}     

这个语句要注意 w0=double(is1)/double(width*height); 因为如果不加强制转换的话,右边一个小的整数除以一个大的整数结果为0。
程序中有这么一句 int lineByte=(width * biBitCount/8+3)/4*4; 这是因为Windows系统中一行像素所占的字节数为4的倍数,因此不是4的倍数时要补充为4的倍数,这样在寻址每一个像素的时候,像素的地址为 pImage+i*lineByte+j ;而循环控制语句for(j=0; j<width; j++)中仍用width,不用lineByte,因为补充的数据不是原图像数据,我们不需要处理。
该函数在Eclipse上调试通过。 

原创粉丝点击