直方图是图像处理中一种非常重要的分析工具。直方图主要是根据灰度图像进行统计和绘制的,所以反映的是灰度图像的统计特性。
从直方图的角度对图像进行描述,可以获得很多图像的重要信息。从直方图的角度对图像进行处理,可以达到增强图像显示效果的目的。
一、什么是图像直方图(image histogram)?
先将彩色图像转化为灰度图像,然后把灰度图像上的所有像素点安装像素值的大小和像素值出现的次数,绘制在坐标系中的图,就是直方图。
横坐标X轴的范围是0-255,表示有255个灰度级,x轴左侧的值较小,对应着图像中较暗的区域,x轴右侧的值较大,对应着图像中较亮的区域。有时我们也可以把x轴分箱,分成多个bins。
纵坐标y轴可以是次数也可以是概率值,如果是概率值,y轴的范围就在0-1,如果是次数,就表示灰度值出现的次数。
二、图像直方图的函数
1、Cv2.Split()
- 将 3 通道 BGR 彩色图像分离为 B、G、R 单通道图像。
- 返回值为:Mat[]
Mat[] mats = Cv2.Split(src);
2、Cv2.Normalize()
- 由于图像大小各异,一般我们会对直方图进行归一化处理,让每个灰度比例之和为1。
- 函数原型:
void normalize(InputArray src,OutputArray dst, double alpha=1, doublebeta=0, int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray() )
3、Cv2.CalcHist()
- 计算一组图像的联合密集直方图。有一个重载方法
void CalcHist(Mat[] images,....)
- 方法1:
- Mat[] images
输入单通道图像集合 - int[] channels
图像在集合中对应的通道 : 0 ~ 2 之间 (0,1,2) - InputArray mask
掩膜 输入的InputArray 对象,可以为空,或者输入对应 images[i],要与通道对应 - OutputArray hist
输出计算后的直方图 OutputArray对象。 - int dims
维度 ,单通道为 1 - int[] histSize
直方图的级数,就是把像素分为几个等级。像素大小在 0 ~ 255之间,如果全部输出就是 256个等级。 - float[][] ranges
值域的范围。 - bool uniform = true
是否规范化。(每个bins大小取值等级一致,默认为true) - bool accumulate = false
是否累加(多通道的需要,默认值为 false)
- Mat[] images
三、程序
图像直方图 private void uiButton4_Click(object sender, EventArgs e)
{
//1:首先对图像做一个中值滤波
Mat m1 = new Mat();
Cv2.MedianBlur(src_img, m1, 3); // ksize必须大于1且是奇数
//2:转为灰度图像
Mat m2 = new Mat();
Cv2.CvtColor(src_img, m2, ColorConversionCodes.BGR2GRAY);
//3:直方图
Mat hist = new Mat();
Cv2.CalcHist(new Mat[] { m2 }, new int[] { 0 }, new Mat(), hist, 1, new int[] { 256 }, new Rangef[] { new Rangef(0, 256) });
Cv2.Normalize(hist, hist);
Mat result = new Mat(new OpenCvSharp.Size(256, 400), MatType.CV_8UC3 , new Scalar(0, 0, 0));
for (int i = 0; i < 256; i++)
{
float v = hist.Get<float>(i);
int len = (int)(v * 400);
if (len != 0)
{
Cv2.Line(result, new OpenCvSharp.Point(i , 399), new OpenCvSharp.Point(i , 400 - len), new OpenCvSharp.Scalar(0,255,255), 1, OpenCvSharp.LineTypes.AntiAlias);
}
}
result.SaveImage("d:\\my_result.jpg");
pictureBox1.Image = result.ToBitmap();
}
}
网友评论