灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其横坐标是灰度级,纵坐标是该灰度出现的频率(像素的个数)。
在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; }
Reference
《学习opencv》