在《《数字图像处理》第三章学习总结感悟2:直方图处理: https://blog.csdn.net/LaoYuanPython/article/details/119856466》相关的文章中介绍了直方图均衡、直方图匹配、局部直方图处理、基于直方图统计信息进行图像增强处理等图像处理与直方图相关的内容,由此可见直方图在OpenCV中大有用途,因此OpenCV中也提供了直方图计算的函数calcHist,这个函数在网上介绍的很多,不过都是基于C语言的,对OpenCV-Python版本介绍得不多,本文就该函数OpenCV-Python版本详细说明一下。
在OpenCV中,图像的直方图计算使用函数calcHist,在C语言中,该函数有多种重载形式,参数也比较多,而在Python中则不一样。
下面是C++版本的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
)
相关介绍网上到处都是,在此就不展开说,而OpenCV-Python关于该函数的资料却很少见,有的也基本是官方文档的简单翻译,下面就calcHist的Python版本介绍一下。
Python中因为不支持函数的多态形式,因此只有一个函数,其定义如下:
hist = cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
这些参数说明如下:
可以看到相比C++版本,python版本变化如下:
下面构造一个简单的图像数组,来进行直方图的计算,看看计算出来的直方图数据:
import cv2
def test():
img = np.array([[[1,2,3],[1,2,3],[1,2,3]],[[4,5,6],[4,5,6],[4,5,6]],[[7,8,9],[7,8,9],[7,8,9]]],dtype=np.uint8)
B, G, R = cv2.split(img)
hb = cv2.calcHist([B], [0], None, [9], [1,10],accumulate=True)
hg = cv2.calcHist([G], [0], None, [9], [3, 8],accumulate=True)
hr = cv2.calcHist([R], [0], None, [9], [1, 5], accumulate=True)
print("蓝色通道的直方图矩阵如下:")
print(hb.shape,hb.reshape(hb.shape[0]))
print("绿色通道的直方图矩阵如下:")
print(hg.shape, hg.reshape(hg.shape[0]))
print("红色通道的直方图矩阵如下:")
print(hr.shape, hr.reshape(hr.shape[0]))
test()
上段程序首先构建了3*3的BGR格式的图像矩阵,像素值每个通道由1-9中的数字构成。使用cv2.split做了各像素的三通道拆分,拆分后三通道的像素值如下:
B通道:
G通道:
R通道:
然后分别计算三个通道的直方图数据,注意B通道指定的范围是[1,10],G是[3,8],R是[1,5],三者中绿色通道指定组数是6,其他2个通道指定的组数是9。我们来看看最终输出结果:
蓝色通道的直方图矩阵如下:
(9, 1) [3. 0. 0. 3. 0. 0. 3. 0. 0.]
绿色通道的直方图矩阵如下:
(6, 1) [0. 0. 3. 0. 0. 0.]
红色通道的直方图矩阵如下:
(9, 1) [0. 0. 0. 0. 3. 0. 0. 0. 0.]
可以看到直方图的矩阵是一个组数×1的二阶数组。
蓝色通道中1、 4、 7三个数字各自出现了三次,组设设置ranges设置为【1-10】,组数设置为9,由于上限10不参与计算,因此一个数字就是一个组,1、 4、 7三个数字分别在0组、3组和6组,因此直方图数组展开后的最终结果是[3. 0. 0. 3. 0. 0. 3. 0. 0.]。
绿色通道中2、 5、 8三个数字各自出现了三次,组设设置ranges设置为【3-8】,组数设置为6,由于上限8不参与计算,实际参与直方图计算的数字是3、4、5、6、7共5个,因此2、 5、 8三个数字实际上只有5能纳入直方图统计中,分为6组后,每组的宽度为(8-3)/6=0.833,5在第3组(组号2),因此数组展开后的最终结果是[0. 0. 3. 0. 0. 0.]。
类似地,红色通道中3、 6、 9三个数字各自出现了三次,组设设置ranges设置为【1-5】,组数设置为9,由于上限5不参与计算,实际参与直方图计算的数字是1、2、3、4共5个,因此3、 6、 9三个数字实际上只有3能纳入直方图统计中,分为9组后,每组的宽度为(5-1)/9=0.444,3在第5组(组号4),因此数组展开后的最终结果是[0. 0. 0. 0. 3. 0. 0. 0. 0.]。
**从上面的结果可以看到,参数accumulate=True没有起到作用。**不知道老猿的测试方法是否存在问题。
本文详细介绍了OpenCV-Python图像直方图计算calcHist函数的语法以及使用案例,希望这些介绍有助于大家详细了解OpenCV-Python图像直方图计算的方法。
本文相关内容其实已经在《OpenCV-Python图像直方图计算calcHist函数详解、示例及图形呈现》中介绍,且该文中还有更多内容,但该文人气不足,老猿就简化了标题和内容,看能否有所改观。
更多图像直方图处理的内容请参考《《数字图像处理》第三章学习总结感悟2:直方图处理》的介绍。
更多图像处理请参考专栏《OpenCV-Python图形图像处理》及《图像处理基础知识》的介绍。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《 专栏:Python基础教程目录》从零开始学习Python。
如对文章内容存在疑问,可在博客评论区留言,或关注:老猿Python 微信公号发消息咨询,可通过扫博客左边的二维码加微信公众号。
如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!
前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。
对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。
如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。