文章目录
一、 直方图概述 Overview of histogram
直方图(Histogram),又称质量分布图,是一种统计报告图,由一系列高度不等的纵向条纹或线段表示数据分布的情况。 一般用横轴表示数据类型,纵轴表示分布情况。
直方图是图像处理中的一个有着广泛应用的工具,直方图本质是概率分布的图形化,同时直方图也可以用来表示向量。
二、直方图的建立 Establishment of histogram
下面以一幅分辨率为8*8、8级灰度的图像来介绍如何建立一幅直方图
以Pi(i = 0、1、2、3…7)表示八级灰度每一级的概率,Ni(i = 0、1、2、3…7)表示88共64个像素点中各级灰度出现的次数,则Pi = Ni/(88),即灰度出现的次数对像素点总数的归一化。
由此绘制出的Pi-灰度的关系图就是灰度直方图。横坐标为灰度值,纵坐标为该灰度值出现的概率。
当然一般是以8位表示一个像素点,灰度一般有256级。
从这张直方图上可以很直观地看到,它的灰度值以0、1、2为主,显然是一张偏暗的图片。
对于图像,不光可以建立灰度直方图,也可以自己设计方法建立任意形式的直方图。如可以对RGB图像三个颜色通道分别建立直方图,得到彩色直方图。也可以针对图像的HSV色彩模型,建立HSC直方图。
两个直方图的比较可以使用欧几里德距离,马氏距离等。Opencv中的compareHist函数提供了四种方法:Correlation、Chi-Square,Intersection,Bhattacharyya距离。
可以想象,如果两个直方图的欧几里德距离为零的话,那么就应该是两个完全一样的直方图。
三、直方图的作用 The function of histogram
1)图像匹配
比较两幅图像的直方图,可以得到两幅图像的相似程度。其本质是对比灰度出现的概率是否相似。
在图像匹配的时候,也可以对其他的特征量建立直方图,来进行匹配。
同样的图像直方图显然相同。反之却不一定成立,这是因为直方图只能记录各级灰度出现的概率,却丢失了空间信息。
如下图就是一个明显的反例:
那么为何要对灰度进行归一化呢,假设我们有一张原图和一张对原图进行放大缩小后的图片,两种图片实际上是同一张图片,只是大小不同,它们的直方图理应是相同的。但是如果不仅归一化,仅仅是以各级灰度出现的次数作为纵坐标,由于放大缩小后的图像与原图像素点存在差异,它呈现出来的纵坐标也是不同的,这就导致了两张相同的图片直方图不同,因此要进行归一化。
2)判断成像质量
下面以几张图片作为示例:
3)二值化阈值
在图像二值化的过程中,我们可以通过分析直方图选择一个适当的阈值,把灰度图像转换为二值化图像,通常的目的是分离前景和背景
以一张256级灰度的细胞的图片为例,下面是它的直方图
可以明显地看到,它的直方图呈现双峰性,它的前景分布集中在一个区域,背景分布集中在另一个区域,这时候我们只要选择直方图中的谷值,就能得到较为理想的二值化图像。
四、编程实现 Programming implementation
通过Opencv编程实现读取一张图片计算并显示RGB三通道直方图。
这里用的Opencv版本是4.40。
当然这里可以用Opencv自带的函数calcHist()函数计算直方图,自己写一个算直方图的函数只是为了能够加深对直方图和OpencvMat类的理解。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
#define hist_rgb_width 800
#define hist_rgb_height 400
void Calc_histogram(cv::Mat src)
{
/*定义直方图矩阵
*这里以一个256*3的矩阵存放各个通道各个灰度值的个数
*以数组下标标记灰度值,数组内容为该灰度值的个数
*/
float histogram[256][3] = {
0 };
//定义vector作为三个通道的容器
std::vector<cv::Mat