Otsu(大津法)源码级讲解

来源:互联网 发布:美元指数行情软件 编辑:程序博客网 时间:2024/04/29 08:24

用铅笔划直线的,表示是定义;划圆的表示公式中要的代码。
本博客才看见冈萨雷斯的数字图像处理的Otsu讲解更好
这里写图片描述

下面这种图片列出了写代码所必须要的公式清单
这里写图片描述

另附上代码注释,代码中的公式命名没有参考标准的coding style。仅仅为了理解

int Otsu(IplImage* src){    int M = src->height;    // 图片的高    int N = src->width;     // 图片的宽    /*    * 直方图分别存储每个灰度级所对应的像素的个数.    * 例如:    * histogram[25] = 56 表示的是灰度值为25的像素个数有56个。    * 下面代码的两个循环给histogram赋值    */    float histogram[256] = {0};    for (int m=0; m<src->height; ++m)    {        unsigned char* p = (unsigned char*)src->imageData+src->widStep*m;        for (int n=0; n<src->width; ++n)        {            histogram[int(*p++)]++;        }    }    int threshold;    long cnt_0_k = 0;  // cnt_0_k:灰度值[0,k]的像素个数    long cnt_k1_L = 0;  // cnt_k1_L:灰度值[k+1, L]的像素个数    long sum_0_k = 0;  // sum_0_k:i在[0,k]的范围i*n_i求和    long sum_k1_L = 0;  // sum_k1_L:i在[k+1,L]的范围i*n_i求和    double m1 = 0; // m1 = sum_0_k / cnt_0_k;    double m2 = 0;  //     double P1 = 0;  // P1: P1 = (double)cnt_0_k / MN;     double P2 = 0; //  P2: = 1-P1    double sigma = 0; // sigma = P1 * P2 *  (m1 - m2) * (m1 - m2);    double maxsigma = 0;    /*    * 求每个灰度值所对应的sigma值,并求sigma最大的对应的灰度    * 虽然公式是从0开始的,但实际上是从1开始,因为从0开始表示是分一类。    * 即阈值范围是[1,255]。    */    for (int i = 1; i < 256; i++)       {        sum_0_k = 0;  // sum_0_k:i在[0,k]的范围i*n_i求和        sum_k1_L = 0;  // sum_k1_L:i在[k+1,L]的范围i*n_i求和        cnt_0_k = 0;  // cnt_0_k:灰度值[0,k]的像素个数        cnt_k1_L = 0;  // cnt_k1_L:灰度值[k+1, L]的像素个数        P1 = 0;        P2 = 0;/***************************begin: 在[0,k]内操作*****************************************/        for (int j = 0; j < i; j++) // j相当与公式中的k        {            cnt_0_k += histogram[j];  // cnt_0_k:灰度值[0,k]的像素个数            sum_0_k += j * histogram[j];  // sum_0_k:i在[0,k]的范围i*n_i求和        }        m1 = (double)sum_0_k / cnt_0_k;        P1 = (double)cnt_0_k / MN;/***************************end: 在[0,k]内操作*****************************************//*************************begin: 在[k+1,L]内操作*****************************************/        for (j = i; j <= 255; j++)        {            cnt_k1_L += histogram[j];     // cnt_k1_L:灰度值[k+1, L]的像素个数            sum_k1_L += j * histogram[j];  // sum_k1_L:i在[k+1,L]的范围i*n_i求和        }        m2 = (double)sum_k1_L / cnt_k1_L;        P2 = 1 - P1; // (double)cnt_k1_L / MN;  /*************************begin: 在[k+1,L]内操作*****************************************/        sigma = P1 * P2 *  (m1 - m2) * (m1 - m2);   // sigma        if (sigma > maxsigma)        {            maxsigma = sigma;            threshold = i;        }    }    return threshold;}

另代码参考其他的博主,不一一列出了。同时也可以参考opencv中的Otsu源码,在threshold.cpp中

0 0
原创粉丝点击