opencv 2.x学习笔记(十三)绘制直方图

简介

在上一篇文章中,我们知道了如何去进行直方图均衡化来增强图像。但是,相信大家会有一个疑惑,那就是如何获取一幅图像的直方图,今天,我们就简单的讲一下如何获取一幅图像的直方图。

想得到一幅图像的直方图很容易,简单的讲:我们可以通过下面几步来得到想要的结果。

1、加载一幅图像

2、设置一些参数

3、计算直方图

4、归一化(可选)

5、定义画布

6、绘制直方图

加载一幅图像很简单,我们已经知道,使用imread()函数来实现。那么第二步的设置参数,需要设置哪些参数呢?首先我们需要了解几个概念。

我们知道灰度图像的直方图就是对灰度图像的强度进行统计。那么首先我们要确定一下,我们需要把灰度值化为几类?如果化为两类,则可以定义为[0-127],[128-255]。所划分区间的个数就称为bins。而要就算的的灰度的强度范围就称为range。对于灰度强度即为[0-255]。当然了,我们不仅可以利用直方图来统计灰度信息。还可以统计一副图像的其他信息。我们把要统计的每类信息称为特征空间。

我们在程序中这样来设置这些参数:

  /// 设置 bins
  int histSize = 256;

  /// 设置区间
  float range[] = { 0, 256 } ;
  const float* histRange = { range };

了解这些参数之后,我们进入下一步,计算直方图。毫无疑问,这是我们本篇中最主要的内容。也是我们最无从下手的内容。不过不用担心,OpenCV为我们包揽了这一切。我们可以使用calcHist()函数来轻松的完成这一步。calcHist()函数的原型如下:

//! computes the joint dense histogram for a set of images.
CV_EXPORTS 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 );

images:原图像数组,(我们输入图像可以不止一个)。

nimages:输入图像的个数。

channels:用于计算直方图的特征通道,第一个数组通道是从0到images[0].channels()-1,第二个数组通道是从images[0].channels()到images[0].channels+images[1].channels -1等等。

mask:掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算直方图。

hist:输出的直方图

dims:直方图的维数,必须为正数。

histSize:每一维直方图的尺寸,简单地讲,如果dims为1,则histSize即为bins。

ranges:用于进行统计的范围。

uniform:决定是否均匀分布bins。

accumulate:再次绘制直方图时,决定是否清除原来的痕迹。

我们在程序中这样使用该函数:

  bool uniform = true; 
  bool accumulate = false;
  Mat hist;
  /// 计算直方图
  calcHist( &gray_image, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );
紧接着我们需要进行归一化,之所以进行归一化是为了更好的去显示图像。我们可以使用normalize()函数来完成这一功能:

我们在程序中这样来使用:

  /// 归一化到 [ 0, histImage.rows ]
  normalize( hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
第一个hist为输入数组,第二个hist为归一化后的输出数组,(支持就地计算)。0和histImage.rows为归一化的范围。

NORM_MINMAX为归一化的方法。-1表示归一化后的输出数组和输入数组同类型。

Mat()是可选的掩码。

之后我们就可以定义画布。即声明一个Mat类型的数组。

  // 创建画布
  int hist_w = 512; int hist_h = 400;
  int bin_w = cvRound( (double) hist_w/histSize );

  Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );

下面我们在画布上进行绘制直方图

  /// 绘制直方图
  for( int i = 1; i < histSize; i++ )
  {
	  rectangle( histImage, Point( bin_w*(i-1), hist_h - cvRound(hist.at<float>(i-1)) ),
		  Point( bin_w*(i), hist_h ), Scalar( 0, 0, 255 ), -1 );
  }

完整程序:

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

using namespace std;
using namespace cv;

/**
 * @function main
 */
int main( int argc, char** argv )
{
  Mat src;

  if( argc != 2 )
  {
	  cout << "输入参数个数错误" << endl;
	  return -1;
  }

  /// 加载图像
  src = imread( argv[1], CV_LOAD_IMAGE_COLOR );
  Mat gray_image;  
  cvtColor(src, gray_image, CV_BGR2GRAY);

  if( !gray_image.data )
  { 
		cout << "图像加载失败" << endl;
		return -1;
  }

  /// 设置 bins
  int histSize = 256;

  /// 设置区间
  float range[] = { 0, 256 } ;
  const float* histRange = { range };

  bool uniform = true; 
  bool accumulate = false;
  Mat hist;
  /// 计算直方图
  calcHist( &gray_image, 1, 0, Mat(), hist, 1, &histSize, &histRange, uniform, accumulate );

  // 创建画布
  int hist_w = 512; int hist_h = 400;
  int bin_w = cvRound( (double) hist_w/histSize );

  Mat histImage( hist_h, hist_w, CV_8UC3, Scalar( 0,0,0) );

  /// 归一化到 [ 0, histImage.rows ]
  normalize( hist, hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

  /// 绘制直方图
  for( int i = 1; i < histSize; i++ )
  {
	  rectangle( histImage, Point( bin_w*(i-1), hist_h - cvRound(hist.at<float>(i-1)) ),
		  Point( bin_w*(i), hist_h ), Scalar( 0, 0, 255 ), -1 );
  }

  namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
  imshow("calcHist Demo", histImage );

  waitKey(0);

  return 0;
}

运行结果:

我们使用上一篇文章中的图像进行测试,结果如下:



而均衡化后的图像的直方图如下:




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值