您的位置:首页 > 运维架构

opencv直方图

2016-03-28 16:18 447 查看
图像直方图:

直方图反映了一幅图像不同灰度级出现的情况,其计算公式为:




表示图像中灰度级为k的像素个数。在直方图中表现为每一列的高度。

相关数据结构与函数:

(1)CvHistogram

typedef struct CvHistogram
{
int     type;   //指定bins的类型
CvArr*  bins;   //指向存储每个灰度级的数组地址
float   thresh[CV_MAX_DIM][2];  //用于指定直方图分布的上下界,并且为均匀直方图的分布
float** thresh2;                //用于指定直方图分布的上下界,是非均匀直方图的分布
CvMatND mat;                    //存储直方图的信息,具体内容为直方图的头信息
}


(2)cvCreateHist

cvCreateHist(int dims, int* sizes, int type,
float** ranges CV_DEFAULT(NULL),
int uniform CV_DEFAULT(1));


dims:表示要绘制的直方图的维数,一般是一维的

sizes:直方图划分的模块数,如:

int size = 256; //表示多大的直方图,对每一个像素做统计  256个像素
//int size[2] = {4,4};  表示二维的,第一维分4个区域,第二维分4个区域


type:直方图的表示格式,有两种:CV_HIST_ARRAY多维密集数组;CV_HIST_SPARSE多维稀疏数组

ranges:

float range[] = { 0, 255 };//range表示在每一个维度的范围
float* ranges[] = { range };//ranges是为了方便表示多维的范围


uniform :uniform 值为0,表示模块划分是均匀的,非0是不均匀的

3. 绘制直方图代码:

#include<highgui.h>
#include<core.hpp>
#include<cv.h>
//查询直方图中每一块的值
#define cvQueryHistValue_1D(hist,idx0)\
cvGetReal1D((hist)->bins,(idx0))

//绘制直方图 scaleX和scaleY是调节直方图与显示窗体的大小
IplImage* DrawHistogran(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);

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, (1-nextValue/histMax)*64 * scaleY);
CvPoint pt4 = CvPoint(    i*scaleX, (1-histValue/histMax)*64 * scaleY);
int numPts = 5;
CvPoint pts[5] = { pt1, pt2, pt3, pt4, pt1 };
//绘制每个像素的图像
cvFillConvexPoly(imgHist, pts, numPts, CvScalar(i));
}
return imgHist;
}

int main(int argc,char *argcv[])
{
IplImage* image = cvLoadImage("E:\\project\\images\\view.jpg");
cvNamedWindow("image");
cvShowImage("image", image);

int dims = 1; //维数

//int size[2] = {4,4};  表示二维的,第一维分4个区域,第二维分4个区域
int size = 256; //表示多大的直方图,对每一个像素做统计  256个像素
//range表示在每一个维度的范围,ranges是为了方便表示多维的范围
float range[] = { 0, 255 };
float* ranges[] = { range };

CvHistogram* hist = cvCreateHist(dims,&size,CV_HIST_ARRAY,ranges,1);
cvClearHist(hist);

IplImage* imgRed = cvCreateImage(cvGetSize(image), 8, 1);
IplImage* imgGreen = cvCreateImage(cvGetSize(image), 8, 1);
IplImage* imgBlue = cvCreateImage(cvGetSize(image), 8, 1);
IplImage* imgGray = cvCreateImage(cvGetSize(image), 8, 1);

cvCvtColor(image, imgGray, CV_BGR2GRAY);

//分解图像  与  cvCvtPixToPlane(image, imgBlue, imgGreen, imgRed,NULL);功能一样
cvSplit(image, imgBlue, imgGreen, imgRed,NULL);

//计算直方图
cvCalcHist(&imgBlue, hist, 0, 0);
IplImage* histBlue = DrawHistogran(hist);
cvClearHist(hist);

cvCalcHist(&imgGreen, hist, 0, 0);
IplImage* histGreen = DrawHistogran(hist);
cvClearHist(hist);

cvCalcHist(&imgRed, hist, 0, 0);
IplImage* histRed = DrawHistogran(hist);
cvClearHist(hist);

cvCalcHist(&imgGray, hist, 0, 0);
IplImage* histGray = DrawHistogran(hist);
cvClearHist(hist);

cvNamedWindow("B");
cvNamedWindow("G");
cvNamedWindow("R");
cvNamedWindow("Gray");
cvShowImage("B", histBlue);
cvShowImage("G", histGreen);
cvShowImage("R", histRed);
cvShowImage("Gray", histRed);
cvWaitKey(0);
return 0;
}


结果显示为:





在绘制直方图时,采用的是cvFillConvexPoly函数,也可以用cvRectangle函数,如:

IplImage* DrawHistogran(CvHistogram* hist)
{
IplImage* imgHist = cvCreateImage(CvSize(256*2,256),8,1);
cvZero(imgHist);

int scale = 2;
float hist_max = 0;
cvGetMinMaxHistValue(hist, 0, &hist_max, 0, 0);

for (int i = 0; i < 256; i++)
{
float bin_value = cvQueryHistValue_1D(hist, i);
int intensity = cvRound(bin_value * 256 / hist_max);
cvRectangle(imgHist,
CvPoint(i*scale,256-1),
CvPoint((i+1)*scale-1,256-intensity),
CV_RGB(255,255,255));
}
return imgHist;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: