• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

C++OpenCV下绘制灰度直方图

武飞扬头像
我刀尼
帮助1

C OpenCV下绘制直方图
直方图的定义:灰度直方图是对一幅灰度图像素分布的统计。对于一幅8Bit量化的图像来说。就是统计在0~255各个灰度级上,像素点的个数或者密度。
在OpenCV库提供了 calcHist()方法用于得到图像的直方图。
具体函数的调用方法如下:
void cv::calcHist(const Mat*images,int nimages,const int *channels,InputArrary mask,OutputArrary hist,int dims,const int* histSize,const float **ranges,bool uniform=true,bool accumulate=false)
//参数说明
//images:带统计直方图的图像数组
//nimages:输入图像的数目
//channels:需要统计的通道索引数组 一般灰度图就是0通道
//mask:掩码 一般填Mat()
//hist:输出的统计直方图结果,是一个dims维度的数组。不过用OpenCV中Mat类型的变量存储
//dims:hist的列数、需要计算直方图的维度
//histSize:存放每个维度直方图数组的尺寸
//ranges:每个通道灰度值的取值范围
根据以上参数,设计了一个获取直方图Mat数组Hist的函数
  1.  
    //@para gray:需要统计的图   Hist:用于存放统计数据
  2.  
    void GetHist(Mat gray,Mat &Hist)    //统计8Bit量化图像的灰度直方图
  3.  
    {
  4.  
        const int channels[1] = { 0 }; //通道索引
  5.  
        float inRanges[2] = { 0,255 };  //像素范围
  6.  
        const float* ranges[1] = {inRanges};//像素灰度级范围
  7.  
        const int bins[1] = { 256 };   //直方图的维度
  8.  
        calcHist(&gray, 1, channels,Mat(), Hist,1, bins, ranges);
  9.  
    }
学新通这里得gray为测试灰度图。看下运行完calcHist函数后,Hist的维数。
可以看到Hist就是一个256行1列Mat类型的变量,可以看做一个数组索引。
这样我们就可以根据这个Hist画图。
这里设计一个ShowHist函数,主要的步骤就是申请一块背景为纯黑的图像,再根据Hist的值转化为点坐标从而画出一个个白色的矩形以完成直方图的绘制。
  1.  
    void ShowHist(Mat &Hist)
  2.  
    {
  3.  
    //准备绘制直方图
  4.  
    int hist_w = 512;
  5.  
    int hist_h = 400;
  6.  
    int width = 2;
  7.  
    Mat histImage = Mat::zeros(hist_h,hist_w,CV_8UC3); //准备histImage为全黑背景色,大小为512*400
  8.  
    for (int i = 0; i < Hist.rows; i )
  9.  
    {
  10.  
    rectangle(histImage,Point(width*(i),hist_h-1),Point(width*(i 1),hist_h-cvRound(Hist.at<float>(i)/20)),
  11.  
    Scalar(255,255,255),-1);
  12.  
    }
  13.  
    namedWindow("histImage", WINDOW_AUTOSIZE);
  14.  
    imshow("histImage", histImage);
  15.  
    //waitKey(0);
  16.  
    }
学新通
首先准备一幅512*400的全黑背景图histImage,接下来通过Hist.rows遍历每个灰度级的像素个数。通过Rectangle函数画出白色的矩形。最后的-1代表绘制的矩形是填充矩形。对于Rectangle,重点分析下两个Point的含义。
@param pt1 Vertex of the rectangle.
@param pt2 Vertex of the rectangle opposite to pt1 .
上面是官方给出的注释,pt1为矩形的一个顶点,pt2为矩形对角线上的另一个顶点。
首先看横坐标,一个矩形的横坐标长度应该为一个像素级所占的长度,这里我们假定一个像素级占长度为width=2。pt1的横坐标值为width*(i),pt2的横坐标值为width*(i 1);
再看纵坐标,首先需要明白图像的坐标系,它是这样的:
学新通
pt1的纵坐标为:hist_h-1相当于图像最下面,也就是矩形的左下角。pt2的纵坐标应该是矩形的右上角才对,hist_h-cvRound(Hist.at<float>(i)/20),cvRound是4舍5入,Hist.at<float>(i)取出在该像素级上像素点的个数,这个数字可能远远大于hist_h(512),因为直方图我们只希望看到图像像素级分布的大致,所以我们除以一个20保证不会超出图像的边界。
最后给出我主函数的调用:
  1.  
    int main(int argc,char *argv)
  2.  
    {
  3.  
        Mat src,gray,hist;   //hist用于统计gray的直方图
  4.  
        src=imread("2.jpg");
  5.  
        cvtColor(src,gray,CV_BGR2GRAY);
  6.  
        GetHist(gray,hist);
  7.  
        ShowHist(hist);
  8.  
        namedWindow("gray");
  9.  
        imshow("gray",gray);
  10.  
        waitKey(0);
  11.  
        return 0;
  12.  
    }
结果:
学新通
总结分析:其实图像的直方图只能告诉我们图像像素级别的分布如何,可以定性的帮助我们判断图像对比度,以及亮度的分布情况,如果想通过直方图进行操作,还是得借助calcHist得到的Hist数组对其进行定量的操作。

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfkibg
系列文章
更多 icon
同类精品
更多 icon
继续加载