图像处理(Image Processing) ---------- 大津二值化 (Otsu‘s)(C#实现)

图像的二值化,通常指灰阶图像转化为二值图像,二值图像即一个pixel只有两种变化全暗(0)或者全亮(255),单独记录二值图像的话就每个Pixel只要1bit就足够了,0或1。

要将一个灰阶图像二值化,你就要能够很好的区分哪些是背景、哪些是前景,或者说哪一部分该变全暗哪一部分该变全亮。这就需要找到一个最好Threshold(阀值),把大于这个阀值的灰度值极大化(全亮),小于这个阀值的灰度值极小化(全暗)。

阀值能我们可以设固定的,也可以用自适应方法。Otsu就是极好的、通过计算找到最佳的阀值的方法。

  • Otsu's :
    • 通过阀值将一幅图的灰度级分成了两个区域,最佳的阀值说简单点要做到的是:这两个区域,各自内部要越像越好,区域之间要差异越大越好。要看一个区域的pixel像不像,差异大不大用什么?答案很简单就是方差。Otsu's的方法就是要两区域,区域內方差要最小或者区域间方差要最大。
    • 方差公式:,x 是均值,n 是数总个数。
    • 所以Otsu's 的公式 : \delta = \omega_{1} \ast s_{1}^{2} + \omega_{2} \ast s_{2}^{2}  ;  \omega_{1} 和 \omega_{2} 分别为两区域 pixel 所占的比例权重,s_{1}^{2} 和 s_{2}^{2} 就是两区域的pixel內方差了。
    • 实现时,只要从0~255灰度级中,计算每一个灰度级的 \delta ,这样找到 \delta 最小的那个灰度级,就是最佳的阀值。

 

C#实现:

//通过Otsu's获得最佳Thresholding;
        public int getOPTThresholding(Bitmap grayImage)
        {   //计算类内方差之和最小;
            //获取按 pixel 个数统计直方图
            int[] histogram = getGrayNumbHistogram(grayImage);
            int pixelNumb = grayImage.Height * grayImage.Width;
            int threshold;
            //储存差异集合
            double[] variances = new double[256];
            //T为0-255,为 Threshold 拟定值.
            for (int T = 0; T < histogram.Length; T++)
            {
                //两区域 pixel 个数,区域 pixel 值总和,区域平均数,区域权重;
                double n1 = 0, n2 = 0;
                double total1 = 0, total2 = 0;
                double aver1 = 0, aver2 = 0;
                double w1 = 0, w2 = 0;
                //区域 1,2 方差
                double ft1 = 0, ft2 = 0;
            
                for (int i = 0; i < T; i++)
                {
                    n1 += histogram[i];
                    total1 += histogram[i] * i;
                }
                for (int j = T; j < variances.Length; j++)
                {
                    n2 += histogram[j];
                    total2 += histogram[j] * j;
                }
                w1 = n1 / pixelNumb;
                w2 = n2 / pixelNumb;
                //防止个数為 0,出错;
                aver1 = (n1 == 0) ? 0 : (total1 / n1);
                aver2 = (n2 == 0) ? 0 : (total2 / n2);
                for (int i = 0; i < T; i++)
                {
                    ft1 += (Math.Pow((i - aver1), 2) * histogram[i]);
                }
                for (int j = T; j < 256; j++)
                {
                    ft2 += (Math.Pow((j - aver2), 2) * histogram[j]);
                }
                ft1 = (n1 == 0) ? 0 : (ft1 / n1);
                ft2 = (n2 == 0) ? 0 : (ft2 / n2);
                variances[T] = w1 * ft1 + w2 * ft2;
            }
            double min = variances[0];
            threshold = 0;
            for (int i = 1; i < variances.Length; i++)
            {
                if (variances[i] < min)
                {
                    min = variances[i];
                    threshold = i;
                }
            }
            return threshold;
        }

 

 

仅为个人理解,如有不足,请指教。 https://blog.csdn.net/weixin_35811044

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值