【Emgu CV教程】8.1、计算直方图

本文介绍了直方图的概念,它是图像灰度值分布的统计表,以及EmguCV中的直方图均衡化函数EqualizeHist的使用方法。通过实例展示了如何计算直方图并调整图像对比度。
摘要由CSDN通过智能技术生成


一、介绍

1.什么叫直方图

之前介绍了一个直方图均衡化的函数,从这篇开始将联系用6篇文章来介绍一下直方图的相关概念和函数的应用。

直方图,是指对整个图像像在灰度范围内的像素值(0~255)统计出现频率次数,据此生成的一个统计表,称为图像直方图。它是一个统计学概念,可以反映图像灰度的分布情况。假如说有某张图片,直方图是下面这样的:
在这里插入图片描述

1、X轴代表像素值,范围是0 - 255;
2、Y轴代表某个像素值在图像中出现的次数。比如0这个值,大概出现了5000次左右;35这个值,出现了大概7000次。

根据这个直方图,我们就能得出这张图片整体不是太亮,因为像素值在 0 - 100这个区间出现的次数最多,也就是图像里面多数像素值都是在 0 - 100之间。100 - 245 的像素值不太多,大于245的像素值倒是有一部分。

因此:
1、直方图是一种像素值分布的图形表达方式。
2、它可以统计每一个值所出现的次数。
3、不同的图形的直方图可能是相同的。

2.直方图计算的函数

Emgu CV里面直方图均衡化的函数是EqualizeHist(),函数定义如下:

public static void CalcHist(
	IInputArrayOfArrays images, // 输入图像,
	int[] channels, // 需要统计直方图的第几通道
	IInputArray mask, // 掩码图
	IOutputArray hist, // 直方图计算的输出值
	int[] histSize, // 直方图横坐标的区间数
	float[] ranges, // 一个列表,表示参与直方图计算的每个维度的数值范围,即横坐标的最小值和最大值,一般都是[0,256]
	bool accumulate // 是否累积计算标记,一般都选false
)

说明:histSize这个参数代表直方图横坐标的区间数。如果是256,则它会将横坐标分为256份,也就是每一个像素值都要统计。如果是10,则它会将横坐标分为10份,然后统计每个区间的像素点总和。比如说第一个区间就是[0,25],第二份就是[26,51]。

二、举例

1.原始素材

原始素材定义为srcMat,如下:
在这里插入图片描述

2.代码

直方图均衡化代码如下:

Mat tempMat = srcMat.Clone(); // 深拷贝
Mat grayImg = new Mat();
CvInvoke.CvtColor(tempMat, grayImg, ColorConversion.Bgr2Gray);

// 定义输出的目标直方图
Mat histogram = new Mat();

// 需要统计的通道索引
int[] channelIndex = new int[] { 0 };

// 每一维数值的统计范围
float[] ranges = new float[] { 0, 256 };

// 直方图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和。也就是bins,表示这个直方图分成多少份(即多少个直方柱)
int[] hitSize = new int[] { 256 };

// 输入的Mat或Mat数组,并将灰度图赋值给它
VectorOfMat vMatImgs = new VectorOfMat();
vMatImgs.Push(grayImg);

// 直方图计算
CvInvoke.CalcHist(vMatImgs, channelIndex, new Mat(), histogram, hitSize, ranges, false);

// 找到直方图最大值
double minGrayValue = 0;
double maxGrayValue = 0;
System.Drawing.Point minLocationBlue = new System.Drawing.Point();
System.Drawing.Point maxLocationBlue = new System.Drawing.Point();
CvInvoke.MinMaxLoc(histogram, ref minGrayValue, ref maxGrayValue, ref minLocationBlue, ref maxLocationBlue);

// 画直方图,X轴上4个像素代表一个区间,共有256个区间
int width = 1024;
int height = 512;
Mat histShow = Mat.Zeros(height, width, DepthType.Cv8U, 1);
Image<Gray, int> histShowImage = histogram.ToImage<Gray, int>();
int grayValue = 0;
for (int i = 0; i < 256; i++)
{
    grayValue = histShowImage.Data[i, 0, 0];
    grayValue = (int)(512 * grayValue / maxGrayValue);  // 绘制高度
    CvInvoke.Rectangle(histShow, new Rectangle((4 * i) - 3, 512 - grayValue, 4, 512), new MCvScalar(255, 0, 0), -1, LineType.EightConnected, 0);
}

CvInvoke.Imshow("Gray image histogram, " + histShow.Size.ToString(), histShow);

3.运行结果

在这里插入图片描述

输出一张宽1024,高度为512的图片,横坐标区间数是256,也就是0到255每个值都单独统计。从原始图片也能看出来,特别亮的就是一个灯泡,而且灯泡的面积不大,剩余多数像素值都是在30到90这个区间内的。

假如上面的代码内,hitSize 参数值改变

int[] hitSize = new int[] { 10 };

像素值分成10个区间,得到的直方图应该是这样的。
在这里插入图片描述


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

  • 19
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值