opencv学习日记之详解图像的直方图(一维和多维)

本文介绍了如何使用直方图来分析图像中的色彩分布、边缘梯度等特性,并详细解释了OpenCV中calcHist函数的参数及使用方法。通过实例展示了如何计算一维和多维直方图。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    在图像分析、物体和信息识别过程中,我们常常想把严重看到的物体用直方图(histogram)表示,直方图可以用来描述各种不同的事情,如物体的色彩分布、物体边缘梯度模板,以及表示目标位置的当前假设。例如,我们可以从输入视频中检测到感兴趣区域,然后计算这些感兴趣区域周围的边缘梯度方向,将得到的边缘地图方向放到一个方向直方图相应的bin中,然后将直方图与手势模板进行匹配,从而识别出手势。直方图广泛应用于很多计算机视觉应用中,通过标记帧与帧之间显著的边缘和颜色的统计变化,直方图被用来检测时品种场景的变换。通过为每个兴趣点设置一个有相近特征的直方图构成的标签,用以确定图像中的兴趣点。边缘、色彩、角等直方图构成了可以被传递个目标识别分类器的一个通用特征。色彩和边缘的直方图序列还可以用来识别网络视频是否被复制。直方图是计算计算机视觉中最经典的工具之一。
    简单地说,直方图就是对数据进行统计,将统计知足知道一系列实现定义好的bin中。bin中的数值是从数据中计算车的特征的统计量,这些数据可以是梯度、方向、色彩或任何其他特征。直方图就是数据分布的统计图。
    换句话说,直方图是一个简单地表,他给出了一幅图像或一组图像中拥有给定数值的像素数量。因此,灰度图像的直方图有256个条目(或称容器)。0号容器给出值为0的像素个数,1号容器给出值为1的像素个数,等等。显然,对直方图的所有项求和,会得到像素的总数。直方图也可以被归一化,归一化后的所有项之和等于1.在这种情况下,每一项给出的都是拥有特定数值的像素在图像中占得比例。下面开始对直方图进行具体分析。
计算直方图函数: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      :   输入图像,如果是多个图像时需要有相同的深度CV_8U或CV_32F,每个图像可以有任意的通道数
              nimages     :   输入图像的个数
              channels    :   用来计算直方图维数的通道列表,第一个输入数组通道被识别为0到images[0].channels()-1,第二个输入数组通道被识别为images[0].channels()到images[0].channels()+images[1].channels() -1.等等。
                       mask          :      掩膜,可选,如果矩阵非空,则务必是一个与images[i]相同大小的8位数组,非0的mask元素标记到直方图中
                       hist             :       输出直方图,是一个dense or sparse 维的数组
                       dims           :        直方图维度,务必是大于0的,<CV_MAX_DIMS(32)
                       histSize      :        每一维直方图大小的数组
                       ranges       :         Array of the dims arrays of the histogram bin boundaries in each dimension. When the histogram is uniform (uniform =true), then for each dimension i it is enough to specify the lower (inclusive) boundary                                  L_0 of the 0-th histogram bin and the upper (exclusive) boundary U_{\texttt{histSize}[i]-1} for the last histogram bin histSize[i]-1 . That is, in case of a uniform histogram each of ranges[i] is an array of 2 elements. 
                                When the histogram is not uniform ( uniform=false ), then each of ranges[i] containshistSize[i]+1 elements:L_0, U_0=L_1, U_1=L_2, ..., U_{\texttt{histSize[i]}-2}=L_{\texttt{histSize[i]}-1}, U_{\texttt{histSize[i]}-1}. The array elements,
                                that are not between L_0 and U_{\texttt{histSize[i]}-1} , are not counted in the histogram
                       uniform     :          是否为均匀or非均匀直方图
                       accumulate:           积累标志,如果为真,直方图在开始阶段不清空,保持积累状态,这个作用就是使你能够计算几个图像的直方图
好了,用实例验证下吧。先开始一维直方图
histogram.h文件
#include<opencv2/opencv.hpp>

class Histogram1D
{
private:
	int histSize[1];
	float hranges[2];
	const float * ranges[1];
	int channels[1];
public:
	Histogram1D();
	cv::MatND getHistogram(const cv::Mat &image);
	cv::Mat getHistogramImage(const cv::Mat &image);
};


histogram.cpp 文件
#include"histogram1D.h"
Histogram1D::Histogram1D()
{
	histSize[0]=256;
	hranges[0]=0.0;
	hranges[1]=255.0;
	ranges[0]=hranges;
	channels[0]=0;
}
cv::MatND Histogram1D::getHistogram(const cv::Mat &image )
{
	cv::MatND hist;
	cv::calcHist(&image,1,channels,cv::Mat(),hist,1,histSize,ranges);
	return hist;
}
cv::Mat Histogram1D::getHistogramImage(const cv::Mat &image)
{
	cv::MatND hist = getHistogram(image);
	double maxVal=0;
	double minVal=0;
	cv::minMaxLoc(hist,&minVal,&maxVal,0,0);
	cv::Mat histImg(histSize[0],histSize[0],CV_8U,cv::Scalar(255));
	int hpt=static_cast<int>(0.9*histSize[0]);
	for(int h=0;h<histSize[0];h++)
	{
		float binVal = hist.at<float>(h);
		int intensity = static_cast<int>(binVal*hpt/maxVal);
		cv::line(histImg,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0));
	}
	return histImg;
}


main()函数
#include"histogram1D.h"
#include<iostream>
int main()
{
	cv::Mat image=cv::imread("g:\\carlicense\\1.jpg");
	Histogram1D h;
	cv::namedWindow("histogram");
	cv::imshow("histogram",h.getHistogramImage(image));
	cv::Mat threshold_img;
	//cv::threshold(image,threshold_img,80,255,cv::THRESH_BINARY);
//	cv::imshow("threshold",threshold_img);
	cv::waitKey();
	return 0;
}


运行结果:
                                                                   
好了,下面开始贴上多维直方图的代码。






评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值