opencv直方图

  1. 图像直方图:
    直方图反映了一幅图像不同灰度级出现的情况,其计算公式为:
    这里写图片描述
    这里写图片描述表示图像中灰度级为k的像素个数。在直方图中表现为每一列的高度。

  2. 相关数据结构与函数:
    (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)) //绘制直方图 scaleXscaleY是调节直方图与显示窗体的大小 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; }

结果显示为:
opencv直方图_第1张图片
opencv直方图_第2张图片
在绘制直方图时,采用的是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;
}

你可能感兴趣的:(opencv,直方图)