文档章节

十三种基于直方图的图像全局二值化算法原理、实现、代码及效果。

abcijkxyz
 abcijkxyz
发布于 2016/11/22 16:40
字数 4389
阅读 18
收藏 0
点赞 0
评论 0

      图像二值化的目的是最大限度的将图象中感兴趣的部分保留下来,在很多情况下,也是进行图像分析、特征提取与模式识别之前的必要的图像预处理过程。这个看似简单的问题,在过去的四十年里受到国内外学者的广泛关注,产生了数以百计的阈值选取方法,但如同其他图像分割算法一样,没有一个现有方法对各种各样的图像都能得到令人满意的结果。

     在这些庞大的分类方法中,基于直方图的全局二值算法占有了绝对的市场份额,这些算法都从不同的科学层次提出了各自的实施方案,并且这类方法都有着一些共同的特点:

  1、简单;

     2、算法容易实现;

     3、执行速度快。

     本文摘取了若干种这类方法进行了介绍。

     一:灰度平局值值法:

  1、描述:即使用整幅图像的灰度平均值作为二值化的阈值,一般该方法可作为其他方法的初始猜想值。

  2、原理:    

            

      3、实现代码:

public static int GetMeanThreshold(int[] HistGram)
    {
        int Sum = 0, Amount = 0;
        for (int Y = 0; Y < 256; Y++)
        {
            Amount += HistGram[Y];
            Sum += Y * HistGram[Y];
        }
        return Sum / Amount;
    }

     二、百分比阈值(P-Tile法)

     1、描述

    Doyle于1962年提出的P-Tile (即P分位数法)可以说是最古老的一种阈值选取方法。该方法根据先验概率来设定阈值,使得二值化后的目标或背景像素比例等于先验概率,该方法简单高效,但是对于先验概率难于估计的图像却无能为力。

  2、该原理比较简单,直接以代码实现。

/// <summary>
    /// 百分比阈值
    /// </summary>
    /// <param name="HistGram">灰度图像的直方图</param>
    /// <param name="Tile">背景在图像中所占的面积百分比</param>
    /// <returns></returns>
    public static int GetPTileThreshold(int[] HistGram, int Tile = 50)
    {
        int Y, Amount = 0, Sum = 0;
        for (Y = 0; Y < 256; Y++) Amount += HistGram[Y];        //  像素总数
         for (Y = 0; Y < 256; Y++)
        {
            Sum = Sum + HistGram[Y];
            if (Sum >= Amount * Tile / 100) return Y;
        }
        return -1;
    }

      三、基于谷底最小值的阈值

     1、描述:

  此方法实用于具有明显双峰直方图的图像,其寻找双峰的谷底作为阈值,但是该方法不一定能获得阈值,对于那些具有平坦的直方图或单峰图像,该方法不合适。

  2、实现过程:

  该函数的实现是一个迭代的过程,每次处理前对直方图数据进行判断,看其是否已经是一个双峰的直方图,如果不是,则对直方图数据进行半径为1(窗口大小为3)的平滑,如果迭代了一定的数量比如1000次后仍未获得一个双峰的直方图,则函数执行失败,如成功获得,则最终阈值取两个双峰之间的谷底值作为阈值。

     注意在编码过程中,平滑的处理需要当前像素之前的信息,因此需要对平滑前的数据进行一个备份。另外,首数据类型精度限制,不应用整形的直方图数据,必须转换为浮点类型数据来进行处理,否则得不到正确的结果。

     该算法相关参考论文如下:

   J. M. S. Prewitt and M. L. Mendelsohn, "The analysis of cell images," innnals of the New York Academy of Sciences, vol. 128, pp. 1035-1053, 1966.
     C. A. Glasbey, "An analysis of histogram-based thresholding algorithms," CVGIP: Graphical Models and Image Processing, vol. 55, pp. 532-537, 1993.

     3、实现代码:

public static int GetMinimumThreshold(int[] HistGram)
    {
        int Y, Iter = 0;
        double[] HistGramC = new double[256];           // 基于精度问题,一定要用浮点数来处理,否则得不到正确的结果
        double[] HistGramCC = new double[256];          // 求均值的过程会破坏前面的数据,因此需要两份数据
        for (Y = 0; Y < 256; Y++)
        {
            HistGramC[Y] = HistGram[Y];
            HistGramCC[Y] = HistGram[Y];
        }

        // 通过三点求均值来平滑直方图
        while (IsDimodal(HistGramCC) == false)                                        // 判断是否已经是双峰的图像了      
        {
            HistGramCC[0] = (HistGramC[0] + HistGramC[0] + HistGramC[1]) / 3;                 // 第一点
            for (Y = 1; Y < 255; Y++)
                HistGramCC[Y] = (HistGramC[Y - 1] + HistGramC[Y] + HistGramC[Y + 1]) / 3;     // 中间的点
            HistGramCC[255] = (HistGramC[254] + HistGramC[255] + HistGramC[255]) / 3;         // 最后一点
            System.Buffer.BlockCopy(HistGramCC, 0, HistGramC, 0, 256 * sizeof(double));
            Iter++;
            if (Iter >= 1000) return -1;                                                   // 直方图无法平滑为双峰的,返回错误代码
        }
       // 阈值极为两峰之间的最小值 
        bool Peakfound = false;
        for (Y = 1; Y < 255; Y++)
        {
            if (HistGramCC[Y - 1] < HistGramCC[Y] && HistGramCC[Y + 1] < HistGramCC[Y]) Peakfound = true;
            if (Peakfound == true && HistGramCC[Y - 1] >= HistGramCC[Y] && HistGramCC[Y + 1] >= HistGramCC[Y])
                return Y - 1;
        }
        return -1;
    }

  其中IsDimodal函数为判断直方图是否是双峰的函数,代码如下:

    private static bool IsDimodal(double[] HistGram)       // 检测直方图是否为双峰的
    {
        // 对直方图的峰进行计数,只有峰数位2才为双峰 
        int Count = 0;
        for (int Y = 1; Y < 255; Y++)
        {
            if (HistGram[Y - 1] < HistGram[Y] && HistGram[Y + 1] < HistGram[Y])
            {
                Count++;
                if (Count > 2) return false;
            }
        }
        if (Count == 2)
            return true;
        else
            return false;
    }

  4、效果:

     

    

        原图                                                 二值图                                          原始直方图                平滑后的直方图

  对于这种有较明显的双峰的图像,该算法还是能取得不错的效果的。

     四、基于双峰平均值的阈值

       1、描述:

   该算法和基于谷底最小值的阈值方法类似,只是最后一步不是取得双峰之间的谷底值,而是取双峰的平均值作为阈值。

       2、参考代码:

public static int GetIntermodesThreshold(int[] HistGram)
    {
        int Y, Iter = 0, Index;
        double[] HistGramC = new double[256];           // 基于精度问题,一定要用浮点数来处理,否则得不到正确的结果
        double[] HistGramCC = new double[256];          // 求均值的过程会破坏前面的数据,因此需要两份数据
        for (Y = 0; Y < 256; Y++)
        {
            HistGramC[Y] = HistGram[Y];
            HistGramCC[Y] = HistGram[Y];
        }
        // 通过三点求均值来平滑直方图
        while (IsDimodal(HistGramCC) == false)                                                  // 判断是否已经是双峰的图像了      
        {
            HistGramCC[0] = (HistGramC[0] + HistGramC[0] + HistGramC[1]) / 3;                   // 第一点
            for (Y = 1; Y < 255; Y++)
                HistGramCC[Y] = (HistGramC[Y - 1] + HistGramC[Y] + HistGramC[Y + 1]) / 3;       // 中间的点
            HistGramCC[255] = (HistGramC[254] + HistGramC[255] + HistGramC[255]) / 3;           // 最后一点
            System.Buffer.BlockCopy(HistGramCC, 0, HistGramC, 0, 256 * sizeof(double));         // 备份数据,为下一次迭代做准备
            Iter++;
            if (Iter >= 10000) return -1;                                                       // 似乎直方图无法平滑为双峰的,返回错误代码
        }
// 阈值为两峰值的平均值
        int[] Peak = new int[2];
        for (Y = 1, Index = 0; Y < 255; Y++)
            if (HistGramCC[Y - 1] < HistGramCC[Y] && HistGramCC[Y + 1] < HistGramCC[Y]) Peak[Index++] = Y - 1;
        return ((Peak[0] + Peak[1]) / 2);
    }

      3、效果:

       

       原图                                                 二值图                                           原始直方图                平滑后的直方图

    五、迭代最佳阈值

  1、描述:

    该算法先假定一个阈值,然后计算在该阈值下的前景和背景的中心值,当前景和背景中心值得平均值和假定的阈值相同时,则迭代中止,并以此值为阈值进行二值化。

    2、实现过程:

  (1)求出图象的最大灰度值和最小灰度值,分别记为gl和gu,令初始阈值为:

                       

      (2) 根据阈值T0将图象分割为前景和背景,分别求出两者的平均灰度值Ab和Af:

              

      (3) 令

                         

    如果Tk=Tk+1,则取Tk为所求得的阈值,否则,转2继续迭代

     3、参考代码:

public static int GetIterativeBestThreshold(int[] HistGram)
    {
        int X, Iter = 0;
        int MeanValueOne, MeanValueTwo, SumOne, SumTwo, SumIntegralOne, SumIntegralTwo;
        int MinValue, MaxValue;
        int Threshold, NewThreshold;

        for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;
        for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;

        if (MaxValue == MinValue) return MaxValue;          // 图像中只有一个颜色             
        if (MinValue + 1 == MaxValue) return MinValue;      // 图像中只有二个颜色

        Threshold = MinValue;
        NewThreshold = (MaxValue + MinValue) >> 1;
        while (Threshold != NewThreshold)    // 当前后两次迭代的获得阈值相同时,结束迭代    
        {
            SumOne = 0; SumIntegralOne = 0;
            SumTwo = 0; SumIntegralTwo = 0;
            Threshold = NewThreshold;
            for (X = MinValue; X <= Threshold; X++)         //根据阈值将图像分割成目标和背景两部分,求出两部分的平均灰度值      
            {
                SumIntegralOne += HistGram[X] * X;
                SumOne += HistGram[X];
            }
            MeanValueOne = SumIntegralOne / SumOne;
            for (X = Threshold + 1; X <= MaxValue; X++)
            {
                SumIntegralTwo += HistGram[X] * X;
                SumTwo += HistGram[X];
            }
            MeanValueTwo = SumIntegralTwo / SumTwo;
            NewThreshold = (MeanValueOne + MeanValueTwo) >> 1;       //求出新的阈值
            Iter++;
            if (Iter >= 1000) return -1;
        }
        return Threshold;
    }

  4、效果:

                  

                   

       原图                                          二值图                                         直方图 

   六、OSTU大律法

  1、描述:

       该算法是1979年由日本大津提出的,主要是思想是取某个阈值,使得前景和背景两类的类间方差最大,matlab中的graythresh即是以该算法为原理执行的。

       2、原理:

       关于该算法的原理,网络上有很多,这里为了篇幅有限,不加以赘述。

       3、参考代码:

    public static int GetOSTUThreshold(int[] HistGram)
    {
        int X, Y, Amount = 0;
        int PixelBack = 0, PixelFore = 0, PixelIntegralBack = 0, PixelIntegralFore = 0, PixelIntegral = 0;
        double OmegaBack, OmegaFore, MicroBack, MicroFore, SigmaB, Sigma;              // 类间方差;
        int MinValue, MaxValue;
        int Threshold = 0;

        for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;
        for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;
        if (MaxValue == MinValue) return MaxValue;          // 图像中只有一个颜色             
        if (MinValue + 1 == MaxValue) return MinValue;      // 图像中只有二个颜色

        for (Y = MinValue; Y <= MaxValue; Y++) Amount += HistGram[Y];        //  像素总数

        PixelIntegral = 0;
        for (Y = MinValue; Y <= MaxValue; Y++) PixelIntegral += HistGram[Y] * Y;
        SigmaB = -1;
        for (Y = MinValue; Y < MaxValue; Y++)
        {
            PixelBack = PixelBack + HistGram[Y];
            PixelFore = Amount - PixelBack;
            OmegaBack = (double)PixelBack / Amount;
            OmegaFore = (double)PixelFore / Amount;
            PixelIntegralBack += HistGram[Y] * Y;
            PixelIntegralFore = PixelIntegral - PixelIntegralBack;
            MicroBack = (double)PixelIntegralBack / PixelBack;
            MicroFore = (double)PixelIntegralFore / PixelFore;
            Sigma = OmegaBack * OmegaFore * (MicroBack - MicroFore) * (MicroBack - MicroFore);
            if (Sigma > SigmaB)
            {
                SigmaB = Sigma;
                Threshold = Y;
            }
        }
        return Threshold;
    }

  4、效果:

              

  该算法对于那些具有平坦的直方图的图像具有一定的适应能力。

      七、一维最大熵

      1、描述:

       该算法把信息论中熵的概念引入到图像中,通过计算阈值分割后两部分熵的和来判断阈值是否为最佳阈值。

      2、算法原理

       这方面的文章也比较多,留给读者自行去查找相关资料。

       3、参考代码: 

public static int Get1DMaxEntropyThreshold(int[] HistGram)
    {
        int  X, Y,Amount=0;
        double[] HistGramD = new double[256];
        double SumIntegral, EntropyBack, EntropyFore, MaxEntropy;
        int MinValue = 255, MaxValue = 0;
        int Threshold = 0;

        for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;
        for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;
        if (MaxValue == MinValue) return MaxValue;          // 图像中只有一个颜色             
        if (MinValue + 1 == MaxValue) return MinValue;      // 图像中只有二个颜色

        for (Y = MinValue; Y <= MaxValue; Y++) Amount += HistGram[Y];        //  像素总数

        for (Y = MinValue; Y <= MaxValue; Y++)   HistGramD[Y] = (double)HistGram[Y] / Amount+1e-17;

        MaxEntropy = double.MinValue; ;
        for (Y = MinValue + 1; Y < MaxValue; Y++)
        {
            SumIntegral = 0;
            for (X = MinValue; X <= Y; X++) SumIntegral += HistGramD[X];
            EntropyBack = 0;
            for (X = MinValue; X <= Y; X++) EntropyBack += (-HistGramD[X] / SumIntegral * Math.Log(HistGramD[X] / SumIntegral));
            EntropyFore = 0;
            for (X = Y + 1; X <= MaxValue; X++) EntropyFore += (-HistGramD[X] / (1 - SumIntegral) * Math.Log(HistGramD[X] / (1 - SumIntegral)));
            if (MaxEntropy < EntropyBack + EntropyFore)
            {
                Threshold = Y;
                MaxEntropy = EntropyBack + EntropyFore;
            }
        }
        return Threshold;
    }

     八、力矩保持法 
     1、描述:

  该算法通过选择恰当的阈值从而使得二值后的图像和原始的灰度图像具有三个相同的初始力矩值。

  2、原理:

    参考论文:W. Tsai, “Moment-preserving thresholding: a new approach,” Comput.Vision Graphics Image Process., vol. 29, pp. 377-393, 1985.

     由于无法下载到该论文(收费的),仅仅给出从其他一些资料中找到的公式共享一下。

             

    其中的A\B\C的函数可见代码部分。

   3、参考代码:

public static byte GetMomentPreservingThreshold(int[] HistGram)
    {
        int X, Y, Index = 0, Amount=0;
        double[] Avec = new double[256];
        double X2, X1, X0, Min;

        for (Y = 0; Y <= 255; Y++) Amount += HistGram[Y];        //  像素总数
        for (Y = 0; Y < 256; Y++) Avec[Y] = (double)A(HistGram, Y) / Amount;       // The threshold is chosen such that A(y,t)/A(y,n) is closest to x0.

        // The following finds x0.

        X2 = (double)(B(HistGram, 255) * C(HistGram, 255) - A(HistGram, 255) * D(HistGram, 255)) / (double)(A(HistGram, 255) * C(HistGram, 255) - B(HistGram, 255) * B(HistGram, 255));
        X1 = (double)(B(HistGram, 255) * D(HistGram, 255) - C(HistGram, 255) * C(HistGram, 255)) / (double)(A(HistGram, 255) * C(HistGram, 255) - B(HistGram, 255) * B(HistGram, 255));
        X0 = 0.5 - (B(HistGram, 255) / A(HistGram, 255) + X2 / 2) / Math.Sqrt(X2 * X2 - 4 * X1);

        for (Y = 0, Min = double.MaxValue; Y < 256; Y++)
        {
            if (Math.Abs(Avec[Y] - X0) < Min)
            {
                Min = Math.Abs(Avec[Y] - X0);
                Index = Y;
            }
        }
        return (byte)Index;
    }

    private static double A(int[] HistGram, int Index)
    {
        double Sum = 0;
        for (int Y = 0; Y <= Index; Y++)
            Sum += HistGram[Y];
        return Sum;
    }

    private static double B(int[] HistGram, int Index)
    {
        double Sum = 0;
        for (int Y = 0; Y <= Index; Y++)
            Sum += (double)Y * HistGram[Y];
        return Sum;
    }

    private static double C(int[] HistGram, int Index)
    {
        double Sum = 0;
        for (int Y = 0; Y <= Index; Y++)
            Sum += (double)Y * Y * HistGram[Y];
        return Sum;
    }

    private static double D(int[] HistGram, int Index)
    {
        double Sum = 0;
        for (int Y = 0; Y <= Index; Y++)
            Sum += (double)Y * Y * Y * HistGram[Y];
        return Sum;
    }

    对于很多图像,该算法也能取得比较满意的结果。

   九、基于模糊集理论的阈值

    该算法的具体分析可见:基于模糊集理论的一种图像二值化算法的原理、实现效果及代码

    此法也借用香农熵的概念,该算法一般都能获得较为理想的分割效果,不管是对双峰的还是单峰的图像。

  十、Kittler最小错误分类法

    由于精力有限,以下几种算法仅仅给出算法的论文及相关的代码。

    该算法具体的分析见:

  • Kittler, J & Illingworth, J (1986), "Minimum error thresholding", Pattern Recognition 19: 41-47

  参考代码:

public static int GetKittlerMinError(int[] HistGram)
    {
        int X, Y;
        int MinValue, MaxValue;
        int Threshold ;
        int PixelBack, PixelFore;
        double OmegaBack, OmegaFore, MinSigma, Sigma, SigmaBack, SigmaFore;
        for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++) ;
        for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--) ;
        if (MaxValue == MinValue) return MaxValue;          // 图像中只有一个颜色             
        if (MinValue + 1 == MaxValue) return MinValue;      // 图像中只有二个颜色
        Threshold = -1;
        MinSigma = 1E+20;
        for (Y = MinValue; Y < MaxValue; Y++)
        {
            PixelBack = 0; PixelFore = 0;
            OmegaBack = 0; OmegaFore = 0;
            for (X = MinValue; X <= Y; X++)
            {
                PixelBack += HistGram[X];
                OmegaBack = OmegaBack + X * HistGram[X];
            }
            for (X = Y + 1; X <= MaxValue; X++)
            {
                PixelFore += HistGram[X];
                OmegaFore = OmegaFore + X * HistGram[X];
            }
            OmegaBack = OmegaBack / PixelBack;
            OmegaFore = OmegaFore / PixelFore;
            SigmaBack = 0; SigmaFore = 0;
            for (X = MinValue; X <= Y; X++) SigmaBack = SigmaBack + (X - OmegaBack) * (X - OmegaBack) * HistGram[X];
            for (X = Y + 1; X <= MaxValue; X++) SigmaFore = SigmaFore + (X - OmegaFore) * (X - OmegaFore) * HistGram[X];
            if (SigmaBack == 0 || SigmaFore == 0)
            {
                if (Threshold == -1)
                    Threshold = Y;
            }
            else
            {
                SigmaBack = Math.Sqrt(SigmaBack / PixelBack);
                SigmaFore = Math.Sqrt(SigmaFore / PixelFore);
                Sigma = 1 + 2 * (PixelBack * Math.Log(SigmaBack / PixelBack) + PixelFore * Math.Log(SigmaFore / PixelFore));
                if (Sigma < MinSigma)
                {
                    MinSigma = Sigma;
                    Threshold = Y;
                }
            }
        }
        return Threshold;
    }

  从实际的运行效果看,该算法并不很好。

  十一:ISODATA(也叫做intermeans法)

  参考论文:

     参考代码(未做整理):

// Also called intermeans
    // Iterative procedure based on the isodata algorithm [T.W. Ridler, S. Calvard, Picture 
    // thresholding using an iterative selection method, IEEE Trans. System, Man and 
    // Cybernetics, SMC-8 (1978) 630-632.] 
    // The procedure divides the image into objects and background by taking an initial threshold,
    // then the averages of the pixels at or below the threshold and pixels above are computed. 
    // The averages of those two values are computed, the threshold is incremented and the 
    // process is repeated until the threshold is larger than the composite average. That is,
    //  threshold = (average background + average objects)/2
    // The code in ImageJ that implements this function is the getAutoThreshold() method in the ImageProcessor class. 
    //
    // From: Tim Morris (dtm@ap.co.umist.ac.uk)
    // Subject: Re: Thresholding method?
    // posted to sci.image.processing on 1996/06/24
    // The algorithm implemented in NIH Image sets the threshold as that grey
    // value, G, for which the average of the averages of the grey values
    // below and above G is equal to G. It does this by initialising G to the
    // lowest sensible value and iterating:

    // L = the average grey value of pixels with intensities < G
    // H = the average grey value of pixels with intensities > G
    // is G = (L + H)/2?
    // yes => exit
    // no => increment G and repeat
    //
    // There is a discrepancy with IJ because they are slightly different methods

    public static int GetIsoDataThreshold(int[] HistGram)
    {
        int i, l, toth, totl, h, g = 0;
        for (i = 1; i < HistGram.Length; i++)
        {
            if (HistGram[i] > 0)
            {
                g = i + 1;
                break;
            }
        }
        while (true)
        {
            l = 0;
            totl = 0;
            for (i = 0; i < g; i++)
            {
                totl = totl + HistGram[i];
                l = l + (HistGram[i] * i);
            }
            h = 0;
            toth = 0;
            for (i = g + 1; i < HistGram.Length; i++)
            {
                toth += HistGram[i];
                h += (HistGram[i] * i);
            }
            if (totl > 0 && toth > 0)
            {
                l /= totl;
                h /= toth;
                if (g == (int)Math.Round((l + h) / 2.0))
                    break;
            }
            g++;
            if (g > HistGram.Length - 2)
            {
                return 0;
            }
        }
        return g;
    }

       十二、Shanbhag 法

        参考论文:

      Shanbhag, Abhijit G. (1994), "Utilization of information measure as a means of image thresholding", Graph. Models Image Process. (Academic Press, Inc.) 56 (5): 414--419, ISSN 1049-9652, DOI 10.1006/cgip.1994.1037

     参考代码(未整理):

public static int GetShanbhagThreshold(int[] HistGram)
    {
        int threshold;
        int ih, it;
        int first_bin;
        int last_bin;
        double term;
        double tot_ent;  /* total entropy */
        double min_ent;  /* max entropy */
        double ent_back; /* entropy of the background pixels at a given threshold */
        double ent_obj;  /* entropy of the object pixels at a given threshold */
        double[] norm_histo = new double[HistGram.Length]; /* normalized histogram */
        double[] P1 = new double[HistGram.Length]; /* cumulative normalized histogram */
        double[] P2 = new double[HistGram.Length];

        int total = 0;
        for (ih = 0; ih < HistGram.Length; ih++)
            total += HistGram[ih];

        for (ih = 0; ih < HistGram.Length; ih++)
            norm_histo[ih] = (double)HistGram[ih] / total;

        P1[0] = norm_histo[0];
        P2[0] = 1.0 - P1[0];
        for (ih = 1; ih < HistGram.Length; ih++)
        {
            P1[ih] = P1[ih - 1] + norm_histo[ih];
            P2[ih] = 1.0 - P1[ih];
        }

        /* Determine the first non-zero bin */
        first_bin = 0;
        for (ih = 0; ih < HistGram.Length; ih++)
        {
            if (!(Math.Abs(P1[ih]) < 2.220446049250313E-16))
            {
                first_bin = ih;
                break;
            }
        }

        /* Determine the last non-zero bin */
        last_bin = HistGram.Length - 1;
        for (ih = HistGram.Length - 1; ih >= first_bin; ih--)
        {
            if (!(Math.Abs(P2[ih]) < 2.220446049250313E-16))
            {
                last_bin = ih;
                break;
            }
        }

        // Calculate the total entropy each gray-level
        // and find the threshold that maximizes it 
        threshold = -1;
        min_ent = Double.MaxValue;

        for (it = first_bin; it <= last_bin; it++)
        {
            /* Entropy of the background pixels */
            ent_back = 0.0;
            term = 0.5 / P1[it];
            for (ih = 1; ih <= it; ih++)
            { //0+1?
                ent_back -= norm_histo[ih] * Math.Log(1.0 - term * P1[ih - 1]);
            }
            ent_back *= term;

            /* Entropy of the object pixels */
            ent_obj = 0.0;
            term = 0.5 / P2[it];
            for (ih = it + 1; ih < HistGram.Length; ih++)
            {
                ent_obj -= norm_histo[ih] * Math.Log(1.0 - term * P2[ih]);
            }
            ent_obj *= term;

            /* Total entropy */
            tot_ent = Math.Abs(ent_back - ent_obj);

            if (tot_ent < min_ent)
            {
                min_ent = tot_ent;
                threshold = it;
            }
        }
        return threshold;
    }

     十三、Yen法

  参考论文:

     1) Yen J.C., Chang F.J., and Chang S. (1995) "A New Criterion  for Automatic Multilevel Thresholding" IEEE Trans. on Image  Processing, 4(3): 370-378
     2) Sezgin M. and Sankur B. (2004) "Survey over Image Thresholding Techniques and Quantitative Performance Evaluation" Journal of  Electronic Imaging, 13(1): 146-165

       参考代码(未整理):

// M. Emre Celebi
    // 06.15.2007
    // Ported to ImageJ plugin by G.Landini from E Celebi's fourier_0.8 routines
    public static int GetYenThreshold(int[] HistGram)
    {
        int threshold;
        int ih, it;
        double crit;
        double max_crit;
        double[] norm_histo = new double[HistGram.Length]; /* normalized histogram */
        double[] P1 = new double[HistGram.Length]; /* cumulative normalized histogram */
        double[] P1_sq = new double[HistGram.Length];
        double[] P2_sq = new double[HistGram.Length];

        int total = 0;
        for (ih = 0; ih < HistGram.Length; ih++)
            total += HistGram[ih];

        for (ih = 0; ih < HistGram.Length; ih++)
            norm_histo[ih] = (double)HistGram[ih] / total;

        P1[0] = norm_histo[0];
        for (ih = 1; ih < HistGram.Length; ih++)
            P1[ih] = P1[ih - 1] + norm_histo[ih];

        P1_sq[0] = norm_histo[0] * norm_histo[0];
        for (ih = 1; ih < HistGram.Length; ih++)
            P1_sq[ih] = P1_sq[ih - 1] + norm_histo[ih] * norm_histo[ih];

        P2_sq[HistGram.Length - 1] = 0.0;
        for (ih = HistGram.Length - 2; ih >= 0; ih--)
            P2_sq[ih] = P2_sq[ih + 1] + norm_histo[ih + 1] * norm_histo[ih + 1];

        /* Find the threshold that maximizes the criterion */
        threshold = -1;
        max_crit = Double.MinValue;
        for (it = 0; it < HistGram.Length; it++)
        {
            crit = -1.0 * ((P1_sq[it] * P2_sq[it]) > 0.0 ? Math.Log(P1_sq[it] * P2_sq[it]) : 0.0) + 2 * ((P1[it] * (1.0 - P1[it])) > 0.0 ? Math.Log(P1[it] * (1.0 - P1[it])) : 0.0);
            if (crit > max_crit)
            {
                max_crit = crit;
                threshold = it;
            }
        }
        return threshold;
    }

      一行很多代码是摘自开源软件ImageJ的资料,读者也可以参考:http://fiji.sc/wiki/index.php/Auto_Threshold  这里获得更多的信息。

      最后,我对这些算法的做了简单的UI界面,供有兴趣的读者参考。

      工程代码下载:http://files.cnblogs.com/Imageshop/HistgramBinaryzation.rar

 

 

 

 

*********************************作者: laviewpbt   时间: 2013.9.7       联系QQ:  33184777  转载请保留本行信息************************

 

本文转载自:http://www.cnblogs.com/Imageshop/p/3307308.html

共有 人打赏支持
abcijkxyz
粉丝 60
博文 6195
码字总数 1876
作品 0
深圳
项目经理
图像直方图与直方图均衡化

图像直方图(英语:Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素数。可以借助观察该直方图了解需要如何调整亮度分布。这种直方图中,横坐标的左侧...

Tony沈哲 ⋅ 2017/05/22 ⋅ 0

(三)matlab数字图像处理实验-图像灰度变换处理

前两节都是熟悉一下怎么在matlab底下对图片做一些操作,并没有什么卵用,这一节稍微有点卵用,灰度变换一般是图像处理的第一步。 数字图像处理实验1-9点击下列链接有源码和链接: matlab数字...

aninstein ⋅ 01/06 ⋅ 0

“我爱智能”原创性博客索引

不知不觉,博客也写出了一点小体系,新的阶段已经开始,未来希望再接再厉继续补充这一体系,在成长中写博客,在博客中成长,在此先做一个小的梳理,谢谢大家的支持。 一)关于深度学习系列 ...

on2way ⋅ 2015/08/29 ⋅ 0

手写数字识别系统之图像分割

背景 本文,主要介绍我之前在学校时候,研究的一些跟手写数字识别相关的技术心得,主要涉及:数字图像处理、特征提取、神经网络等等相关的一些技术。。 虽然很多用到的还是网上现有的比较成熟...

ruki ⋅ 2016/07/30 ⋅ 0

灰度图像的阈值化

通过对灰度图像二值化处理,能够凸现出感兴趣目标的轮廓. 灰度图像的二值化处理就是讲图像上的点的灰度置为0或255,也就是讲整个图像呈现出明显的黑白效果。即将256个亮度等级的灰度图像通过适...

文艺小青年 ⋅ 2017/07/06 ⋅ 0

图像分析之直方图分析

图像分析之强度直方图分析 直方图介绍 强度直方图图形化显示不同的像素值在不同的强度值上的出现频率,对于灰度图像来说强度 范围为[0~255]之间,对于RGB的彩色图像可以独立显示三种颜色的强...

iamfish ⋅ 2012/04/22 ⋅ 0

不同色彩转换

〇 引子 图像有多种色彩模型,如灰度图、RGB、HSV、YCbCr等等。这些图片文件在计算机中以不同的格式存在,如JPEG、png。图像的原始存储格式限定了读取到内存后的存在形式,在图像处理、计算机...

Aspirinrin ⋅ 2017/09/19 ⋅ 0

OpenCV之LBP算法学习

目录 前言 LBP算法概述 指局部二值模式,英文全称:,是一种用来描述图像局部特征的算子,特征具有灰度不变性和旋转不变性等显著优点。常应用于人脸识别和目标检测中,在中有使用特征进行人脸...

simonforfuture ⋅ 2017/12/20 ⋅ 0

LBP特征原理及代码实现

一、LBP特征的背景介绍 LBP指局部二值模式,英文全称:Local Binary Pattern,是一种用来描述图像局部特征的算子,LBP特征具有灰度不变性和旋转不变性等显著优点。它是由T. Ojala, M.Pietikä...

Quincuntial ⋅ 2016/01/19 ⋅ 0

【OpenCV3.3】检测图像中的身份证区域

假设现有一些含身份证前景以及不确定背景的图像,想通过计算机将身份证区域检测出来,实现诸如用户拍照定位提示、背景分离等业务,用OpenCV该如何做呢?如果输入图像前景和背景同时具有一定区...

wjf1997 ⋅ 2017/08/16 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

volatile和synchronized的区别

volatile和synchronized的区别 在讲这个之前需要先了解下JMM(Java memory Model :java内存模型):并发过程中如何处理可见性、原子性、有序性的问题--建立JMM模型 详情请看:https://baike.b...

MarinJ_Shao ⋅ 30分钟前 ⋅ 0

深入分析Kubernetes Critical Pod(一)

Author: xidianwangtao@gmail.com 摘要:大家在部署Kubernetes集群AddOn组件的时候,经常会看到Annotation scheduler.alpha.kubernetes.io/critical-pod"="",以表示这是一个关键服务,那你知...

WaltonWang ⋅ 37分钟前 ⋅ 0

原子性 - synchronized关键词

原子性概念 原子性提供了程序的互斥操作,同一时刻只能有一个线程能对某块代码进行操作。 原子性的实现方式 在jdk中,原子性的实现方式主要分为: synchronized:关键词,它依赖于JVM,保证了同...

dotleo ⋅ 44分钟前 ⋅ 0

【2018.06.22学习笔记】【linux高级知识 14.4-15.3】

14.4 exportfs命令 14.5 NFS客户端问题 15.1 FTP介绍 15.2/15.3 使用vsftpd搭建ftp

lgsxp ⋅ 54分钟前 ⋅ 0

JeeSite 4.0 功能权限管理基础(Shiro)

Shiro是Apache的一个开源框架,是一个权限管理的框架,实现用户认证、用户授权等。 只要有用户参与一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户...

ThinkGem ⋅ 昨天 ⋅ 0

python f-string 字符串格式化

主要内容 从Python 3.6开始,f-string是格式化字符串的一种很好的新方法。与其他格式化方式相比,它们不仅更易读,更简洁,不易出错,而且速度更快! 在本文的最后,您将了解如何以及为什么今...

阿豪boy ⋅ 昨天 ⋅ 0

Python实现自动登录站点

如果我们想要实现自动登录,那么我们就需要能够驱动浏览器(比如谷歌浏览器)来实现操作,ChromeDriver 刚好能够帮助我们这一点(非谷歌浏览器的驱动有所不同)。 一、确认软件版本 首先我们...

blackfoxya ⋅ 昨天 ⋅ 0

线性回归原理和实现基本认识

一:介绍 定义:线性回归在假设特证满足线性关系,根据给定的训练数据训练一个模型,并用此模型进行预测。为了了解这个定义,我们先举个简单的例子;我们假设一个线性方程 Y=2x+1, x变量为商...

wangxuwei ⋅ 昨天 ⋅ 0

容器之查看minikue的environment——minikube的环境信息

执行如下命令 mjduan@mjduandeMacBook-Pro:~/Docker % minikube docker-envexport DOCKER_TLS_VERIFY="1"export DOCKER_HOST="tcp://192.168.99.100:2376"export DOCKER_CERT_PATH="/U......

汉斯-冯-拉特 ⋅ 昨天 ⋅ 0

mysql远程连接不上

设置了root所有hosts远程登录,可是远程登录还是失败,原因可能如下: 登录本地数据库 mysql -uroot -p123456 查询用户表 mysql> select user,host,password from mysql.user; 删除密码为空的...

冰公子 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部