一、介绍
1.写在前面
上一篇文章介绍的是直方图均衡化,使用Emgu CV的EqualizeHist()函数。它对于背景和前景都太亮或者太暗的图像非常有用,而且计算速度非常快,简单又好用。但是存在一个缺点:EqualizeHist()函数的输出结果是8位单通道的灰度图,如果我们输入图像是一个彩色图像,先要转灰度图,再传入EqualizeHist()函数,最后得到一个锐化后的新灰度图。
怎么样能够将彩色图像经过直方图均衡化,得到的结果也是彩色图像呢?Emgu CV没有这个函数,但是伟大的CSDN上面有专家高手啊。这不,介绍的文章它就来了:
作者是 小武~~ ,利用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);
看一下效果,不光由黑夜变白天,还由黑白变彩色,真厉害,再次感谢原始作者 小武~~ 。
原创不易,请勿抄袭。共同进步,相互学习。