原创 大津法取阈值

2009-2-23 22:26 3525 8 8 分类: 软件与OS

    大津法又称最大类间方差法。对图像,记t为前景与背景的分割阈值,前景点数占图像比例为w0, 平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,当t使得值g=w0*(u0-u)2+w1*(u1-u)2 最大时t即为分割的最佳阈值。阈值t分割出的前景和背景两部分构成了整幅图像,而前景取值u0,概率为w0,背景取值u1,概率为w1,总均值为u,根据方差的定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差别越大,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类间方差最大的分割意味着错分概率最小。直接应用大津法计算量较大,因此我们在实现时采用了等价的公式g=w0*w1*(u0-u1)2


// 获取直方图
// 1. pImageData   图像数据
// 2. nWidth       图像宽度
// 3. nHeight      图像高度
// 4. nWidthStep   图像行大小
// 5. pHistogram   直方图
BOOL GetHistogram(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep,
    int *pHistogram)
{
    int            i     = 0;
    int            j     = 0;
    unsigned char *pLine = NULL;
    // 清空直方图
    memset(pHistogram, 0, sizeof(int) * 256);
    for (pLine = pImageData, j = 0; j < nHeight; j++, pLine += nWidthStep)
    {
        for (i = 0; i < nWidth; i++)
        {
            pHistogram[pLine]++;
        }
    }
    return TRUE;
}


// 大津法取阈值
// 1. pImageData   图像数据
// 2. nWidth       图像宽度
// 3. nHeight      图像高度
// 4. nWidthStep   图像行大小
// 函数返回阈值
int Otsu(unsigned char *pImageData, int nWidth, int nHeight, int nWidthStep)
{
    int    i          = 0;
    int    j          = 0;
    int    nTotal     = 0;
    int    nSum       = 0;
    int    A          = 0;
    int    B          = 0;
    double u          = 0;
    double v          = 0;
    double dVariance  = 0;
    double dMaximum   = 0;
    int    nThreshold = 0;
    int    nHistogram[256];
    // 获取直方图
    GetHistogram(pImageData, nWidth, nHeight, nWidthStep, nHistogram);
    for (i = 0; i < 256; i++)
    {
        nTotal += nHistogram;
        nSum   += (nHistogram * i);
    }
    for (j = 0; j < 256; j++)
    {
        A = 0;
        B = 0;
        for (i = 0; i < j; i++)
        {
            A += nHistogram;
            B += (nHistogram * i);
        }
        if (A > 0)
        {
            u = B / A;
        }
        else
        {
            u = 0;
        }
        if (nTotal - A > 0) 
        {
            v = (nSum - B) / (nTotal - A);
        }
        else
        {
            v = 0;
        }
        dVariance = A * (nTotal - A) * (u - v) * (u - v);
        if (dVariance > dMaximum)
        {
            dMaximum = dVariance;
            nThreshold = j;
        }
    }
    return nThreshold;
}


大津法效果:



03f1f137-05e5-439c-8c73-8c6a76d498cb.jpg2d32a954-f0f9-4163-a327-c32da2aa390d.jpg

文章评论0条评论)

登录后参与讨论
我要评论
0
8
关闭 站长推荐上一条 /2 下一条