栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

【OpenCV-Python-课程学习(贾)】OpenCV3.3课程学习笔记:图像直方图的计算、图像直方图特征的应用、直方图反向投影、matplotlib绘制图像直方图

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【OpenCV-Python-课程学习(贾)】OpenCV3.3课程学习笔记:图像直方图的计算、图像直方图特征的应用、直方图反向投影、matplotlib绘制图像直方图

图像直方图,本质上就是对图像的所有像素点的取值进行统计,在不同的横轴子区间内各有的像素点的数量作为纵轴取值。                                   

一、利用Matplotlib绘制图像直方图

在Matplotlib模块中,有一个pyplot.hist函数,可以统计数组的取值在不同区间上的发生频率,也即计算直方图。

语法格式如下,参考官方API文档:  

matplotlib.pyplot.hist(x, bins=None, range=None, density=False, weights=None, cumulative=False, bottom=None, histtype='bar', align='mid', orientation='vertical', rwidth=None, log=False, color=None, label=None, stacked=False, *, data=None, **kwargs)

因为涉及到的参数很多,我们就挑重点讲。

  • x是一维数组或者多个一维数组构成的序列;可以是二维数组,但不能是二维以上的数组。
  • bins是横轴划分参数;如果bins是一个整数,代表横轴划分的份数,默认取10;如果bins是一个数值序列,序列中的各个数值表示横轴分隔点。
  • range是横轴有效显示范围(计数范围),只显示这个范围之内的数据。
  • density是概率密度直方图标志,默认为False,表示纵轴的取值是子区间内数值点的数量;如果设置为True,表示直方图和横轴围成的区域面积应该为1,因此需要对每个子区间的计数进行归一化。
  • 函数返回结果是一维数组或者包括多个一维数组的序列(取决于x的类型),因为bins默认是10,所以默认每一个一维数组的长度就是10;一维数组的每一个元素取值代表在对应子区间内的次数。

下面分享一个案例。

import cv2 as cv
import matplotlib.pyplot as plt

img = cv.imread('images/lena.png')
plt.figure()
plt.subplot(1,2,1)
arr = plt.hist(img.ravel())
plt.subplot(1,2,2)
plt.imshow(img[:, :, ::-1])
plt.show()
print(img.ravel())
print(arr)
cv.waitKey()
cv.destroyAllWindows()

 

二、 利用OpenCV中的calcHist绘制

OpenCV中的calcHist函数只能用来计算图像直方图对应的数字信息,而无法像matplotlib.pyplot的hist函数一样直接在执行完后还能将直方图绘制出来。

OpenCV中的calcHist函数的语法格式如下。

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])

  • images应是位深度为8位无符号整型或32位浮点型的图像多维数组;书写形式上应该在图像多维数组变量两边加方括号,比如[img]。
  • channels是通道索引号,索引用方括号包裹;对于灰度图,只能用[0];对于BGR三通道图像多维数组,可以用[0]、[1]、[2],表示分别计算蓝色、绿色、红色通道上的直方图。一次只能用一个通道进行计算,这一点与本文的第一部分不同,第一部分用的plt.hist函数允许对彩色图进行多通道的直方图并行计算,但是这样的计算方式也肯定会降低直方图特征精度。
  • mask是遮罩控制参数,如果传入None,则不进行遮罩控制,直接对全图进行计算;而如果需要对图像的特定子区域进行计算,那么可以在运行函数前构建一个遮罩层。
  • histSize代表了bin的数目,也需要用方括号包裹;比如对于uint8图像,histSize=[255]时就对全部像素值进行单独计数。
  • ranges是计数范围,只有在计数范围内的像素值才会被计入;一般来说是[0, 255]。
  • hist是一个histSize*1的数组,每一个元素代表对应的bin范围内的像素数目(明显是整数)。

计算得到hist后,如果想要绘制折线型直方图,可以用plt.plot(hist)——并未涉及颜色和线型等格式的设置,只是想在这里简略提到,给读者一个思路。

三、利用numpy中的histogram函数绘制

numpy中的histogram函数与OpenCV中的calcHist函数一样,都不能直接绘直方图,都只能得到各bin内的像素计数。

但是!!!OpenCV中的calcHist函数以及matplotlib的hist函数的bins划分方式都是左闭右开,只有最右边的一个区间才是全闭,比如[0, 1),[1, 0),...,[244, 255];而numpy中的histogram函数是xxx(下图由官网截得——OpenCV: Histograms - 1 : Find, Plot, Analyze !!!)

刚开始我以为numpy的这个函数确实如官网所述,但是后来我发现完全不用将bins=256,将range=[0, 256] 。详见下面的代码,虽然最后的点是10,在第10个bin中还是包括了像素点10,说明最后一个bin的区间范围是[9, 10],而不是[9, 9.99]。

import numpy as np

print(np.histogram([[1, 2, 5, 10], [1, 0, 3, 10]], bins=10, range=[0, 10]))

# (array([1, 2, 1, 1, 0, 1, 0, 0, 0, 2], dtype=int64), array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10.]))

说明!!!numpy的histogram函数的bins分配机制和其他两者相同。

下面是numpy的histogram函数的语法格式,源于numpy.histogram — NumPy v1.23 Manual

numpy.histogram(a, bins=10, range=None, normed=None, weights=None, density=None)

  • a是n维数组,注意这里不跟matplotlib.pyplot.hist函数和cv.calcHist函数一样,它对数组的维数没有限制;因为在计算直方图特性前,会对a直接进行铺平。
  • bins是直方图x轴子区间划定参数;跟matplotlib.pyplot.hist函数的几乎一样。
  • range是计数范围,只有在计数范围内的像素值才会被计入;一般来说是[0, 255]。
  • normed参数已经在numpy 1.6.0被遗弃,不再建议使用。
  • weights是一个与a形状相同的n维数组;a中的每个值仅将其关联权重贡献给bin计数(而不是1;意思是说如果对应的权重是2,那么这个像素点所处的bin计数加的是2而不是1)。如果density为True,则对权重进行归一化,以便密度在该范围内的求和保持为1。
  • density参数跟matplotlib.pyplot.hist函数的意义一样。
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034321.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号