1.把彩***像分成3个图像(cvSplit)
2.创建直方图并且分配内存(CvHistogram* hist=cvCreateHist)
3.读取图像的直方图,把数据存放在直方图结构体中(cvCapcHist)
4.读取直方图结构体中每个值的点数(cvQueryHistValue_1D)
5.描点,画图(cvPoint,cvFillConvexPoly)
直方图的其它操作:
1.cvNorMalizeHist(CvHistogram* hist,double factor)
归一化直方图,factor表示直方图归一化后的数字
2.cvThreshHist(CvHistogram* hist,double factor);
factor是一个开关阀值,小于该阀值的各个bin的值都被设为0
3.void cvCopyHist(const CvHistogram* src,CvHistogram** dst);
复制一个直方图的信息到另一个直方图,如果设置*dst为NULL,那么生成一个与src一样大小的新直方图,*dst被分配给一个指向新分配的直方图的指针
4.cvGetMinMaxHistValue(const CvHistogram* hist,float* min_value,float* max_value,int min_idx=NULL,int max_idx=NULL)
求直方图hist中的最小最大值及其索引
5.cvCalcHist(IplImage** image,CvHistogram* hist,int accumulate=0,const CvArr* mask=NULL);
从图像中自动计算直方图,图像要转换为单通道图像,accumulate如果非零,表示直方图hist在读入图像之前没有被清零,允许cvCalcHist()在一个数据采集循环中被多次调用,mask如果非零,则只有与mask非零元素对应
6.double cvCompareHist(const CvHistogram* hist1,const CvHistogram* hist2,int method)
比较两个大小相同的直方图的相似度
程序1(自己):
#include "cv.h" #include "cxcore.h" #include "highgui.h" IplImage* cvDrawHist(IplImage *image,int x=1,int y=1) { int dim=1; int size=256; float range[]={0,255}; float *ranges[]={range}; //数组的个数等于维数,这里是一维 CvHistogram *hist=cvCreateHist(dim,&size,CV_HIST_ARRAY,ranges,1); cvClearHist(hist); cvCalcHist(&image,hist); float max=0; cvGetMinMaxHistValue(hist,NULL,&max); IplImage *HistImage=cvCreateImage(cvSize(256*x,64*y),8,1); cvZero(HistImage); CvPoint pts[5]; for(int i=0;i<255;i++) { float num=cvQueryHistValue_1D(hist,i); float nextnum=cvQueryHistValue_1D(hist,i+1); pts[0]=cvPoint(i*x,0); pts[1]=cvPoint((i+1)*x,0); pts[2]=cvPoint((i+1)*x,64*y-nextnum/max*64*y); pts[3]=cvPoint(i*x,64*y-num/max*64*y); pts[4]=cvPoint(i*x,0); cvFillConvexPoly(HistImage,pts,5,cvScalar(255)); } return HistImage; } void main() { IplImage *src=cvLoadImage("c:\\1.jpg"); cvNamedWindow("src"); cvShowImage("src",src); IplImage *red=cvCreateImage(cvGetSize(src),8,1); IplImage *green=cvCreateImage(cvGetSize(src),8,1); IplImage *blue=cvCreateImage(cvGetSize(src),8,1); cvSplit(src,red,green,blue,NULL); cvNamedWindow("red"); cvNamedWindow("green"); cvNamedWindow("blue"); cvShowImage("red",red); cvShowImage("green",green); cvShowImage("blue",blue); IplImage *r_hist=cvDrawHist(red); IplImage *b_hist=cvDrawHist(blue); IplImage *g_hist=cvDrawHist(blue); cvNamedWindow("r_hist"); cvNamedWindow("g_hist"); cvNamedWindow("b_hist"); cvShowImage("r_hist",r_hist); cvShowImage("g_hist",b_hist); cvShowImage("b_hist",g_hist); cvWaitKey(0); cvDestroyWindow("red"); cvReleaseImage(&red); cvDestroyWindow("green"); cvReleaseImage(&green); cvDestroyWindow("blue"); cvReleaseImage(&blue); cvDestroyWindow("r_hist"); cvReleaseImage(&r_hist); cvDestroyWindow("g_hist"); cvReleaseImage(&g_hist); cvDestroyWindow("b_hist"); cvReleaseImage(&b_hist); }
程序2:
#include "cv.h" #include "cxcore.h" #include "highgui.h" //绘制直方图 IplImage* DrawHistogram(CvHistogram* hist , float scaleX = 1 , float scaleY = 1) { //获取直方图中极大值 float histMax = 0; cvGetMinMaxHistValue(hist , 0 ,&histMax ,0 ,0); //创建图像 该图像用于显示直方图 IplImage* imgHist = cvCreateImage(cvSize(256*scaleX , 64*scaleY) , 8 ,1); //图像置零 cvZero(imgHist); //依次绘制直方图的bin for(int i=0;i<255;i++) { //获取直方图的值 float histValue = cvQueryHistValue_1D(hist , i); float nextValue = cvQueryHistValue_1D(hist , i+1); //获取四边形的四个点的坐标 详情请观看视频的讲解 CvPoint pt1 = cvPoint( i*scaleX , 64*scaleY); CvPoint pt2 = cvPoint( (i+1)*scaleX , 64*scaleY); CvPoint pt3 = cvPoint( (i+1)*scaleX , (64 - (nextValue/histMax)*64) *scaleY ); CvPoint pt4 = cvPoint ( i*scaleX , (64 - (histValue/histMax)*64) *scaleY ); int numPts = 5; CvPoint pts[5]; pts[0] = pt1; pts[1] = pt2; pts[2] = pt3; pts[3] = pt4; pts[4] = pt1; //填充四边形 cvFillConvexPoly(imgHist , pts ,numPts , cvScalar(255)); } return imgHist; } int main(int argc, char* argv[]) { //加载图像 IplImage* src = cvLoadImage("c:\\1.jpg"); cvNamedWindow("sr"); cvShowImage("sr" , src); int dims = 1; // 一维直方图 int size =256; //bin的个数 float range[] = {0,255}; //取值范围 float* ranges[] = {range}; CvHistogram* hist; //创建直方图 hist = cvCreateHist(dims , &size , CV_HIST_ARRAY , ranges , 1 ); //清空直方图 cvClearHist(hist); //给B G R 三个通道的图像分配空间 IplImage* imgRed = cvCreateImage(cvGetSize(src) , 8 ,1); IplImage* imgGreen = cvCreateImage(cvGetSize(src) , 8 ,1); IplImage* imgBlue = cvCreateImage(cvGetSize(src) , 8 ,1); //将图像src 分解成B G R 三个通道 cvSplit(src , imgBlue , imgGreen , imgRed , NULL); //计算B通道 直方图 cvCalcHist(&imgBlue , hist , 0 , 0 ); //绘制B通道直方图 结果保存在histBlue IplImage* histBlue = DrawHistogram(hist); //将B通道的直方图数据清空 cvClearHist(hist); //计算G通道直方图 cvCalcHist(&imgGreen , hist , 0 , 0 ); //绘制G通道直方图 histGreen IplImage* histGreen = DrawHistogram(hist); //将G通道的直方图数据清空 cvClearHist(hist); //计算R通道 直方图 cvCalcHist(&imgRed , hist , 0 , 0 ); //绘制R通道直方图 histRed IplImage* histRed = DrawHistogram(hist); //将R通道的直方图数据清空 cvClearHist(hist); cvNamedWindow("B"); cvNamedWindow("G"); cvNamedWindow("R"); cvShowImage("B" , histBlue); cvShowImage("G" , histGreen); cvShowImage("R" , histRed); cvWaitKey(0); //释放资源 //(1) 释放源图像 cvReleaseImage(&src); //(2) 释放三个通道的图像 cvReleaseImage(&imgRed); cvReleaseImage(&imgGreen); cvReleaseImage(&imgBlue); //(3)释放三个通道直方图 cvReleaseImage(&histBlue); cvReleaseImage(&histGreen); cvReleaseImage(&histRed); //(4)释放直方图空间 cvReleaseHist(&hist); return 0; }