颜色直方图的计算、显示、处理、对比及反向投影(How to Use Histogram? Calculate, Show, Process, Compare and BackProject)

您所在的位置:网站首页 色彩空间有什么用途和作用 颜色直方图的计算、显示、处理、对比及反向投影(How to Use Histogram? Calculate, Show, Process, Compare and BackProject)

颜色直方图的计算、显示、处理、对比及反向投影(How to Use Histogram? Calculate, Show, Process, Compare and BackProject)

2024-07-12 12:17| 来源: 网络整理| 查看: 265

作者:王先荣

前言    颜色直方图直观的显示了图像在色彩空间的分布状况,本文将讨论在EmguCv及OpenCv中跟直方图相关的一些基本操作,包括:计算、显示、处理、对比及反向投影,并谈谈在实践过程中得到的一些经验。如无特别说明,下文所提的直方图均指颜色直方图。

 

直方图的计算    EmguCv将OpenCv的一系列直方图函数封装到了类DenseHistogram里面,可以用方法Calculate方便的计算图像的直方图。不过值得注意的是,该方法接受的第一个参数是“单通道”图像数组;而一般情况下的图像都是3通道的,在计算之前我们需要用Image.Split方法将其分解成单通道图像,然后选择需要参与直方图计算的通道。下面有几段计算直方图的代码,分别计算单通道(红色)直方图、色调和饱和度直方图。

计算直方图 /// /// 计算直方图(红色) /// private void CalcHistRed() { //计算 int rBins = 256; RangeF rRange = new RangeF(0f, 255f); Image imageSource = new Image((Bitmap)pbSource.Image); Image imageRed = imageSource.Split()[2]; DenseHistogram hist = new DenseHistogram(rBins, rRange); hist.Calculate(new IImage[] { imageRed }, false, null); //显示 pbHistogram.Image = GenerateHistImage(hist).Bitmap; //释放资源 imageSource.Dispose(); imageRed.Dispose(); hist.Dispose(); }

/// /// 计算直方图(色调和饱和度) /// private void CalcHistHs() { //计算 int hBins = 180; RangeF hRange = new RangeF(0f, 179f); //色调的范围在0~180之间 int sBins = 256; RangeF sRange = new RangeF(0f, 255f); Image imageSource = new Image((Bitmap)pbSource.Image); Image imageHsv = imageSource.Convert(); //将色彩空间从BGR转换到HSV Image[] imagesHsv = imageSource.Split(); //分解成H、S、V三部分 DenseHistogram hist = new DenseHistogram(new int[] { hBins, sBins }, new RangeF[] { hRange, sRange }); hist.Calculate(new IImage[] { imagesHsv[0], imagesHsv[1] }, false, null); //显示 pbHistogram.Image = GenerateHistImage(hist).Bitmap; //释放资源 imageSource.Dispose(); imageHsv.Dispose(); foreach (Image image in imagesHsv) image.Dispose(); hist.Dispose(); }

 

直方图的显示    我们可以用以下方式来查看直方图:(1)使用HistogramViewer窗体显示直方图;(2)使用HistogramBox控件显示直方图;(3)用自己写的方法将直方图转换成图像,然后显示出来。这3个方式依次从易到难,不过对直方图的显示控制程度却依次提高。1.HistogramViewer窗体    HistogramViewer窗体的3个静态方法可以很方便的显示直方图,它们的定义如下:    Show(IImage) 显示指定图像的直方图:它会自动为图像的每个通道生成直方图,然后显示一个或者多个一维直方图;    Show(IImage, Int32) 显示指定图像的直方图:除了可以自己指定直方图的区间数目之外,跟前一个方法一样;    Show(DenseHistogram, String) 显示指定的一维直方图:可以在图上显示一个标题,注意这个方法只能显示一维直方图。     HistogramViewer窗体还有一个名为HistogramCtrl的属性,它用来获取窗体内的HistogramBox控件。    下面的代码演示了HistogramViewer的用法:

用HistogramViewer显示直方图 /// /// 计算直方图(RGB) /// private void CalcHistRgb() { //在HistogramViewer中显示直方图 Image imageSource = new Image((Bitmap)pbSource.Image); //直接用HistogranViewer的静态函数Show来查看直方图,不过不能控制行为 HistogramViewer.Show(imageSource, 256); //可以用HistogramViewer对象来显示直方图,有较多的控制 HistogramViewer hv = new HistogramViewer(); hv.Text = "RGB直方图"; hv.ShowInTaskbar = false; hv.HistogramCtrl.GenerateHistograms(imageSource, 256); hv.WindowState = FormWindowState.Maximized; hv.Show(this); //释放资源 imageSource.Dispose(); }

2.HistogramBox控件    HistogramBox控件有4个方法跟直方图有关:    AddHistogram(String, Color, DenseHistogram) 向控件添加一块一维直方图:可以指定标题及绘制的颜色;    ClearHistogram() 移除控件中的所有直方图;    GenerateHistograms(IImage, Int32) 为指定图像的每个通道生成直方图:可以指定直方图的区间数目;    Refresh() 绘制直方图:对控件的直方图进行任何改动之后,都要调用Refresh来重新绘制才行。

用HistogramBox显示直方图 /// /// 计算直方图(色调) /// private void CalcHistHue() { //计算 int hBins = 180; RangeF hRange = new RangeF(0f, 179f); //色调的范围在0~180之间 Image imageSource = new Image((Bitmap)pbSource.Image); Image imageHsv = imageSource.Convert(); //将色彩空间从BGR转换到HSV Image imageHue = imageSource.Split()[0]; //分解Hue部分 DenseHistogram hist = new DenseHistogram(hBins, hRange); hist.Calculate(new IImage[] { imageHue }, false, null); //显示(注意:这里的变量histBox是一个HistogramBox控件的对象) histBox.AddHistogram("色调直方图", Color.FromArgb(255, 0, 0), hist); histBox.Refresh(); //释放资源 imageSource.Dispose(); imageHsv.Dispose(); imageHue.Dispose(); hist.Dispose(); }

 

3.自己写方法将直方图转换成图像    HistogramViewer和HistogramBox很方便,但是它们只能显示一维的直方图,如果要显示二维甚至三维的直方图,那么只有自己写方法了。  

自己写代码显示直方图 //生成直方图图示 private Image GenerateHistImage(DenseHistogram hist) { Image imageHist = null; float minValue, maxValue; int[] minLocations, maxLocations; hist.MinMax(out minValue, out maxValue, out minLocations, out maxLocations); if (hist.Dimension == 1) { int bins = hist.BinDimension[0].Size; int width = bins; int height = 300; imageHist = new Image(width, height, new Bgr(255d, 255d, 255d)); double heightPerTick = 1d * height / maxValue; Bgr color=new Bgr(0d,0d,255d); //遍历每个bin对应的值,并画一条线 for (int i = 0; i 0) hist.Threshold(thresholdValue); //归一化 if (cbNormalize.Checked) hist.Normalize(normalizeFactor); return hist; }

 

    需要注意的是:EMD方式要求先将直方图转换成矩阵:

 

将直方图转换成矩阵 /// /// 将直方图转换成矩阵; /// 注意:只支持1、2、3维直方图 /// /// 直方图 /// 返回矩阵 private Matrix ConvertDenseHistogramToMatrix(DenseHistogram hist) { Matrix matrix = null; if (hist != null) { int cols = hist.Dimension + 1; //矩阵的列数为直方图维数加1 int rows = 1; //矩阵的行数为直方图所有bin的乘积 foreach (MCvMatND.Dimension bin in hist.BinDimension) rows *= bin.Size; //初始化矩阵 matrix = new Matrix(rows, cols); //填充矩阵 if (hist.Dimension == 1) { // 1维直方图 for (int idx0 = 0; idx0


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3