多级(4)Otsu阈值 [英] multi-level (4) Otsu thresholding

查看:512
本文介绍了多级(4)Otsu阈值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图实现多层次的Otsu的阈值,更具体地说,我需要3个阈值/ 4类。



我知道2个similair问题关于它:#34856019和#22706742。
问题是我没有得到好的结果:我已经阅读了几个文章与示例图像和阈值发现的代码不同于这些文件中的。



假设我有一张在黑色背景上有3个圆圈的图片,圆圈的亮度从非常明亮到黑暗不等:






阈值: 179,92,25


I'm trying to implement multi-level Otsu's thresholding, more specifically I need 3 thresholds/4 classes.

I'm aware of 2 similair questions on SO about it: #34856019 and #22706742. The problem is that I don't get good results: I've read several articles with sample images and thresholds found by that code differ from the ones in these papers.

Let's say I have a picture with 3 circles on the black background, the brightness of the circles differ from very bright to dark:

Sample Image

Am I right to suppose to get as a result 4 classes: black background and 3 more classes according to circles' intensity?

My program gives me these threshold values: 226, 178, 68

As a result, the third circle is completely invisible - it's in the same class as the background.

Can someone please check these values and/or the source code? Maybe it is possible to check this image using Matlab or somehow else... By the way, what's the best way to handle divisions by zero, which happen often with zero values in histogram? The source code:

void MultilevelThresholding(cv::Mat& src)
{
    int histogram[256] = { 0 };
    int pixelsCount = src.cols * src.rows;

    for (int y = 0; y < src.rows; y++)
    {
        for (int x = 0; x < src.cols; x++)
        {
            uchar value = src.at<uchar>(y, x);
            histogram[value]++;
        }
    }

    double c = 0;
    double Mt = 0;

    double p[256] = { 0 };
    for (int i = 0; i < 256; i++)
    {
        p[i] = (double) histogram[i] / (double) pixelsCount;
        Mt += i * p[i];
    }

    int optimalTreshold1 = 0;
    int optimalTreshold2 = 0;
    int optimalTreshold3 = 0;

    double maxBetweenVar = 0;

    double w0 = 0;
    double m0 = 0;
    double c0 = 0;
    double p0 = 0;

    double w1 = 0;
    double m1 = 0;
    double c1 = 0;
    double p1 = 0;

    double w2 = 0;
    double m2 = 0;
    double c2 = 0;
    double p2 = 0;
    for (int tr1 = 0; tr1 < 256; tr1++)
    {
        p0 += p[tr1];
        w0 += (tr1 * p[tr1]);
        if (p0 != 0)
        {
            m0 = w0 / p0;
        }

        c0 = p0 * (m0 - Mt) * (m0 - Mt);

        c1 = 0;
        w1 = 0;
        m1 = 0;
        p1 = 0;
        for (int tr2 = tr1 + 1; tr2 < 256; tr2++)
        {

            p1 += p[tr2];
            w1 += (tr2 * p[tr2]);
            if (p1 != 0)
            {
                m1 = w1 / p1;
            }

            c1 = p1 * (m1 - Mt) * (m1 - Mt);


            c2 = 0;
            w2 = 0;
            m2 = 0;
            p2 = 0;
            for (int tr3 = tr2 + 1; tr3 < 256; tr3++)
            {

                p2 += p[tr3];
                w2 += (tr3 * p[tr3]);
                if (p2 != 0)
                {
                    m2 = w2 / p2;
                }

                c2 = p2 * (m2 - Mt) * (m2 - Mt);

                c = c0 + c1 + c2;

                if (maxBetweenVar < c)
                {
                    maxBetweenVar = c;
                    optimalTreshold1 = tr1;
                    optimalTreshold2 = tr2;
                    optimalTreshold3 = tr3;
                }
            }
        }
    }

解决方案

So, I've figured it out. The final source code for 4 classes (3 thresholds) Otsu thresholding:

// cv::Mat& src - source image's matrix
    int histogram[256] = { 0 };
    int pixelsCount = src.cols * src.rows;

    for (int y = 0; y < src.rows; y++)
    {
        for (int x = 0; x < src.cols; x++)
        {
            uchar value = src.at<uchar>(y, x);
            histogram[value]++;
        }
    }

    double c = 0;
    double Mt = 0;

    double p[256] = { 0 };
    for (int i = 0; i < 256; i++)
    {
        p[i] = (double) histogram[i] / (double) pixelsCount;
        Mt += i * p[i];
    }

    int optimalTreshold1 = 0;
    int optimalTreshold2 = 0;
    int optimalTreshold3 = 0;

    double maxBetweenVar = 0;

    double w0 = 0;
    double m0 = 0;
    double c0 = 0;
    double p0 = 0;

    double w1 = 0;
    double m1 = 0;
    double c1 = 0;
    double p1 = 0;

    double w2 = 0;
    double m2 = 0;
    double c2 = 0;
    double p2 = 0;
    for (int tr1 = 0; tr1 < 256; tr1++)
    {
        p0 += p[tr1];
        w0 += (tr1 * p[tr1]);
        if (p0 != 0)
        {
            m0 = w0 / p0;
        }

        c0 = p0 * (m0 - Mt) * (m0 - Mt);

        c1 = 0;
        w1 = 0;
        m1 = 0;
        p1 = 0;
        for (int tr2 = tr1 + 1; tr2 < 256; tr2++)
        {

            p1 += p[tr2];
            w1 += (tr2 * p[tr2]);
            if (p1 != 0)
            {
                m1 = w1 / p1;
            }

            c1 = p1 * (m1 - Mt) * (m1 - Mt);


            c2 = 0;
            w2 = 0;
            m2 = 0;
            p2 = 0;
            for (int tr3 = tr2 + 1; tr3 < 256; tr3++)
            {

                p2 += p[tr3];
                w2 += (tr3 * p[tr3]);
                if (p2 != 0)
                {
                    m2 = w2 / p2;
                }

                c2 = p2 * (m2 - Mt) * (m2 - Mt);

                double p3 = 1 - (p0 + p1 + p2);
                double w3 = Mt - (w0 + w1 + w2);
                double m3 = w3 / p3;
                double c3 = p3 * (m3 - Mt) * (m3 - Mt);

                double c = c0 + c1 + c2 + c3;

                if (maxBetweenVar < c)
                {
                    maxBetweenVar = c;
                    optimalTreshold1 = tr1;
                    optimalTreshold2 = tr2;
                    optimalTreshold3 = tr3;
                }
            }
        }
    }

Source image

Result: 3 thresholds / 4 classes

threshold values: 179, 92, 25

这篇关于多级(4)Otsu阈值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆