• OTSU二值化方法


        OTSU二值化方法是一种全局阈值分割方法,它基于类间方差最大原理。

        C代码如下:

        

    #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上调试通过。

  • 相关阅读:
    找零钱「Usaco2006 Dec」
    才艺表演「Usaco2018 Open」
    潜入行动「JSOI2018」
    任务安排「SDOI2012」
    BZOJ2298: [HAOI2011]problem a
    JZOJ 5818
    JZOJ 3493
    JZOJ 3470
    JZOJ 5781
    JZOJ 5778
  • 原文地址:https://www.cnblogs.com/haigege/p/2195758.html
Copyright © 2020-2023  润新知