【Emgu CV教程】7.3、图像锐化(增强)之手搓代码实现直方图均衡化


一、介绍

1.写在前面

上一篇文章介绍的是直方图均衡化,使用Emgu CV的EqualizeHist()函数。它对于背景和前景都太亮或者太暗的图像非常有用,而且计算速度非常快,简单又好用。但是存在一个缺点:EqualizeHist()函数的输出结果是8位单通道的灰度图,如果我们输入图像是一个彩色图像,先要转灰度图,再传入EqualizeHist()函数,最后得到一个锐化后的新灰度图。

怎么样能够将彩色图像经过直方图均衡化,得到的结果也是彩色图像呢?Emgu CV没有这个函数,但是伟大的CSDN上面有专家高手啊。这不,介绍的文章它就来了:

直方图均衡化算法原理与c++实现

作者是 小武~~ ,利用C++配合OpenCV完成,代码的原理我看了半天也没看懂,说是涉及到了概率论的知识,可惜大学时期学的概率论在n年前就忘了,不过不影响我把它转换为可以正常运行的C#程序。

1、感谢原作者 小武~~ 提供的代码和思路。
2、这只是代码的演示,如果涉及到侵权行为,可以联系我删除这篇文章。代码及程序思路是否可以用于商业行为,我也不清楚。不建议读者们直接拿过来并应用到商业项目中。

2.彩色图像直方图均衡化函数

C#代码如下:

        /// <summary>
        /// 彩色图像直方图均衡化函数.
        /// </summary>
        /// <param name="inputMat">输入的图像,三通道彩色图像.</param>
        /// <returns>直方图均衡化后的图像,也是三通道彩色图像.</returns>
        private Mat HistogramEqualization(Mat inputMat)
        {
            Mat dst = inputMat.Clone();
            int rows = inputMat.Rows; // 输入图像行数
            int cols = inputMat.Cols; // 输入图像列数
            int totalNum = rows * cols; // 输入图像总像素数

            Image<Bgr, int> imgSrc = inputMat.ToImage<Bgr, int>();
            int[] blueChannel = new int[256];
            int[] greenChannel = new int[256];
            int[] redChannel = new int[256];
            for (int i = 0; i < 256; ++i)
            {
                blueChannel[i] = 0;
                greenChannel[i] = 0;
                redChannel[i] = 0;
            }
            
            for (int i = 0; i < rows; ++i)
            {
                for (int j = 0; j < cols; ++j)
                {
                    blueChannel[imgSrc.Data[i, j, 0]]++;
                    greenChannel[imgSrc.Data[i, j, 1]]++;
                    redChannel[imgSrc.Data[i, j, 2]]++;
                }
            }

            // 计算分布函数
            int[] lutBlue = new int[256];
            int[] lutGreen = new int[256];
            int[] lutRed = new int[256];
            int sumBlue = 0, sumGreen = 0, sumRed = 0;
            for (int k = 0; k < 256; k++)
            {
                sumBlue += blueChannel[k];
                sumGreen += greenChannel[k];
                sumRed += redChannel[k];
                lutBlue[k] = 255 * sumBlue / totalNum;
                lutGreen[k] = 255 * sumGreen / totalNum;
                lutRed[k] = 255 * sumRed / totalNum;
            }

            // 灰度变换(赋值)
            Image<Bgr, int> imgDst = dst.ToImage<Bgr, int>();
            for (int i = 0; i < rows; ++i)
            {
                for (int j = 0; j < cols; ++j)
                {
                    imgDst.Data[i, j, 0] = lutBlue[imgSrc.Data[i, j, 0]];
                    imgDst.Data[i, j, 1] = lutGreen[imgSrc.Data[i, j, 1]];
                    imgDst.Data[i, j, 2] = lutRed[imgSrc.Data[i, j, 2]];
                }
            }

            dst = imgDst.Mat;
            dst.ConvertTo(dst, DepthType.Cv8U);
            return dst;
        }

二、举例

原始素材定义为srcMat,如下:
在这里插入图片描述
还是这个电影里的镜头,执行

Mat dstMat = HistogramEqualization(srcMat);

看一下效果,不光由黑夜变白天,还由黑白变彩色,真厉害,再次感谢原始作者 小武~~

在这里插入图片描述


原创不易,请勿抄袭。共同进步,相互学习。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值