下面用两种方法实现直方图的计算和绘制,其一用自己实现计算直方图,其二利用OpenCV提供的库函数计算直方图。代码和算法不难,适合OpenCV初学者学习之用。如有疏漏错误之处,还请各路方家指出。下面使用的测试图是标准的lena图。
代码之一
- #include <cv.h>
- #include <highgui.h>
- #pragma comment( lib, "cv.lib" )
- #pragma comment( lib, "cxcore.lib" )
- #pragma comment( lib, "highgui.lib" )
- int main()
- {
- IplImage* src=cvLoadImage("lena.jpg",0);
- int width=src->width;
- int height=src->height;
- int step=src->widthStep;
- uchar* data=(uchar *)src->imageData;
- int hist[256]={0};
- for(int i=0;i<height;i++)
- {
- for(int j=0;j<width;j++)
- {
- hist[data[i*step+j]]++;
- }
- }
- int max=0;
- for(i=0;i<256;i++)
- {
- if(hist[i]>max)
- {
- max=hist[i];
- }
- }
- IplImage* dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(dst,cvScalarAll(255),0);
- double bin_width=(double)dst->width/256;
- double bin_unith=(double)dst->height/max;
- for(i=0;i<256;i++)
- {
- CvPoint p0=cvPoint(i*bin_width,dst->height);
- CvPoint p1=cvPoint((i+1)*bin_width,dst->height-hist[i]*bin_unith);
- cvRectangle(dst,p0,p1,cvScalar(0,255),-1,8,0);
- }
- cvNamedWindow("src",1);
- cvShowImage("src",src);
- cvNamedWindow("dst",1);
- cvShowImage("dst",dst);
- cvWaitKey(0);
- cvDestroyAllWindows();
- cvReleaseImage(&src);
- cvReleaseImage(&dst);
- return 0;
- }
代码效果如下
代码之二
- #include <cv.h>
- #include <highgui.h>
- #pragma comment( lib, "cv.lib" )
- #pragma comment( lib, "cxcore.lib" )
- #pragma comment( lib, "highgui.lib" )
- int main()
- {
- IplImage* src=cvLoadImage("lena.jpg",0);
- int size=256;
- float range[]={0,255};
- float* ranges[]={range};
- CvHistogram* hist=cvCreateHist(1,&size,CV_HIST_ARRAY,ranges,1);
- cvCalcHist(&src,hist,0,NULL);
- float max=0;
- cvGetMinMaxHistValue(hist,NULL,&max,NULL,NULL);
- IplImage* dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(dst,cvScalarAll(255),0);
- double bin_width=(double)dst->width/size;
- double bin_unith=(double)dst->height/max;
- for(int i=0;i<size;i++)
- {
- CvPoint p0=cvPoint(i*bin_width,dst->height);
- CvPoint p1=cvPoint((i+1)*bin_width,dst->height-cvGetReal1D(hist->bins,i)*bin_unith);
- cvRectangle(dst,p0,p1,cvScalar(0,255),-1,8,0);
- }
- cvNamedWindow("src",1);
- cvShowImage("src",src);
- cvNamedWindow("dst",1);
- cvShowImage("dst",dst);
- cvWaitKey(0);
- cvDestroyAllWindows();
- cvReleaseImage(&src);
- cvReleaseImage(&dst);
- return 0;
- }
代码效果如下
可见上面两种方法的结果并无明显的差异。
通过复用上面的代码。我们可以得到彩色图像各通道的直方图,代码如下
- #include <cv.h>
- #include <highgui.h>
- #pragma comment( lib, "cv.lib" )
- #pragma comment( lib, "cxcore.lib" )
- #pragma comment( lib, "highgui.lib" )
- int main()
- {
- IplImage* src=cvLoadImage("lena.jpg",1);
- IplImage* r=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
- IplImage* g=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
- IplImage* b=cvCreateImage(cvGetSize(src), IPL_DEPTH_8U, 1);
- cvSplit(src,b,g,r,NULL);
- IplImage* gray = cvCreateImage(cvGetSize(src),8,1);
- cvCvtColor(src,gray,CV_BGR2GRAY);
- int size=256;
- float range[]={0,255};
- float* ranges[]={range};
-
- CvHistogram* r_hist = cvCreateHist(1,&size,CV_HIST_ARRAY,ranges,1);
- CvHistogram* g_hist = cvCreateHist(1,&size,CV_HIST_ARRAY,ranges,1);
- CvHistogram* b_hist = cvCreateHist(1,&size,CV_HIST_ARRAY,ranges,1);
- CvHistogram* hist = cvCreateHist(1,&size,CV_HIST_ARRAY,ranges,1);
- cvCalcHist(&r,r_hist,0,NULL);
- IplImage* r_dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(r_dst,cvScalarAll(255),0);
- float r_max=0;
- cvGetMinMaxHistValue(r_hist,NULL,&r_max,NULL,NULL);
- double r_bin_width=(double)r_dst->width/size;
- double r_bin_unith=(double)r_dst->height/r_max;
- for(int i=0;i<size;i++)
- {
- CvPoint p0=cvPoint(i*r_bin_width,r_dst->height);
- CvPoint p1=cvPoint((i+1)*r_bin_width,r_dst->height-cvGetReal1D(r_hist->bins,i)*r_bin_unith);
- cvRectangle(r_dst,p0,p1,cvScalar(255,0,0),-1,8,0);
- }
- cvCalcHist(&g,g_hist,0,NULL);
- IplImage* g_dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(g_dst,cvScalarAll(255),0);
- float g_max=0;
- cvGetMinMaxHistValue(g_hist,NULL,&g_max,NULL,NULL);
- double g_bin_width=(double)g_dst->width/size;
- double g_bin_unith=(double)g_dst->height/g_max;
- for(i=0;i<size;i++)
- {
- CvPoint p0=cvPoint(i*g_bin_width,g_dst->height);
- CvPoint p1=cvPoint((i+1)*g_bin_width,g_dst->height-cvGetReal1D(g_hist->bins,i)*g_bin_unith);
- cvRectangle(g_dst,p0,p1,cvScalar(0,255,0),-1,8,0);
- }
- cvCalcHist(&b,b_hist,0,NULL);
- IplImage* b_dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(b_dst,cvScalarAll(255),0);
- float b_max=0;
- cvGetMinMaxHistValue(b_hist,NULL,&b_max,NULL,NULL);
- double b_bin_width=(double)b_dst->width/size;
- double b_bin_unith=(double)b_dst->height/b_max;
- for(i=0;i<size;i++)
- {
- CvPoint p0=cvPoint(i*b_bin_width,b_dst->height);
- CvPoint p1=cvPoint((i+1)*b_bin_width,b_dst->height-cvGetReal1D(b_hist->bins,i)*b_bin_unith);
- cvRectangle(b_dst,p0,p1,cvScalar(0,0,255),-1,8,0);
- }
- cvCalcHist(&gray,hist,0,NULL);
- IplImage* gray_dst=cvCreateImage(cvSize(400,300),8,3);
- cvSet(gray_dst,cvScalarAll(255),0);
- float max=0;
- cvGetMinMaxHistValue(hist,NULL,&max,NULL,NULL);
- double bin_width=(double)gray_dst->width/size;
- double bin_unith=(double)gray_dst->height/max;
- for(i=0;i<size;i++)
- {
- CvPoint p0=cvPoint(i*bin_width,gray_dst->height);
- CvPoint p1=cvPoint((i+1)*bin_width,gray_dst->height-cvGetReal1D(hist->bins,i)*bin_unith);
- cvRectangle(gray_dst,p0,p1,cvScalar(0),-1,8,0);
- }
- IplImage* dst=cvCreateImage(cvSize(800,600),8,3);
- cvSetZero(dst);
- CvRect rect = cvRect(0, 0, 400, 300);
- cvSetImageROI(dst, rect);
- cvCopy(r_dst, dst);
- rect = cvRect(400, 0, 400, 300);
- cvSetImageROI(dst, rect);
- cvCopy(g_dst, dst);
- rect = cvRect(0, 300, 400, 300);
- cvSetImageROI(dst, rect);
- cvCopy(b_dst, dst);
- rect = cvRect(400, 300, 400, 300);
- cvSetImageROI(dst, rect);
- cvCopy(gray_dst, dst);
- cvResetImageROI(dst);
- cvNamedWindow("src",1);
- cvShowImage("src",src);
- cvNamedWindow("dst",1);
- cvShowImage("dst",dst);
- cvSaveImage("dst.jpg",dst);
- cvWaitKey(0);
- cvDestroyAllWindows();
- cvReleaseImage(&src);
- cvReleaseImage(&dst);
- cvReleaseImage(&r);
- cvReleaseImage(&g);
- cvReleaseImage(&b);
- cvReleaseImage(&gray);
- cvReleaseImage(&r_dst);
- cvReleaseImage(&g_dst);
- cvReleaseImage(&b_dst);
- cvReleaseImage(&gray_dst);
- return 0;
- }
效果图如下