本示例是《OpenCV3编程入门》中7.5.3中的示例程序的C# + EMGU 3.4.1版,演示了如何用EqualizeHist()函数进行图像的直方图均衡化。
原书代码仅演示了对灰度图像的直方图均衡化,对此我做了一些改变,从而可对彩色图像进行直方图均衡化。
彩色图像的直方图均衡化说明
由于opencv自带的函数是对灰度图像进行直方图均衡化的,所以在需要对彩色图像进行直方图均衡化时,不可直接调用函数。另外需要注意的是,对于彩色图像(RGB),直接对三个通道单独进行直方图均衡化,然后合成是不可取的,原因是直方图均衡化并非线性操作,这样会引起颜色失真。
可行的方式是将RGB转换到HSV,HSI,YUV 或者YCrCb颜色空间,然后对亮度(即前面的V,I,Y)通道进行均衡化,这样不会对彩色的色调产生影响,最后再转换回RGB空间即可。特别推荐YCrCb颜色空间,因为它就是专门为数字图像所设计的。
彩色图像的直方图均衡化程序代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
namespace EqualizeHist
{
class Program
{
static void Main(string[] args)
{
//【1】加载并显示源图像
Mat srcImage = CvInvoke.Imread("star.jpg");
CvInvoke.Imshow("Source Image", srcImage); //显示源图像
//【2】将srcImage转换到YCrCb颜色空间
Mat yccImage = new Mat(); //定义yccImage变量,存储转化后的图
CvInvoke.CvtColor(srcImage, yccImage, ColorConversion.Bgr2YCrCb); //颜色空间转化
//【3】分离yccImage,以便对其亮度通道(Y通道)应用直方图均衡化
VectorOfMat channels = new VectorOfMat(); //定义channels存储split后的各通道图像
CvInvoke.Split(yccImage, channels); //调用Split函数,分离yccImage颜色通道
CvInvoke.EqualizeHist(channels[0], channels[0]); //对Y通道进行直方图均衡化
//【4】转换回Bgr颜色空间,并显示结果图
CvInvoke.Merge(channels, yccImage); //合并所有通道,重新生成yccImage
Mat dstImage = new Mat(); //定义存储结果的Mat变量
CvInvoke.CvtColor(yccImage, dstImage, ColorConversion.YCrCb2Bgr); //从YCrCb转回Bgr颜色空间
//【5】显示结果图
CvInvoke.Imshow("Destination Image", dstImage);
//等待用户按键退出程序
CvInvoke.WaitKey(0);
}
}
}
程序运行截图如下: