图像直方图是反映图像中像素分布特性的统计表,一般显示如下:

其中横坐标代表的是图像像素的种类,或者说是灰度级,纵坐标代表的是每一级灰度下像素数或者该灰度级下像素数在所有图像总像素数总所占的百分比。

直方图反映了图像像素的整体分布,是图像的一个很重要的特征,直方图处理也是很多空间域图像处理的基础,在特征提取,图像增强,图像匹配等方面都占有一席之地。

直观上看,若直方图的分量主要集中在左侧低灰度级的区域,说明该图像整体灰度偏低,欠曝或者环境昏暗就有可能造成灰度偏低;

若直方图的分量主要集中在右侧高灰度级的区域,说明图像整体灰度偏高,过曝或环境光过于明亮就有可能造成灰度偏高;

若直方图的分量在各个灰度级分布均匀,占据了整个灰度级,则说明该幅图像对比度明显,一般情况下,具有这种直方图分布的图像的灰度细节比较丰富,图像质量较好。

直方图并不包含位置信息,相同的图像一定对应同一个直方图,而相同的直方图有可能所对应的图像千差万别,一个明显的例子是一幅选择180°的图像跟原图像的直方图分布是一致的,但是图像在表现上已经把图像倒置了,是完全不同的两幅图像。

opencv中计算直方图使用的是calcHist()函数,函数原型:

void calcHist( const Mat* images, int nimages,
const int* channels, InputArray mask,
OutputArray hist, int dims, const int* histSize,
const float** ranges, bool uniform=true, bool accumulate=false );

第一个参数:const Mat类型的images指针,可以是单幅图像或数组;

第二个参数:int型的nimages,是number of images的缩写,表示 输入数组的个数,单通道值为1;

第三个参数:const int型的channesl,需要统计的通道 (dim)索引数,单通道灰度图像为0;

第四个参数:InputArray类型的Mat()掩码,传入Mat()表示未定义,不使用掩码;

第五个参数:OutputArray类型的r_hist,储存直方图的矩阵;

第六个参数:int型的dims,直方图维数;

第七个参数:const int型的histSize指针,表示直方图的bin数目,即灰度级;

第八个参数:const float型的histRange指针,表示每个维度的取值范围;

第九和第十个参数:uniform 和 accumulate,bin大小相同,清楚直方图痕迹,分别是指为true和false

直方图opencv calcHist函数实现:

#include "core/core.hpp"
#include "highgui/highgui.hpp"
#include "imgproc/imgproc.hpp" using namespace cv; int main(int argc,char *argv[])
{
Mat image,imageGray,imageHist,imageNormalize;
image=imread(argv[1]);
if(!image.data)
{
return -1;
}
// RGB三通道图像转化成单通道灰度图像
// 也可以直接在imread函数里第二个参数设为0获取灰度图像
cvtColor(image,imageGray,CV_RGB2GRAY);
const int histSize=255; //定义灰度级数量
float histR[]={0,255}; //定义每个灰度级下取值范围
const float *histRange=histR; //计算直方图
calcHist(&imageGray,1,0,Mat(),imageHist,1,&histSize,&histRange,true,false); //直方图归一化到范围[0,histSize]
normalize(imageHist,imageNormalize,0,histSize,NORM_MINMAX,-1,Mat()); //创建直方图画布
Mat imageShowHist(histSize,histR[1],CV_8UC3,Scalar(0,0,0)); //分别画出每个灰度级下的直方图分布
for(int i=0;i<histSize;i++)
{
line(imageShowHist,Point(i,histR[1]),Point(i,histR[1]-cvRound(imageNormalize.at<float>(i))),Scalar(0,0,255),1,8,0);
}
imshow("Moon",image); imshow("MoonGray",imageGray);
imshow("Hist",imageShowHist);
waitKey();
return 0;
}

运行效果:
           

从直方图上特性上分析,灰度级基本上在每个数量级上都有分布,对比度和细节较为明显,但图像整体稍微偏暗,对比灰度图像,可以印证这些特性。

值得探讨的是我觉得在opencv文档里的教程中对直方图的计算应该有误,原文链接:

Opencv文档教程之直方图计算

例程代码照抄如下:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h> using namespace std;
using namespace cv; /** @函数 main */
int main( int argc, char** argv )
{
Mat src, dst; /// 装载图像
src = imread( argv[1], 1 ); if( !src.data )
{ return -1; } /// 分割成3个单通道图像 ( R, G 和 B )
vector<Mat> rgb_planes;
split( src, rgb_planes ); /// 设定bin数目
int histSize = 255; /// 设定取值范围 ( R,G,B) )
float range[] = { 0, 255 } ;
const float* histRange = { range }; bool uniform = true; bool accumulate = false; Mat r_hist, g_hist, b_hist; /// 计算直方图:
calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate ); // 创建直方图画布
int hist_w = 400; int hist_h = 400;
<span style="color:#ff0000;">int bin_w = cvRound( (double) hist_w/histSize );</span> Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) ); /// 将直方图归一化到范围 [ 0, histImage.rows ]
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() ); /// 在直方图画布上画出直方图
for( int i = 1; i < histSize; i++ )
{
// 加入了三个if语句,为了比对直方图,不是例程程序所有
if(i==180)
{
imshow("180",histImage);
}
if(i==200)
{
imshow("199",histImage);
}
if(i==210)
{
imshow("210",histImage);
} line( histImage, <span style="color:#ff0000;">Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) )</span> ,
Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
Scalar( 0, 0, 255), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
Scalar( 0, 255, 0), 2, 8, 0 );
line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
Scalar( 255, 0, 0), 2, 8, 0 );
} /// 显示直方图
namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
imshow("calcHist Demo", histImage ); waitKey(0); return 0; }

例程中所设直方图灰度级为255,直方图画布cols为400, int bin_w = cvRound( (double) hist_w/histSize )计算出来值为2;

这里会有问题:当计算200灰度级下的直方图时,Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)))所在的点已经超出了直方图画布的宽度400,意味着200~255灰度级的直方图被截取舍弃了,直方图并不完整。

以下是180,199和210灰度下直方图对比:

   

   

可以看到,199灰阶下已经绘制到了画布的边缘,其后的200~255灰阶超出了画布范围,没有再绘制出来,直方图也不再有变化;

把200~255灰阶补充完整的直方图如下:

可以明显看到绿色线代表的直方图分布,在200~255灰阶下有一个下降的过程曲线,做了补充绘制。

opencv直方图该怎么画的更多相关文章

  1. OpenCV直方图(直方图、直方图均衡,直方图匹配,原理、实现)

    1 直方图 灰度级范围为 \([0,L-1]\) 的数字图像的直方图是离散函数 \(h(r_k) = n_k\) , 其中 \(r_k\) 是第\(k\)级灰度值,\(n_k\) 是图像中灰度为 \( ...

  2. openCV 直方图统计

    直方图显示 #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(int argc ...

  3. OPENCV直方图与匹配

    直方图可以用来描述不同的参数和事物,如物体的色彩分布,物体的边缘梯度模版以及目标位置的当前假设的概率分布. 直方图就是对数据进行统计的一种方法,并且将统计值定义到一系列定义好的bin(组距)中,获得一 ...

  4. OpenCV——直方图均衡化(用于图像增强)

    #include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ...

  5. opencv:直方图操作

    示例程序: #include <opencv.hpp> using namespace cv; using namespace std; int main() { Mat src, dst ...

  6. opencv 直方图

    1.简介 对输入图像进行直方图均衡化处理,提升后续对象检测的准确率在OpenCV人脸检测的代码演示中已经很常见.此外对医学影像图像与卫星遥感图像也经常通过直方图均衡化来提升图像质量. 图像直方图均衡化 ...

  7. opencv直方图均衡化

    #include <iostream> #include "highgui.h" #include "cv.h" #include "cx ...

  8. opencv直方图拉伸

    1.首先计算出一幅图像的直方图 //计算直方图 cv::MatND ImageHist::getHist(const cv::Mat &image){ cv::Mat im; if(image ...

  9. Opencv 直方图比较

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

随机推荐

  1. 三类(创结行),23种设计模式,速记理解法!PHP

    一,创建型设计模式 1.FACTORY—追MM少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是MM爱吃的东西,虽然口味有所不同,但不管你带MM去麦当劳或肯德基,只管向服务员说“来四个鸡翅”就行了.麦当劳 ...

  2. css3的一些新属性及部分用法

    CSS3是CSS(层叠样式表)技术的升级版本,增加了很多新属性,我们在web开发中采用css3技术可以提高程序的性能以及用户体验.而且一般面试中会问到知道哪些新增加的属性,我们不可能将所有东西一一复述 ...

  3. CODEVS_1033 蚯蚓的游戏问题 网络流 最小费用流 拆点

    原题链接:http://codevs.cn/problem/1033/ 题目描述 Description 在一块梯形田地上,一群蚯蚓在做收集食物游戏.蚯蚓们把梯形田地上的食物堆积整理如下: a(1,1 ...

  4. Linux出现cannot create temp file for here-document: No space left on device的问题解决

    在终端输入:cd /ho 按tab键时,显示错误: bash: cannot create temp file for here-document: No space left on device 这 ...

  5. phpQuery用法总结

    项目下载地址:http://code.google.com/p/phpquery/ 获取内容的方法: 第一种:newDocumentFile phpQuery::newDocumentFile($ur ...

  6. “ORA-01747: user.table.column, table.column 或列说明无效” 的解决方案

    此问题的原因是因为表的列名称使用了Oracle声明的关键字,列名起的不好引起的. 如果列很多,又不好确定是哪个列名使用了关键字,以下建议可供参考: select * from v$reserved_w ...

  7. redis集群设置密码详解

    原文:http://lookingdream.blog.51cto.com/5177800/1827851 注意事项: 1.如果是使用redis-trib.rb工具构建集群,集群构建完成前不要配置密码 ...

  8. 阿里云OSS 图片处理api(custom)

    阿里云OSS 图片处理api(custom) 阿里云对象存储服务(Object Storage Service, 简称OSS) 学习了:https://blog.csdn.net/u014559227 ...

  9. ZT:三十个好习惯

  10. App反编译二次打包常见问题处理

    1.二次打包时报错:Error retrieving parent for item: No resource found that matches the given name 如: D:\用户文件 ...