opencv学习笔记(九)-灰度直方图

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

灰度直方图的定义

直方图(Histogram)又称柱状图、质量分布图,是一种统计报告图。直方图由一系列高度不等的纵向条纹或线段表示数据分布的情况。一般用横轴表示数据类型,纵轴表示分布情况。在图像处理上,直方图是图像信息统计的有力工具。

灰度直方图是灰度级的函数,描述图像中该灰度级的像素个数(或该灰度级像素出现的频率):其横坐标是灰度级(像素的种类),纵坐标表示图像中该灰度级出现的个数(频率)。
一维直方图的结构表示为
这里写图片描述

高维直方图可以理解为图像在每个维度上灰度级分布的直方图。常见的是二维直方图。如红-蓝直方图的两个分量分别表示红光图像的灰度值和蓝光图像灰度值的函数。其图像坐标(Dr,Db)处对应在红光图像中具有灰度级Dr同时在蓝光图像中具有灰度级Db的像素个数。这是基于多光谱——每个像素有多个变量——的数字图像,二维中对应每个像素统计个变量。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
cvCreateHist()
创建直方图

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

dims
直方图维数的数目
sizes
直方图维数尺寸的数组
type
直方图的表示格式: CV_HIST_ARRAY 意味着直方图数据表示为多维密集数组 CvMatND; CV_HIST_TREE 意味着直方图数据表示为多维稀疏数组 CvSparseMat.
ranges
图中方块范围的数组. 它的内容取决于参数 uniform 的值。这个范围的用处是确定何时计算直方图或决定反向映射(backprojected ),每个方块对应于输入图像的哪个/哪组值。
uniform
归一化标识。 如果不为0,则ranges[i](0<=i

#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);
    printf("%f\n", histMax);
    /*图像清零*/
    cvZero(imgHist);


    for (int i = 0; i < 255; i++)
    {
        float histValue = cvQueryHistValue_1D(hist, i);
        float nextValue = cvQueryHistValue_1D(hist, i + 1);

        printf("histValue = %f,nextValue = %f\n", histValue, nextValue);

        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);   //这是四边形的右上角点
        /*这里是为了将所有的灰度值得高度限定在64之内,
        设定最大值高度为64,其他值按占最大值的比例(nexValue/histMax)*64 计算得出*/
        CvPoint pt4 = cvPoint(i*scaleX, (1 - (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()
{
    IplImage* img = cvLoadImage("G:\\Opencv\\素材\\楪析.jpg");
    cvNamedWindow("Test");
    cvShowImage("Test", img);

    /*定义画多大的直方图*/
    int size = 256;//每个bin中含有一个像素点

    /*直方图的维度*/
    int dims = 1;//一维直方图

    /*设置方块范围*/
    float range[] = { 0, 255 };
    float* ranges[] = { range };
    CvHistogram* hist;
    hist = cvCreateHist(dims, &size, CV_HIST_ARRAY, ranges, 1);
    cvClearHist(hist);

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

    /*将图像src  分解成B   G   R 三个通道*/
    cvSplit(img, imgBlue, imgRed, imgGreen, NULL);

    /*计算B通道 直方图*/
    cvCalcHist(&imgBlue, hist, 0, 0);

    /*绘制B通道直方图,并储存在histBlue中*/
    IplImage* histBlue = DrawHistogram(hist);

    /*清空直方图数据*/
    cvClearHist(hist);

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

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


    cvNamedWindow("B");
    cvNamedWindow("R");
    cvNamedWindow("G");

    cvShowImage("B", histBlue);
    cvShowImage("R", histRed);
    cvShowImage("G", histGreen);

    cvWaitKey(0);

    histBlue = NULL;
    histRed = NULL;
    histGreen = NULL;
    imgRed = NULL;
    imgBlue = NULL;
    imgGreen = NULL;
    img = NULL;
    cvDestroyWindow("Test");
    cvDestroyWindow("B");
    cvDestroyWindow("R");
    cvDestroyWindow("G");
}

你可能感兴趣的:(opencv)