基于OpenCV库绘制灰度图,彩色图的直方图。
灰度图为单通道图,每个像素只有一个采样颜色。cvConvertImage()函数可以将其他图转换为单通道图像。绘制灰度图直方图代码如下:
void grayImgHist(IplImage* inputImg)
{
IplImage* grayImg = cvCreateImage(cvGetSize(inputImg), 8, 1);
cvCvtColor(inputImg, grayImg, CV_BGR2GRAY); //彩色图转灰度图
int histSize = 256;//直方图宽度
int histHeight = 256;//直方图高度
float range[] = {0,255}; //灰度级的范围
float* ranges[] ={range};
//创建一维直方图,统计图像在[0 255]像素的均匀分布
CvHistogram* grayHist = cvCreateHist(1, &histSize, CV_HIST_ARRAY, ranges, 1);
//计算灰度图像的一维直方图
cvCalcHist(&grayImg, grayHist, 0, 0);
//归一化直方图
cvNormalizeHist(grayHist, 1.0);
//统计直方图中的最大直方块(做多的点数)
float maxValue = 0;
cvGetMinMaxHistValue(grayHist, 0, &maxValue, 0, 0);
//创建一张一维直方图的“图”,横坐标为灰度级,纵坐标为像素个数
IplImage* histImage = cvCreateImage(cvSize(histSize, histHeight), 8, 3);
cvZero(histImage); //全部初始化为0
//分别将每个直方块的值绘制到图中
//图像原点为左上角
// cvRectangle通过对角线上点绘制矩形
for(int i = 0; i < histSize; i++)
{
float binNum = cvQueryHistValue_1D(grayHist, i); //像素i对应的点数
int binHeight = cvRound(binNum / maxValue * histHeight); //要绘制的高度
cvRectangle(histImage,
cvPoint(i, histHeight - 1),
cvPoint(i + 1, histHeight - binHeight),
CV_RGB(255,255,255));
}
}
彩色图一般有RGB3个通道,或者RGBA4个通道。需要对每个通道分离,再单独处理。源代码如下
void colorImgHist(IplImage* inputImg)
{
IplImage* r=cvCreateImage(cvGetSize(inputImg), IPL_DEPTH_8U, 1);
IplImage* g=cvCreateImage(cvGetSize(inputImg), IPL_DEPTH_8U, 1);
IplImage* b=cvCreateImage(cvGetSize(inputImg), IPL_DEPTH_8U, 1);
cvSplit(inputImg, b, g, r,NULL); //各个通道分离
IplImage* grayHistImage = cvCreateImage(cvGetSize(inputImg), 8, 1);
cvCvtColor(inputImg, grayHistImage, CV_BGR2GRAY);
int histWidth = 256;
int histHeight = 256;
float range[]={0,255};
float* ranges[]={range};
CvHistogram* rHist = cvCreateHist(1, &histWidth, CV_HIST_ARRAY, ranges, 1);
CvHistogram* gHist = cvCreateHist(1, &histWidth, CV_HIST_ARRAY, ranges, 1);
CvHistogram* bHist = cvCreateHist(1, &histWidth, CV_HIST_ARRAY, ranges, 1);
//R通道
cvCalcHist(&r, rHist, 0, NULL);
float rMax=0;
cvGetMinMaxHistValue(rHist, NULL, &rMax, NULL, NULL);
IplImage* rHistImage = cvCreateImage(cvSize(histWidth, histHeight), 8, 3);
cvZero(rHistImage); //全部初始化为0
for(int i = 0; i < histWidth; i++)
{
float binNum = cvQueryHistValue_1D(rHist, i); //像素i对应的点数
int binHeight = cvRound(binNum / rMax * histHeight); //要绘制的高度
cvRectangle(rHistImage,
cvPoint(i, histHeight - 1),
cvPoint(i + 1, histHeight - binHeight),
CV_RGB(255, 0, 0));
}
//G通道
cvCalcHist(&g, gHist, 0, NULL);
float gMax=0;
cvGetMinMaxHistValue(gHist, NULL, &gMax, NULL, NULL);
IplImage* gHistImage = cvCreateImage(cvSize(histWidth, histHeight), 8, 3);
cvZero(gHistImage); //全部初始化为0
for(int i = 0; i < histWidth; i++)
{
float binNum = cvQueryHistValue_1D(gHist, i); //像素i对应的点数
int binHeight = cvRound(binNum / gMax * histHeight); //要绘制的高度
cvRectangle(gHistImage,
cvPoint(i, histHeight - 1),
cvPoint(i + 1, histHeight - binHeight),
CV_RGB(0, 255, 0));
}
//B通道
cvCalcHist(&b, bHist, 0, NULL);
float bMax=0;
cvGetMinMaxHistValue(bHist, NULL, &bMax, NULL, NULL);
IplImage* bHistImage = cvCreateImage(cvSize(histWidth, histHeight), 8, 3);
cvZero(bHistImage); //全部初始化为0
for(int i = 0; i < histWidth; i++)
{
float binNum = cvQueryHistValue_1D(bHist, i); //像素i对应的点数
int binHeight = cvRound(binNum / bMax * histHeight); //要绘制的高度
cvRectangle(bHistImage,
cvPoint(i, histHeight - 1),
cvPoint(i + 1, histHeight - binHeight),
CV_RGB(0, 0, 255));
}
//对3通道直方图整合到同一张图
IplImage* dst=cvCreateImage(cvSize(histWidth * 3, histHeight), 8, 3);
cvSetZero(dst);
CvRect rect = cvRect(0, 0, histWidth, histWidth);
cvSetImageROI(dst, rect);
cvCopy(rHistImage, dst);
rect = cvRect(histWidth, 0, histWidth, histHeight);
cvSetImageROI(dst, rect);
cvCopy(gHistImage, dst);
rect = cvRect(histWidth * 2, 0, histWidth, histHeight);
cvSetImageROI(dst, rect);
cvCopy(bHistImage, dst);
cvResetImageROI(dst);
}