Otsu最佳全局算法c#实现-基于EmguCV

代码也没进行优化,可能运行速度比较慢。


此函数根据输入的图像返回其最适应阈值。


 public static int OtsuThreshold(Mat image)
        {
            if (image.NumberOfChannels != 1)
            {
                throw new Exception("通道必须为1");
            }

            //提取直方图------------------------------------
            long[] his = new long[256];
            for (int i = 0; i < 256; i++)
            {
                his[i] = 0;
            }


            unsafe
            {
                byte* data = (byte*)image.DataPointer.ToPointer();

                for (int row = 0; row < image.Height; row++)
                {
                    //data = data + row * image.Cols;
                    for (int col = 0; col < image.Width; col++)
                    {
                        his[*data]++;
                        data++;
                    }
                }
            }
            //-----------------------------------------------

            float _PK;
            float _MK;//第k级累加灰度均值;
            float _MG = 0;//整个图片的灰度均值

            double _MN = image.Rows * image.Cols;//图片的像素数目
            float[] _Ks = new float[256];//存储类值最大方差
            float _Max;//类间最大方差
            List<int> _MaxKs = new List<int>();//存储使类间最大方差的多个K值;



            for (int i = 0; i < 256; i++)//计算图片平均灰度值
            {
                _MG += (float)(i * (double)his[i] / _MN);
            }


            for (int k = 0; k < 256; k++)//计算 图片在不同K的类值最大方差
            {
                long _count = 0;//表示在k中存在的像素
                for (int _index = 0; _index <= k; _index++)//若所有像素都在k内,就将其方差置为0
                {
                    _count += his[_index];
                }
                if (_count == image.Rows * image.Cols)
                {
                    _Ks[k] = 0;
                    continue;
                }
                else if (_count == 0)
                {
                    _Ks[k] = 0;
                    continue;
                }

                _PK = (float)(_count / _MN);
                _MK = 0;

                for (int i = 0; i <= k; i++)
                {
                    float p = (float)(his[i] / _MN);
                    //_PK += p;
                    _MK += i * p;
                }

                _Ks[k] = (float)Math.Pow(_MG * _PK - _MK, 2) / (_PK * (1 - _PK));
            }

            _Max = _Ks.Max();
            for (int i = 0; i < 256; i++)
            {
                if (_Ks[i] == _Max)
                    _MaxKs.Add(i);
            }

            int _K = (int)_MaxKs.Average();
            return _K;
        }




  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值