博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
opencv学习笔记三:直方图的计算和绘制
阅读量:3948 次
发布时间:2019-05-24

本文共 7399 字,大约阅读时间需要 24 分钟。

前言

此代码可依次复制粘贴,拼接即可运行

直方图绘制时使用opencv的一项基本的能力,但当初接触直方图是我并没有整太明白,如今又好好研究了一遍代码,现在来总结一下。

直方图,顾名思义,就是类似于我们常规意义上的统计图,有三个术语:

  1. dims:需要统计的特征的数目。
  2. bins:每个特征空间子区段的数目,可以翻译为“直条”和“组距”。
  3. range:每个特征空间的取值范围。例如:range = [0,255]。

直方图的计算与绘制

直方图的计算使用到了calcHist()函数,函数原型:

calcHist(				const Mat*   images,    //输入数组				int          nimages,   //输入数组个数				const int*   channels,  //通道索引				InputArray   mask;      //Mat(),  //不使用腌膜				OutputArray  hist,      //输出的目标直方图,一个二维数组				int			 dims,      //需要计算的直方图的维度  例如:灰度,R,G,B,H,S,V等数据				congst int*  histSize,   //存放每个维度的直方图尺寸的数组				const float**    ranges, //每一维数组的取值范围数组				bool          uniform=true,   				bool          accumulate = false			);

这里会用到一个返回最大值最小值的函数,在我的上篇博文《opencv学习笔记二:角点检测》中有介绍:

void cv::MinMaxLoc(					arr ,  //输入单通道数组	     double*	min_val, //返回最小值的指针		 double*	max_val,//返回最大值的指针		 Point*		min_loc,//指向返回最小值的位置指针		 Point*		max_loc,//指向返回最大值的位置指针)

注意:它的输入为单通道数组

示例程序一:计算并绘制图像的一维数组

我们先从绘制一维图像开始,一维直方图就像我们在word里用的柱状图一样,有这类似的思路:

  • 定义直方图需要统计的特征数目,如灰度,RGB,HSV等衡量标准
  • 定义每个特征的直方图尺寸大小
  • 定义通道索引,当计算RGB或HSV等特征时会用到
  • 定义每个特征的取值范围数组,即高度
  • 进行绘制
    下面看程序:
#include "pch.h"#include 
#include
using namespace std;using namespace cv;int main(){
//【1】读取原图并显示 Mat srcImage = imread("5.jpg", 0); imshow("原图:", srcImage); if (!srcImage.data) {
cout << "fail to load image" << endl; return 0; }

首先,上面的是开头,将需要计算的图片载入并显示,原图如下图:

在这里插入图片描述
但我们载入的时候为: Mat srcImage = imread(“5.jpg”, 0); 是按灰度图载入的,因此显示出来为:
在这里插入图片描述

//【2】定义变量	MatND dstHist;   	int dims = 1;  //特征数目(直方图维度)	float hranges[] = {
0,255 }; //特征空间的取值范围 const float *ranges[] = {
hranges }; int size = 256; //存放每个维度的直方图的尺寸的数组 int channels = 0; //通道数

然后就需要定义变量了,MatND为多维,多通道的密集数组类型

dims为特征数目,此程序只计算该图片的一个特征,且图片是一张灰度图,由后面的int channals = 0我们可以看出,计算的是该图片的通道0,也就是灰度的直方图。
hranges[]为特征空间的取值范围数组,为0-255;有几个特征就需要定义几个这样的数组,然后将这些数组存到const float *ranges[] = { hranges }中
size为存放每个维度的直方图的尺寸的数组

//【3】计算直方图	calcHist(&srcImage, 1, &channels, Mat(), dstHist, dims, &size, ranges);	int scale = 1;	cout << dstHist << endl;	Mat dstImage(size * scale, size, CV_8U, Scalar(0));	//【4】获取最大值和最小值	double minValue = 0;	double maxValue = 0;	minMaxLoc(dstHist, &minValue, &maxValue, 0, 0);

接下来我们计算直方图并获取脂肪图的最大,最小值。我并不清楚计算出来的直方图是啥子?所以我在中间cout<<desHist<<endl;看了一下,如下图:

在这里插入图片描述
图片很长,是一个一列很多行的数组,这我们就明白了,每一行数都表示一个像素点的灰度值。

//【5】绘制直方图	int hpt = saturate_cast
(0.9*size); for (int i = 0; i < 256; i++) {
float binValue = dstHist.at
(i); int realValue = saturate_cast
(binValue*hpt / maxValue); rectangle(dstImage, Point(i*scale, size - 1), Point((i + 1)*scale - 1, size - realValue), Scalar(255)); } imshow("一维直方图", dstImage); waitKey(0); return 0;}

程序到此就结束了,在绘制直方图的这一段程序里,我们运用了rectangle()函数,函数原型如下:是一个画矩形的函数

rectangle(		img,  //输入图像		pt1,  //矩阵的一个定点		pt2,  //矩阵对角线上另一个顶点		color, //线条颜色(RGB)或亮度(灰度图像)(grayscale image)		thickness,  //组成矩形的线条的粗细程度。取负值时函数绘制填充了色彩的矩形		line_type,  //线条的类型  		shift  //坐标点的小数点位数		);

在其中有一句 int hpt = saturate_cast(0.9size);

感觉0.9出现的很突然,这一句其实是可以调整直方图绘制的大小的,看了下面截图应该就明白了:
当:int hpt = saturate_cast(0.9
size);
在这里插入图片描述
当:int hpt = saturate_cast(0.5*size);
在这里插入图片描述
看到这里就应该明白了吧?

示例程序二:H-S 二维直方图的计算与绘制

接下来我们看看包含H-S两个特征的二维直方图的绘制///

#include "pch.h"#include 
#include
using namespace std;using namespace cv;int main(){
//【1】输入原图像,并转换为HSV颜色模型 Mat srcImage, hsvImage; srcImage = imread("5.jpg"); cvtColor(srcImage, hsvImage, COLOR_BGR2HSV);

还是,先读取一张图片,然后转换为HSV模型。H为色调,S为饱和度

//【2】参数准备	//将色调量化为30个等级,将饱和度量化为32个等级	int hueBinNum = 30;  //色调的直方图直条数量	int saturationBinNum = 32;  //饱和度的直方图直条数量	int histSize[] = {
hueBinNum,saturationBinNum }; //存放每个维度的直方图尺寸的数组 float hueRanges[] = {
0,180 }; //色调变化范围为0-179 float saturationRanges[] = {
0,256 }; //定义饱和度变化范围为0(黑,白,灰)到255(纯光谱颜色) const float* ranges[] = {
hueRanges,saturationRanges }; //每一位数值的取值范围数组

还是我们示例一程序中的思路,先定义bins,就是区间个数,示例一中我们定义为了256,在这儿我们将色调的设为30,饱和度的设为32;

然后将这两个尺寸放进int histSize[] = { hueBinNum,saturationBinNum };中用来传给直方图计算函数;
接着定义特征值的取值范围,色调的取值范围为0-180,饱和度的为0-256,同样,装进const float* ranges[] = { hueRanges,saturationRanges }; 数组中传给直方图计算函数;

//输出目标直方图	MatND dstHist;	//参数准备,calcHist函数中将计算第0通道和第一通道的直方图	int channels[] = {
0,1 }; //【3】 正式调用calcHist,进行直方图计算 calcHist( &hsvImage, //输入数组 1, //输入数组个数 channels, //通道索引 Mat(), //不使用腌膜 dstHist, //输出的目标直方图,一个二维数组 2, //需要计算的直方图的维度为2 histSize, //存放每个维度的直方图尺寸的数组 ranges, //每一维数组的取值范围数组 true, false );
//打印直方图	cout << dstHist<

然后就是直方图计算了,这里就不多说了。同样,我们还打印一下看看直方图计算出来是个什么东西:是一个比较大的二维数组,就是H-S的大小啦

在这里插入图片描述

double maxValue = 0;   //最大值	minMaxLoc(dstHist, 0, &maxValue, 0, 0);  //查找数组和子数组的全局最小值和最大值存入maxValue中	int scale = 10;	Mat histImg = Mat::zeros(saturationBinNum *scale, hueBinNum * 10, CV_8UC3);  //每个bin分配10个像素宽度	//【5】双层循环,进行直方图绘制	for (int hue = 0; hue < hueBinNum; hue++)	{
for (int saturation = 0; saturation < saturationBinNum; saturation++) {
float binValue = dstHist.at
(hue, saturation); //直方图直条的值 //访问像素值 int intensity = cvRound(binValue * 255 / maxValue); //强度 cvRound返回和参数最接近的整数值 //正式进行绘制 rectangle(histImg, Point(hue* scale, saturation*scale), Point((hue + 1)*scale - 1, (saturation + 1)*scale - 1), Scalar::all(intensity), FILLED); } } //【6】显示效果图 imshow("素材图", srcImage); imshow("H-S直方图", histImg); waitKey();}

最后,就是绘制直方图了:运行结果如下:

在这里插入图片描述
对于二维的绘制过程,和画图表也很相似,原理就是下图:
在这里插入图片描述

示例程序三:绘制RGB三色直方图

最后我们绘制RGB三色直方图,虽然是三色,但也是一维的,而不像示例二中是二维直方图。

#include "pch.h"#include 
#include
using namespace std;using namespace cv;int main(){
//【1】载入原图并显示 Mat srcImage; srcImage = imread("5.jpg"); imshow("素材图", srcImage); //【2】参数准备 int bins = 256; //直条数 int hist_size[] = {
bins}; //存放每个维度的直方图尺寸数组 // 均为256条宽度 float range[] = {
0,256 }; //每一维数组的取值范围 // 均为0-255高度 const float* ranges[] = {
range }; MatND redHist, grayHist, blueHist; //定义三个图像数组

开头我们就不多说了,还是千篇一律的设置尺寸等,我们至此还没有定义通道;

//计算红色分量	int channels_r[] = {
0 }; //每个图像数组一个通道 calcHist(&srcImage, 1,channels_r, Mat(), redHist, 1, hist_size, ranges, true, false); //计算绿色分量 int channels_g[] = {
1 }; calcHist(&srcImage, 1, channels_g, Mat(), grayHist, 1, hist_size, ranges, true, false); //计算蓝色分量 int channels_b[] = {
2 }; calcHist(&srcImage, 1, channels_b, Mat(), blueHist, 1, hist_size, ranges, true, false);

然后我们分别定义了通道0,1,2并分别进行了计算;

最后就是绘制了:

//参数准备	double maxValue_red, maxValue_green, maxValue_blue;	minMaxLoc(redHist, 0, &maxValue_red, 0, 0);	minMaxLoc(grayHist, 0, &maxValue_green, 0, 0);	minMaxLoc(blueHist, 0, &maxValue_blue, 0, 0);	int scale = 1;	int histHeight = 256;	Mat histImage = Mat::zeros(histHeight, bins * 3, CV_8UC3);	//绘制直方图	for (int i = 0; i < bins; i++)	{
float binValue_red = redHist.at
(i); float binValue_green = grayHist.at
(i); float binValue_blue = blueHist.at
(i); int intensity_red = cvRound(binValue_red*histHeight / maxValue_red); int intensity_green = cvRound(binValue_green*histHeight / maxValue_green); int intensity_blue = cvRound(binValue_blue*histHeight / maxValue_blue); rectangle(histImage, Point(i*scale, histHeight - 1), Point((i + 1)*scale - 1, histHeight - intensity_red), Scalar(255, 0, 0)); rectangle(histImage, Point((i+bins)*scale, histHeight - 1), Point((i+bins+ 1)*scale - 1, histHeight - intensity_green), Scalar(0, 255, 0)); rectangle(histImage, Point((i+bins*2)*scale, histHeight - 1), Point((i + bins*2+1)*scale - 1, histHeight - intensity_blue), Scalar(0, 0, 255)); } imshow("图像的RGB直方图", histImage); waitKey(0); return 0;}

运行结果如下:

在这里插入图片描述

转载地址:http://ldewi.baihongyu.com/

你可能感兴趣的文章
mysql中GROUP_CONCAT的应用
查看>>
研发人员的绩效考核
查看>>
Python 3 之多线程研究
查看>>
Python 3中的多线程文件下载类
查看>>
Python库之MySQLdb介绍
查看>>
Python3中利用Urllib进行表单数据提交(Get,Post)
查看>>
Python开发之扩展库的安装指南及Suds(Webservice)的使用简介
查看>>
软件项目管理一点分享
查看>>
iphone程序打包ipa格式
查看>>
Ios开发之Apns功能介绍(应用程序通知)及PHP/Python代码
查看>>
iphone开发的几个Apple官方中文教程地址
查看>>
Algorithms: Kruskal's algorithm and Prim's algorithm for Minimum-spanning-tree
查看>>
Algorithm : Dijkstra's algorithm and Bellmon-Ford Paths algorithm
查看>>
Algorithm: k-nearest neighbors and decison boundary(Cross Validation)
查看>>
Algorithm: Principle Component Analysis for High Dimension Reduction Data
查看>>
Naive Bayesian for Text Classification (MLE, Gaussian Naive Bayesian)
查看>>
Algorithm: Decision Tree, Entropy, Information Gain and Continues features
查看>>
FastDFS 架构分析
查看>>
Windows 应用生成MiniDump文件的方法笔记
查看>>
安装FastDFS单机版环境
查看>>