图像直方图的计算

9 篇文章 0 订阅

1.1 cv.calcHist()函数,函数原型如下:

void cv::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:需要计算直方图的源图像阵列集;注意:它们都应该具有相同的深度、CV_8U、CV_16U或CV_32F以及相同的大小。它们中的每一个都可以具有任意数量的通道。
nimages:这个图像阵列中,图像的个数
channels:用于计算直方图中的每个维度的每个通道的列表,需要统计的图像的通道集合(是一个整型数组,且数组值不可变)。
mask:掩膜,如果掩膜非空, 那么这个掩膜必须是和源图像阵列中的图像同样大小的8位图像数组。
hist:存放经过直方图计算后的图像
dims:直方图的维度,直方图维度必须为正且不大于CV_MAX_DIMS(在当前OpenCV版本中等于32)
histSize:每个维度上直方图的尺寸大小
ranges:每个维度上直方图二进制边界的维度数组的数组,是一个二位数组。当直方图是均匀的(uniform=true)时,对于每个维度,只需指定第0个直方图的下(含)边界和最后一个直方图的上(不含)边界即可,即,在均匀直方图的情况下,每个范围是2个元素的阵列。当直方图不一致(uniform=false)时,则每个范围i中包含histSize[i]+1个元素:L0,U0=L1,U1=L2,....... ,UhistSize[i]−2=LhistSize[i]−1,UhistSize[i]−1。不在L0和UhistSize[i]−1之间的数组元素不计入直方图中。
uniform:直方图是否进行归一化处理,true为是,false为否
accumulate:累计,是否累计,如果已设置,则分配直方图时不会在开始时清除直方图。此功能使您能够从多组数组中计算单个直方图,或及时更新直方图。

实例代码

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

using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
  Mat src, dst;
  String imageName( "demo.jpg" ); //图像名
  src = imread( imageName ); // 读取这个路径下的图片放在这个src容器当中
  if( src.empty() ) //图片是否为空
    { return -1; }
  vector<Mat> bgr_planes; // 创建源图像的图像容器vector
  split( src, bgr_planes );//将这个图像在RGB三个通道分别分离出来。记得到三个通道的三张图片存放在bgr_planes中
  int histSize = 256; //设置直方图大小
  float range[] = { 0, 256 } ; // 指定饱和度范围在0~255中。
  const float* histRange = { range };
  bool uniform = true; bool accumulate = false;
  Mat b_hist, g_hist, r_hist;
  calcHist( &bgr_planes[0], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
  calcHist( &bgr_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
  calcHist( &bgr_planes[2], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate ); 
  //上边是计算三个通道三张图片的直方图。
  //下边是画出这三条折线图(过点划线),当然你也可以使用rectangle去绘制条形图。当然如果是Python,则可以借助三方库matlab中的方法直接完成绘图。
  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) ); 
//利用Mat的重写的构造函数构造一个histImage图像对象
//用于存储均质化(规范化一个数组的标准范围或者数组中元素值的范围)的结果。
//这个图像的大小和直方图一样大。
  //标准化处理:
  normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
  normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
  normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
  for( int i = 1; i < histSize; i++ )//下边就是采点划线的过程了。
  {
      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  );
      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(r_hist.at<float>(i-1)) ) ,
                       Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) ),
                       Scalar( 0, 0, 255), 2, 8, 0  );
  }
  namedWindow("calcHist Demo", WINDOW_AUTOSIZE );
  imshow("calcHist Demo", histImage );
  waitKey(0);
  return 0;


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序小K

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值