当前位置: 代码迷 >> 综合 >> opencv学习笔记:直方图(histogram)
  详细解决方案

opencv学习笔记:直方图(histogram)

热度:56   发布时间:2023-12-17 16:03:37.0

一、直方图的理解

??直方图就是对数据的统计图,比如最常使用的灰度图像直方图就是对灰度图像的像素值进行频率统计,按照一定的顺序绘制的图,横坐标是像素值,纵坐标是像素值出现的频率。缺点是会丢失像素的位置信息。
??通常对图像的亮度、梯度、像素值、方向等都可以进行直方图绘制。

二、直方图均衡化----equalizeHist()

2.1 介绍
??直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法。
??其本质是扩大了动态范围,因此,原来灰度不同的像素经过处理后可能变得相同,形成一片相同灰度的区域,各个区域之间有明显的边界,从而出现了伪轮廓。
??对于对比度本来就很高的图像,均衡化之后对比度会下降,对于已经均衡化的图像,再次均衡化不会产生什么影响。
2.2 API介绍

void equalizeHist( InputArray src, OutputArray dst );
参数src:8位单通道图像;
参数dst:和原图一样的大小和类型。

2.3 均衡化推导过程
??①计算输入图像的直方图;
??②计算直方图中每个灰度级的累积分布概率;
??③通过查表法进行灰度值变换
??原理公式:
??????在这里插入图片描述
??其中sss表示输出的像素灰度值,pr(x)p_{r}(x)pr?(x)表示概率密度函数,rrr表示待处理图像的灰度,取值范围是[0, L?1L-1L?1],对于灰度图来说就是[0, 255]。
??直方图均衡化的过程就是对于输入图像的灰度值,使用一个变换函数T(r)T(r)T(r),计算得到新的灰度值,该变换函数满足的条件:
??①T(r)T(r)T(r)[0,L?1][0, L-1][0,L?1]上严格单调递增;
??②当0<=r<=L?10<=r<=L-10<=r<=L?1时,0<=T(r)<=L?10<=T(r)<=L-10<=T(r)<=L?1
条件①满足了输出灰度值与输入灰度值一一对应的关系;条件②满足了输出灰度值范围与输入灰度值范围相同。

??在概率论中有 py(y)=px(x)∣f?1(y)′∣p_{y}(y)=p_{x}(x)\left | f^{-1}(y)^{'} \right |py?(y)=px?(x)?f?1(y)?这一公式,

f(x)=(L?1)∫0xpx(x)dxf(x)=(L-1)\int_{0}^{x}p_{x}(x)dxf(x)=(L?1)0x?px?(x)dx,且有f?1(y)′=1/f′(x)f^{-1}(y)^{'} =1/f^{'}(x)f?1(y)=1/f(x)带入上述公式可得:

py(y)=1L?1p_{y}(y)=\frac{1}{L-1}py?(y)=L?11?

所以直方图经过均衡化后得到的每个像素值得概率分布是相同的,均是1L?1\frac{1}{L-1}L?11?。因为直方图是累计概率的近似,并且处理后不产生新的(超过范围的)灰度级,所以实际的直方图均衡化很少能够得到完全平坦(均匀分布)的直方图,但是其有助于直方图的动态范围的扩展。
用和来代替积分计算:
??在这里插入图片描述
其中rrr代表灰度值,h(r)h(r)h(r)代表该灰度值出现的次数,w、hw、hwh代表图像的宽和高。
2.4 自定义的均衡化与API相比较出现的问题
??在比较自定义的均衡化函数和OPENCV的API时,发现API会将输入图像的灰度值中最小灰度值的统计数自动忽略,最小灰度值位置处输出结果为0,其他位置的灰度值计算方式是:
??在这里插入图片描述
其中h(r0)h(r_{0})h(r0?)是最小灰度值的统计次数,最小灰度值表示图像中出现的最小的值,不一定是0。

三、直方图的计算与绘制----calcHist()

3.1 原理介绍
??原理:通过遍历图像中的所有灰度值,统计每个灰度值出现的次数,按照灰度值从小到大(0~255)的变化顺序,将统计到的次数依次填放在数组或Mat型变量中,在绘制时,要先将统计次数的大小归一化到直方图的高度范围之内,再进行绘制。

3.2 API介绍

 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 );

参数image:输入图像指针,可以用&image表示,该参数可以有多个图像,每个图像要有相同的大小和深度,可以有不同的通道数;
参数nimages:表示输入图像的个数;
参数channels:输入图像的通道索引,可以用数组的方式的表示,其中若有多个输入图像,则第一个输入图像的通道索引为0~image.channels() - 1表示,第二个输入图像的通道索引为image.channels() ~ image.channels() + image1.channels() - 1表示,依此类推;
参数mask:如果该矩阵不为空,那么必须是8-bit的矩阵,与原图相同的尺寸,在图像中,只有被mask覆盖的区域的像素才参与直方图统计,默认为Mat();
参数hist:输出直方图,具有dims个维度;
参数dims:直方图的维度,一定是正值,不超过32;
参数histsize:表示直方图每一维的大小的数组,即指出每一维的直方图的条数;(就是将每个维度分成多少份),这里维度可以理解为通道;
参数ranges:表示直方图每一维的每个bin的上下界范围数组的数组,当直方图的bin组距是均匀时,对每一维指定上下界,下界(包含)是第0个bin的边界,上界(不包含)是第(histsize[i] - 1)个bin的边界,也就是说均匀直方图的每个range是由两个元素的数组组成,而每个ranges是由n维个range数组组成;
参数uniform:用于说明直方条bin(组距)是否是均匀等宽的;
参数accumulate:如果已设置,那么重新分配直方图时不会清零之前的,此功能可以从多个数组中计算单个直方图。

3.2.1 个别参数的理解

参数ranges的理解:
在这里插入图片描述
参数dims的理解:
??当 dims=idims=idims=i 时,得到的输出结果是一个 iii 维的(Mat型)数组。
??例如:当计算一维直方图时,计算得到的结果是一个相当于一维的矩阵(Mat),列(x)坐标表示灰度值,行(y)坐标表示统计值;
??当计算H-S二维直方图时,计算得到的结果是一个二维的矩阵(Mat),若设置channels[] = {0,1},则对应直方图的行(y)、列(x)坐标分别表示色调(hue)、饱和度(saturation);若设置channels[] = {1,0},则对应直方图的行(y)、列(x)坐标分别表示饱和度(saturation)、色调(hue);
??计算三维直方图时,dims维度对应顺序是y轴,x轴,z轴。

四、直方图对比----compareHist()

直方图比较,是用一定的标准来判断两个直方图的相似度方法;
4.1、API介绍

double compareHist( InputArray H1, InputArray H2, int method );

参数H1:第一个直方图;
参数H2:第二个直方图,和第一个有相同的大小;
参数method:比较方式。
该函数返回的是距离值d(H1,H2)

4.2、常用的四种比较方法
在这里插入图片描述
在这里插入图片描述
方法1的结果越接近1则越相似,方法2的结果越接近0则越相似,方法3的结果越大则越相似,方法4的结果越接近0则越相似。
4.3、函数实现步骤
①先用cvtColor()把图像从RGB色彩空间转换到HSV色彩空间;
②计算图像的直方图,然后归一化到[0~1]之间,用到函数calcHist()和normalize();
③使用上面4种对比标准来计算图像直方图的相似度:

五、直方图的方向投影----calcBackProject()

??反向投影是反映直方图模型在目标图像中的分布情况;简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型。
5.1、实现步骤:
①转化色彩空间到HSV;
②计算图像直方图;
③对测试图像中每个像素,获取直方图所对应的统计次数,将该值返回到测试图像的像素位置,依次遍历得到反向投影图。
可以通过对比(compareHist)两幅图像的反向投影矩阵的相似度,判断两幅图的特征相似。
原理:
??原图----原图直方图(建立灰度值与统计值的映射关系)----反向投影图
反向投影中某点的值就是它所对应的原图像中的点所在区间的灰度直方图的值,所以一个区间内的点越多,其反向投影值就越大,显示越亮,这就是提取到的特征。

例如: 给定一个数组:src = {1,2,3,4,5, 2,2,3,3,4,5,5,6,7,8,1,2,3,9,5}
将其区间划分为[0,2],[3,5],[6,8],[9,11],可以得到其直方图值为6,10,3,1
反向投影和原图的灰度图有相同的大小和深度,原图中坐标为(0,0)的值是1,其所在区间的直方图值为6,所以反向投影坐标(0,0)处的值为6,依次类推。(这里这个区间是由bin来划分的

5.2、API介绍

void calcBackProject( const Mat* images, int nimages,const int* channels, InputArray hist,OutputArray backProject, const float** ranges,double scale = 1, bool uniform = true );

参数image:可以有一个或多个图像,大小和深度相同,通道数可以不同;
参数nimage:输入图像个数;
参数channels:输入的通道索引;
参数hist:输入图像的直方图;
参数backProject:输出反向投影图,和原图的灰度图一样的大小和深度;
参数ranges:包含一个或多个设置边界参数数组的数组;
参数scale:灰度值的缩放倍数;
参数uniform:直方图组距是否均匀。

  相关解决方案