opencv直方图该怎么画
图像直方图是反映图像中像素分布特性的统计表,一般显示如下:
其中横坐标代表的是图像像素的种类,或者说是灰度级,纵坐标代表的是每一级灰度下像素数或者该灰度级下像素数在所有图像总像素数总所占的百分比。
直方图反映了图像像素的整体分布,是图像的一个很重要的特征,直方图处理也是很多空间域图像处理的基础,在特征提取,图像增强,图像匹配等方面都占有一席之地。
直观上看,若直方图的分量主要集中在左侧低灰度级的区域,说明该图像整体灰度偏低,欠曝或者环境昏暗就有可能造成灰度偏低;
若直方图的分量主要集中在右侧高灰度级的区域,说明图像整体灰度偏高,过曝或环境光过于明亮就有可能造成灰度偏高;
若直方图的分量在各个灰度级分布均匀,占据了整个灰度级,则说明该幅图像对比度明显,一般情况下,具有这种直方图分布的图像的灰度细节比较丰富,图像质量较好。
直方图并不包含位置信息,相同的图像一定对应同一个直方图,而相同的直方图有可能所对应的图像千差万别,一个明显的例子是一幅选择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文档里的教程中对直方图的计算应该有误,原文链接:
例程代码照抄如下:
#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直方图该怎么画的更多相关文章
- OpenCV直方图(直方图、直方图均衡,直方图匹配,原理、实现)
		1 直方图 灰度级范围为 \([0,L-1]\) 的数字图像的直方图是离散函数 \(h(r_k) = n_k\) , 其中 \(r_k\) 是第\(k\)级灰度值,\(n_k\) 是图像中灰度为 \( ... 
- openCV 直方图统计
		直方图显示 #include <opencv2/opencv.hpp> using namespace std; using namespace cv; int main(int argc ... 
- OPENCV直方图与匹配
		直方图可以用来描述不同的参数和事物,如物体的色彩分布,物体的边缘梯度模版以及目标位置的当前假设的概率分布. 直方图就是对数据进行统计的一种方法,并且将统计值定义到一系列定义好的bin(组距)中,获得一 ... 
- OpenCV——直方图均衡化(用于图像增强)
		#include <opencv2/opencv.hpp> #include <iostream> #include <math.h> using namespac ... 
- opencv:直方图操作
		示例程序: #include <opencv.hpp> using namespace cv; using namespace std; int main() { Mat src, dst ... 
- opencv 直方图
		1.简介 对输入图像进行直方图均衡化处理,提升后续对象检测的准确率在OpenCV人脸检测的代码演示中已经很常见.此外对医学影像图像与卫星遥感图像也经常通过直方图均衡化来提升图像质量. 图像直方图均衡化 ... 
- opencv直方图均衡化
		#include <iostream> #include "highgui.h" #include "cv.h" #include "cx ... 
- opencv直方图拉伸
		1.首先计算出一幅图像的直方图 //计算直方图 cv::MatND ImageHist::getHist(const cv::Mat &image){ cv::Mat im; if(image ... 
- Opencv 直方图比较
		#include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ... 
随机推荐
- php——两种无限级分类
			/** * 无级递归分类 TP框架 * @param int $assortPid 要查询分类的父级id * @param mixed $tag 上下级分类之间的分隔符 * @return strin ... 
- Redis命令行之Hash
			一.Redis之Hash简介 1. Hash是一个string类型的field和value的映射表,适合用于存储对象. 2. 每个hash可以存储232-1个键值对(40多亿). 二.Redis之Ha ... 
- spring--路由
			@RestController: Spring4之后新加入的注解,原来返回json需要@ResponseBody和@Controller配合. 即@RestController是@ResponseBo ... 
- 《从零开始搭建游戏服务器》Eclipse和Tomcat安装配置
			我选择用来进行服务器开发的语言是Java,开发流程更接近于JavaWeb,所以需要先为开发配置一个开发环境,需要配置的主要是Eclipse和Tomcat(Web工程的容器或管理工具). 一.资源下载: ... 
- Jenkins持续部署-Windows环境持续部署探究1
			目录 Jenkins持续部署-Windows环境持续部署探究1 目录 前言 目的 方案流程 技术实现 PowerShell FTP上传插件 环境变量插件 脚本执行 远程调用 升级服务 启动服务 总结 ... 
- 多个Nginx如何实现集群(没具体方案,只是初步探究)
			场景: Nginx+Web服务器可以实现负载均衡,但是一台Nginx也是有限的,如果并非量高的话,在他的上层如何实现负载均衡. 如果是DNS或者CDN的话,建多个机房,势必有多个机房数据同步的问题. ... 
- nrf51822中app_button 的应用
			Button Handler(按键处理程序) 按键处理程序是使用GPIOTE(GPIO Task and Event)的处理机制实现的,为了防止按键的抖动.在GPIOTE event(事件)处理程序中 ... 
- 安装 python 的 pip install fabric 库 问题
			安装 pip install fabric 安装依赖需要 gcc 并且不能单独的安装gcc 还要安装完整的gcc依赖 yum -y install gcc gcc-c++ kernel-devel y ... 
- Android Studio——gradle同步出错:MALFORMED
			Android Studio之前使用本地的gradle-2.10,而后创建新的工程总是报错,信息如下: Gradle sync failed: MALFORMED 而后在File->Projec ... 
- 配置resin支持maven项目
			1. 在resin.conf中找到 <!-- includes the app-default fordefault web-app behavior --> <resin:impo ... 
