灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其横坐标是灰度级,纵坐标是该灰度出现的频率(像素的个数)。
在opencv中可以通过cvCreateHist()来生成直方图
CvHistogram* cvCreateHist(
int dims,
int* sizes,
int type,
float** ranges=NULL,
int uniform=1
)
dims
//直方图包含的维数
sizes
//数组的长度等于dims,数组中每个整数表示分配给对应维数的的bin的个数
type
//表示存储类型,CV_HIST_ARRAy表示用密集多维矩阵结构存储直方图,CV_HIST_SPARSE表示数据已稀疏矩阵方式存储
ranges=NULL,
//浮点数对的构成的数组,每个浮点数对表示对应维数的bin的区间的上下界
uniform=1
//非0表示均匀直方图,为NULL表示未知,即在后面可以设置。CvHistogram* cvCreateHist(
使用cvCalcHist()函数来计算直方图
void cvCalcHist(
IplImage** image,
CvHistogram* hist,
int accmulate=0,
const CvArr* mask=NULL
)
image //是一个指向数组的IplImage*类型的指针,着允许利用多个图像通道
hist //要计算的直方图
accmulate //非0时,表示直方图hist在读入图像之前没有被清零
mask //如果为非NULL,则只有与mask非零元素对应的像素点会被包含在计算直方图中。
1.单通道图像的直方图
#include "stdafx.h"
#include <highgui.h>
#include <math.h>
#include <cv.h>
int main()
{
IplImage* sourceImage=0;
//以单通道读入图像
if(!(sourceImage=cvLoadImage("YAYA.jpg",0)))
return -1;
int hdims=51; //分配给对应维数的bin的个数
float rangesArray[]={0,255};
float* ranges[]={rangesArray};
float maxValue;
CvHistogram* histogram=0;
histogram=cvCreateHist(1,&hdims,CV_HIST_ARRAY,ranges,1);
IplImage* histImage; //用来显示直方图
histImage=cvCreateImage(cvGetSize(sourceImage),8,3);
cvZero(histImage);
//计算直方图
cvCalcHist(&sourceImage,histogram,0,0);
//获取最大值
cvGetMinMaxHistValue(histogram,0,&maxValue,0,0);
cvConvertScale(histogram->bins,histogram->bins,maxValue?255./maxValue:0,0);
float binsWidth;
binsWidth=histImage->width/hdims;
CvScalar color=CV_RGB(255,255,255);
for(int i=0;i<hdims;i++)
{
double value=(cvGetReal1D(histogram->bins,i)*histImage->height/255);
cvRectangle(histImage,cvPoint(i*binsWidth,histImage->height),cvPoint((i+1)*binsWidth,(int)(histImage->height-value)),color,1,8,0);
}
//显示
cvNamedWindow("sourceImage",0);
cvNamedWindow("histImage",0);
cvShowImage("sourceImage",sourceImage);
cvShowImage("histImage",histImage);
//释放资源
cvDestroyAllWindows();
cvReleaseImage(&sourceImage);
cvReleaseImage(&histImage);
cvReleaseHist(&histogram);
cvWaitKey(-1);
return 0;
}
运行结果:
多通道图像的直方图
因为ccCalHist()只接受单通道图像,所以在调用cvCalcHist()之前,首先用cvSplit()将多通道图像分解为单通道图像。
#include "stdafx.h"
#include <highgui.h>
#include <math.h>
#include <cv.h>
int main()
{
IplImage* sourceImage=0;
if(!(sourceImage=cvLoadImage("YAYA.jpg",1)))
return -1;
IplImage* hsvImage=cvCreateImage(cvGetSize(sourceImage),8,3);
cvCvtColor(sourceImage,hsvImage,CV_BGR2HSV);
IplImage* h_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
IplImage* s_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
IplImage* v_plane=cvCreateImage(cvGetSize(sourceImage),8,1);
cvSplit(hsvImage,h_plane,s_plane,v_plane,0);
int h_bins=30,s_bins=32;
CvHistogram* histogram;
{
int hist_size[]={h_bins,s_bins};
float h_ranges[]={0,180};
float s_ranges[]={0,255};
float* ranges[]={h_ranges,s_ranges};
histogram=cvCreateHist(
2,
hist_size,
CV_HIST_ARRAY,
ranges,
1
);
}
IplImage* planes[]={h_plane,s_plane};
cvCalcHist(planes,histogram,0,0);
cvNormalizeHist(histogram,1.0);
int scale=10;
IplImage* histImage=cvCreateImage(
cvSize(h_bins*scale,s_bins*scale),8,3);
cvZero(histImage);
float maxValue;
cvGetMinMaxHistValue(histogram,0,&maxValue,0,0);
for(int h=0;h<h_bins;h++)
for(int s=0;s<s_bins;s++)
{
float binValue=cvQueryHistValue_2D(histogram,h,s);
int intensity=cvRound(binValue*255./maxValue);
cvRectangle(
histImage,
cvPoint(h*scale,s*scale),
cvPoint((h+1)*scale-1,(s+1)*scale-1),
CV_RGB(intensity,intensity,intensity),
CV_FILLED
);
}
cvNamedWindow("hsvImage",1);
cvNamedWindow("histImage",1);
cvShowImage("hsvImage",hsvImage);
cvShowImage("histImage",histImage);
cvWaitKey(-1);
cvDestroyAllWindows();
cvReleaseImage(&sourceImage);
cvReleaseImage(&histImage);
cvReleaseHist(&histogram);
return 0;
}
运行结果:
直方图的相似度
计算直方图相似度的函数如下:
double cvCompareHist(
const CvHistogram* hist1,
const CvHistogram* hist2,
int method; //距离标准
)
method的取值有:
CV_COMP_CORREL 完全匹配为1,完全不匹配为-1,数值越大越匹配
CV_COMP_CHISQR 低分比高分匹配的程度高,完全匹配的值为0,完全不匹配为无限值
CV_COMP_INTERSECT 高分表示好匹配,低分表示坏匹配
CV_COMP_BHATTACHARYYA 低分表示好匹配,高分表示换匹配。完全匹配为0,完全不匹配为0.
#include "stdafx.h"
#include <highgui.h>
#include <math.h>
#include <cv.h>
using namespace std;
//对比两个直方图的相似度
int main()
{
IplImage* templateImage=cvLoadImage("YAYA.jpg");
if(!templateImage)
return -1;
IplImage* grayImage=cvCreateImage(cvGetSize(templateImage),8,1);
cvCvtColor(templateImage,grayImage,CV_BGR2GRAY);
//首先加载图片,然后将图片变为灰度图
int hist_size=51;
float range[]={0,255};
float* ranges[]={range};
CvHistogram* histogram;
histogram=cvCreateHist(
1,
&hist_size, //size 元素为对应bin的个数
CV_HIST_ARRAY,
ranges,
1
);
cvCalcHist(&grayImage,histogram,0,0);
IplImage* compareImage=cvLoadImage("YAYA2.jpg");
if(!compareImage)
return -1;
IplImage* compareGrayImage=cvCreateImage(cvGetSize(compareImage),8,1);
cvCvtColor(compareImage,compareGrayImage,CV_BGR2GRAY);
//首先加载图片,然后将图片变为灰度图
CvHistogram* compareHistogram;
compareHistogram=cvCreateHist(
1,
&hist_size,
CV_HIST_ARRAY,
ranges,
1
);
cvCalcHist(&compareGrayImage,compareHistogram,0,0);
//对直方图进行归一化操作
cvNormalizeHist(histogram,1);
cvNormalizeHist(compareHistogram,1);
//计算匹配系数
double degree=cvCompareHist(histogram,compareHistogram,
CV_COMP_CHISQR);
cout<<degree<<endl;
cvWaitKey(10000000);
cvDestroyAllWindows();
cvReleaseImage(&templateImage);
cvReleaseImage(&grayImage);
cvReleaseImage(&compareImage);
cvReleaseImage(&compareGrayImage);
cvReleaseHist(&compareHistogram);
cvReleaseHist(&histogram);
return 0;
}