在分析图像的时候我们经常会用直方图来表示各种色彩分布、边缘梯度、分布概率等等事情。所谓的直方图就是对数据进行统计。
下面介绍一下直方图常用的函数
创建直方图
CvHistogram* cvCreateHist(
int dims, //直方图维数
int* sizes, //维数尺寸
int type, //直方图的形式
float** ranges=null, //取值的上下界
int uniform=1 //判断直方图是否均匀
)
CvHistogram是直方图的数据结构
首先要了解直方图里bin的含义。对数据进行统计的统计值会组织到事先定义好的bin中,bin的数值是从数据中计算出特征的统计量。看了之后你可能还是不太懂,没关系先放着继续往下看。
dims:表示直方图的维数。
为了更好的理解这个函数,我先说明ranges的意思,ranges:表示灰度级取值的上下界,则在直方图里显示的横坐标的范围是定义的上下界。
uniform:表示直方图的类型,非0值表示均匀直方图,0表示不均匀直方图。均匀就是将ranges平均分配,即直方图里每一段矩形的宽是一样的。
sizes:为整数数组,数组的长度等于dims,即一维直方图只有一个值,二维直方图有两个值存放在数组里。数组中的每一个整数表示分配给对应维数的bin的个数。例如ranges的上下界分别设置为0和20,相应维数的size等于5,并且是均匀直方图,则bin将被指定为[0,4]、[4,8]、[8,12]、[12,16]、[16,20]。如果是非均匀直方图,在size等于5的情况下如设置相应的区间(0,6,8,10,14,20),则bin将被指定为[0,6]、[6,8]、[8,10]、[10,14]、[14,20]。
type:两种形式。CV_HIST_ARRAY用来表示使用密集多维矩阵结构存储多维直方图。CV_HIST_SPARSE表示数据用稀疏矩阵存储。
直方图归一化
cvNormalizeHist(CvHistogram* hist, double factor)
hist表示直方图,factor表示直方图归一化后的数值,通常为1
直方图最大值和最小值
void cvGetMinMaxHistValue(
const CvHistogram* hist, //直方图
float* min_value, //最小值
float* max_value, //最大值
int* min_idx=NULL, //最小值索引值
int* min_idx=NULL, //最大值索引值
)
hist为指定直方图,*min_value和*max_value设置为最小值和最大值,剩下的两个参数是可选的,如果不是NULL的指针,则返回最小和最大值的索引值,参数min_idx和max_idx被设为指向一个整数数组的指针,我将其理解为指向的是上面介绍过的sizes,假如一个直方图里有很多的bin值都是最值,则返回最小索引的bin。
计算直方图
void cvCalcHist(
IplImage** image, //输入图像
CvHistogram* hist, //直方图
int accumulate=0, //判断直方图在读入图像之前是够清零
const CvArr* mask=NULL, //可选的布尔变量
)
此函数所接受的图像都被要求为单通道图像,主要是为了避免要确定多通道图像的混淆,包含多通道的多个图像需要确定谁在哪儿用这些图像的哪个通道
直方图绘制的思路:如果是单通道图像,利用cvCreateHist来创建直方图,用CalcHist来计算直方图,cvNormalizeHist来进行直方图归一化,接着创建一幅放直方图的图像,用cvGetMinMaxHistValue来统计最小最大值,然后在创建的图像里绘制直方图,调用cvRectangle来画矩形。
一维直方图代码如下:
#include"cv.h"
#include"highgui.h"
int main()
{
IplImage * src = cvLoadImage("D://321.jpg");
IplImage* gray_plane = cvCreateImage(cvGetSize(src), 8, 1);
cvCvtColor(src, gray_plane, CV_BGR2GRAY); //RGB图像转换成灰度图
int hist_size = 256; //直方图尺寸
int hist_height = 256;
float range[] = { 0, 255 }; //灰度级的范围
float* ranges[] = { range };
CvHistogram* gray_hist = cvCreateHist(1, &hist_size, CV_HIST_ARRAY, ranges, 1); //创建一维直方图,统计图像在[0 255]像素的均匀分布
cvCalcHist(&gray_plane, gray_hist, 0, 0); //计算灰度图像的一维直方图 此函数被要求为单通道图像
cvNormalizeHist(gray_hist, 1.0); //归一化直方图
int scale = 2; //比例系数
IplImage* hist_image = cvCreateImage(cvSize(hist_size*scale, hist_height), 8, 3);//创建一张一维直方图的图,横坐标为灰度级,纵坐标为像素个数(*scale)
cvZero(hist_image);
float max_value = 0;
cvGetMinMaxHistValue(gray_hist, 0, &max_value, 0, 0); //统计直方图中的最大直方块
//分别将每个直方块的值绘制到图中
for (int i = 0; i<hist_size; i++)
{
float bin_val = cvQueryHistValue_1D(gray_hist, i); //像素i的概率 cvQueryHistValue_1D返回的是浮点数
int intensity = cvRound(bin_val*hist_height / max_value); //要绘制的高度 cvRound:对数进行四舍五入 返回整型
cvRectangle(hist_image,
cvPoint(i*scale, hist_height - 1),
cvPoint((i + 1)*scale - 1, hist_height - intensity),
CV_RGB(255, 255, 255)); //用白色绘制矩形
}
cvNamedWindow("GraySource", 1);
cvShowImage("GraySource", gray_plane);
cvNamedWindow("H-S Histogram", 1);
cvShowImage("H-S Histogram", hist_image);
cvWaitKey(0);
}