OpenCV 图像直方图 - 技术文档 (C#)
目录
- 引言
- 环境准备
- 计算灰度图像直方图
- 显示灰度图像直方图
- 计算彩色图像直方图
- 显示彩色图像直方图
- 结论
1. 引言
图像直方图是描述图像中像素值分布的统计图。通过图像直方图,可以分析图像的对比度、亮度和灰度分布等信息。本技术文档介绍如何使用OpenCV结合C#计算和显示图像直方图,包括灰度图像和彩色图像的直方图。
2. 环境准备
在开始之前,请确保已安装以下软件和库:
- Visual Studio 或其他C# IDE
- OpenCV库
- Emgu CV库(OpenCV的C#封装)
安装Emgu CV库:
Install-Package Emgu.CV
3. 计算灰度图像直方图
使用CvInvoke.CalcHist
函数计算灰度图像的直方图。
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
class Program
{
static void Main()
{
// 读取图像
Mat image = CvInvoke.Imread("path_to_image.jpg", ImreadModes.Grayscale);
// 计算灰度图像直方图
VectorOfMat images = new VectorOfMat(image);
Mat hist = new Mat();
CvInvoke.CalcHist(images, new int[] { 0 }, null, hist, new int[] { 256 }, new float[] { 0, 256 }, false);
// 归一化直方图
CvInvoke.Normalize(hist, hist, 0, 255, NormType.MinMax);
}
}
4. 显示灰度图像直方图
使用Matplotlib绘制并显示灰度图像的直方图。
using System;
using System.Drawing;
using Emgu.CV;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
using Emgu.CV.Util;
class Program
{
static void Main()
{
// 读取图像
Mat image = CvInvoke.Imread("path_to_image.jpg", ImreadModes.Grayscale);
// 计算灰度图像直方图
VectorOfMat images = new VectorOfMat(image);
Mat hist = new Mat();
CvInvoke.CalcHist(images, new int[] { 0 }, null, hist, new int[] { 256 }, new float[] { 0, 256 }, false);
CvInvoke.Normalize(hist, hist, 0, 255, NormType.MinMax);
// 创建直方图图像
int histWidth = 512;
int histHeight = 400;
int binWidth = (int)((double)histWidth / 256);
Mat histImage = new Mat(histHeight, histWidth, DepthType.Cv8U, 1);
histImage.SetTo(new MCvScalar(255));
for (int i = 1; i < 256; i++)
{
CvInvoke.Line(histImage,
new Point(binWidth * (i - 1), histHeight - (int)hist.GetData().GetValue(i - 1)),
new Point(binWidth * i, histHeight - (int)hist.GetData().GetValue(i)),
new MCvScalar(0), 2, LineType.EightConnected, 0);
}
// 显示结果
CvInvoke.Imshow("Gray Image", image);
CvInvoke.Imshow("Gray Histogram", histImage);
CvInvoke.WaitKey(0);
CvInvoke.DestroyAllWindows();
}
}
5. 计算彩色图像直方图
分别计算彩色图像中每个通道的直方图。
class Program
{
static void Main()
{
// 读取图像
Mat image = CvInvoke.Imread("path_to_image.jpg", ImreadModes.Color);
// 分割图像通道
VectorOfMat bgrPlanes = new VectorOfMat();
CvInvoke.Split(image, bgrPlanes);
// 计算每个通道的直方图
Mat bHist = new Mat();
Mat gHist = new Mat();
Mat rHist = new Mat();
int histSize = 256;
float[] histRange = { 0, 256 };
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[0]), new int[] { 0 }, null, bHist, new int[] { histSize }, histRange, false);
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[1]), new int[] { 0 }, null, gHist, new int[] { histSize }, histRange, false);
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[2]), new int[] { 0 }, null, rHist, new int[] { histSize }, histRange, false);
// 归一化直方图
CvInvoke.Normalize(bHist, bHist, 0, 255, NormType.MinMax);
CvInvoke.Normalize(gHist, gHist, 0, 255, NormType.MinMax);
CvInvoke.Normalize(rHist, rHist, 0, 255, NormType.MinMax);
}
}
6. 显示彩色图像直方图
分别绘制并显示彩色图像中每个通道的直方图。
class Program
{
static void Main()
{
// 读取图像
Mat image = CvInvoke.Imread("path_to_image.jpg", ImreadModes.Color);
// 分割图像通道
VectorOfMat bgrPlanes = new VectorOfMat();
CvInvoke.Split(image, bgrPlanes);
// 计算每个通道的直方图
Mat bHist = new Mat();
Mat gHist = new Mat();
Mat rHist = new Mat();
int histSize = 256;
float[] histRange = { 0, 256 };
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[0]), new int[] { 0 }, null, bHist, new int[] { histSize }, histRange, false);
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[1]), new int[] { 0 }, null, gHist, new int[] { histSize }, histRange, false);
CvInvoke.CalcHist(new VectorOfMat(bgrPlanes[2]), new int[] { 0 }, null, rHist, new int[] { histSize }, histRange, false);
// 归一化直方图
CvInvoke.Normalize(bHist, bHist, 0, 255, NormType.MinMax);
CvInvoke.Normalize(gHist, gHist, 0, 255, NormType.MinMax);
CvInvoke.Normalize(rHist, rHist, 0, 255, NormType.MinMax);
// 创建直方图图像
int histWidth = 512;
int histHeight = 400;
int binWidth = (int)((double)histWidth / histSize);
Mat histImage = new Mat(histHeight, histWidth, DepthType.Cv8U, 3);
histImage.SetTo(new MCvScalar(255, 255, 255));
for (int i = 1; i < histSize; i++)
{
CvInvoke.Line(histImage,
new Point(binWidth * (i - 1), histHeight - (int)bHist.GetData().GetValue(i - 1)),
new Point(binWidth * i, histHeight - (int)bHist.GetData().GetValue(i)),
new MCvScalar(255, 0, 0), 2, LineType.EightConnected, 0);
CvInvoke.Line(histImage,
new Point(binWidth * (i - 1), histHeight - (int)gHist.GetData().GetValue(i - 1)),
new Point(binWidth * i, histHeight - (int)gHist.GetData().GetValue(i)),
new MCvScalar(0, 255, 0), 2, LineType.EightConnected, 0);
CvInvoke.Line(histImage,
new Point(binWidth * (i - 1), histHeight - (int)rHist.GetData().GetValue(i - 1)),
new Point(binWidth * i, histHeight - (int)rHist.GetData().GetValue(i)),
new MCvScalar(0, 0, 255), 2, LineType.EightConnected, 0);
}
// 显示结果
CvInvoke.Imshow("Original Image", image);
CvInvoke.Imshow("Color Histogram", histImage);
CvInvoke.WaitKey(0);
CvInvoke.DestroyAllWindows();
}
}
7. 结论
通过以上操作,我们可以计算和显示图像的灰度直方图和彩色直方图。OpenCV结合Emgu CV提供了强大的直方图计算和绘制功能,可以满足
各种图像分析和处理需求。更多高级操作和应用请参考OpenCV和Emgu CV官方文档。
附录
- OpenCV 官方文档: https://opencv.org/
- Emgu CV 官方文档: https://www.emgu.com/wiki/index.php/Main_Page
- GitHub: https://github.com/emgucv/emgucv