Python OpenCV 直方图的计算与显示的方法示例

作者:Daetalus 时间:2022-10-15 07:36:24 

本篇文章介绍如何用OpenCV Python来计算直方图,并简略介绍用NumPy和Matplotlib计算和绘制直方图

直方图的背景知识、用途什么的就直接略过去了。这里直接介绍方法。

计算并显示直方图

与C++中一样,在Python中调用的OpenCV直方图计算函数为cv2.calcHist。

cv2.calcHist的原型为:


cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate ]]) #返回hist

通过一个例子来了解其中的各个参数:


#coding=utf-8
import cv2
import numpy as np

image = cv2.imread("D:/histTest.jpg", 0)
hist = cv2.calcHist([image],
 [0], #使用的通道
 None, #没有使用mask
 [256], #HistSize
 [0.0,255.0]) #直方图柱的范围

其中第一个参数必须用方括号括起来。

第二个参数是用于计算直方图的通道,这里使用灰度图计算直方图,所以就直接使用第一个通道;

第三个参数是Mask,这里没有使用,所以用None。

第四个参数是histSize,表示这个直方图分成多少份(即多少个直方柱)。第二个例子将绘出直方图,到时候会清楚一点。

第五个参数是表示直方图中各个像素的值,[0.0, 256.0]表示直方图能表示像素值从0.0到256的像素。

最后是两个可选参数,由于直方图作为函数结果返回了,所以第六个hist就没有意义了(待确定)

最后一个accumulate是一个布尔值,用来表示直方图是否叠加。

彩色图像不同通道的直方图

下面来看下彩色图像的直方图处理。以最著名的lena.jpg为例,首先读取并分离各通道:


import cv2  
import numpy as np  

img = cv2.imread("D:/lena.jpg")  
b, g, r = cv2.split(img)

接着计算每个通道的直方图,这里将其封装成一个函数:


def calcAndDrawHist(image, color):  
 hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])  
 minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)  
 histImg = np.zeros([256,256,3], np.uint8)  
 hpt = int(0.9* 256);  

for h in range(256):  
   intensity = int(hist[h]*hpt/maxVal)  
   cv2.line(histImg,(h,256), (h,256-intensity), color)  

return histImg;

这里只是之前代码的简单封装,所以注释就省掉了。

接着在主函数中使用:


if __name__ == '__main__':  
 img = cv2.imread("D:/lena.jpg")  
 b, g, r = cv2.split(img)  

histImgB = calcAndDrawHist(b, [255, 0, 0])  
 histImgG = calcAndDrawHist(g, [0, 255, 0])  
 histImgR = calcAndDrawHist(r, [0, 0, 255])  

cv2.imshow("histImgB", histImgB)  
 cv2.imshow("histImgG", histImgG)  
 cv2.imshow("histImgR", histImgR)  
 cv2.imshow("Img", img)  
 cv2.waitKey(0)  
 cv2.destroyAllWindows()

这样就能得到三个通道的直方图了,如下:

Python OpenCV 直方图的计算与显示的方法示例

更进一步

这样做有点繁琐,参考abid rahman的做法,无需分离通道,用折线来描绘直方图的边界可在一副图中同时绘制三个通道的直方图。方法如下:


#coding=utf-8  
import cv2  
import numpy as np  

img = cv2.imread('D:/lena.jpg')  
h = np.zeros((256,256,3)) #创建用于绘制直方图的全0图像  

bins = np.arange(256).reshape(256,1) #直方图中各bin的顶点位置  
color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三种颜色  
for ch, col in enumerate(color):  
 originHist = cv2.calcHist([img],[ch],None,[256],[0,256])  
 cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)  
 hist=np.int32(np.around(originHist))  
 pts = np.column_stack((bins,hist))  
 cv2.polylines(h,[pts],False,col)  

h=np.flipud(h)  

cv2.imshow('colorhist',h)  
cv2.waitKey(0)

结果如下图所示:

Python OpenCV 直方图的计算与显示的方法示例

代码说明:

这里的for循环是对三个通道遍历一次,每次绘制相应通道的直方图的折线。for循环的第一行是计算对应通道的直方图,经过上面的介绍,应该很容易就能明白。

这里所不同的是没有手动的计算直方图的最大值再乘以一个系数,而是直接调用了OpenCV的归一化函数。该函数将直方图的范围限定在0-255×0.9之间,与之前的一样。下面的hist= np.int32(np.around(originHist))先将生成的原始直方图中的每个元素四舍六入五凑偶取整(cv2.calcHist函数得到的是float32类型的数组),接着将整数部分转成np.int32类型。即61.123先转成61.0,再转成61。注意,这里必须使用np.int32(...)进行转换,numpy的转换函数可以对数组中的每个元素都进行转换,而Python的int(...)只能转换一个元素,如果使用int(...),将导致only length-1 arrays can be converted to Python scalars错误。

下面的pts = np.column_stack((bins,hist))是将直方图中每个bin的值转成相应的坐标。比如hist[0] =3,...,hist[126] = 178,...,hist[255] = 5;而bins的值为[[0],[1],[2]...,[255]]。使用np.column_stack将其组合成[0, 3]、[126, 178]、[255, 5]这样的坐标作为元素组成的数组。

最后使用cv2.polylines函数根据这些点绘制出折线,第三个False参数指出这个折线不需要闭合。第四个参数指定了折线的颜色。

当所有完成后,别忘了用h = np.flipud(h)反转绘制好的直方图,因为绘制时,[0,0]在图像的左上角。这在直方图可视化一节中有说明。

NumPy版的直方图计算

在查阅abid rahman的资料时,发现他用NumPy的直方图计算函数np.histogram也实现了相同的效果。如下:


#coding=utf-8
import cv2
import numpy as np

img = cv2.imread('D:/lena.jpg')
h = np.zeros((300,256,3))
bins = np.arange(257)
bin = bins[0:-1]
color = [ (255,0,0),(0,255,0),(0,0,255) ]

for ch,col in enumerate(color):
 item = img[:,:,ch]
 N,bins = np.histogram(item,bins)
 v=N.max()
 N = np.int32(np.around((N*255)/v))
 N=N.reshape(256,1)
 pts = np.column_stack((bin,N))
 cv2.polylines(h,[pts],False,col)

h=np.flipud(h)

cv2.imshow('img',h)
cv2.waitKey(0)

效果图和上面的一个相同。NumPy的histogram函数将在NumPy通用函数这篇博文中介绍,这里就不详细解释了。这里采用的是与一开始相同的比例系数的方法,参考本文的第二节。

另外,通过NumPy和matplotlib可以更方便的绘制出直方图,下面的代码供大家参考,如果有机会,再写的专门介绍matplotlib的文章。


import matplotlib.pyplot as plt
import numpy as np
import cv2

img = cv2.imread('D:/lena.jpg')
bins = np.arange(257)

item = img[:,:,1]
hist,bins = np.histogram(item,bins)
width = 0.7*(bins[1]-bins[0])
center = (bins[:-1]+bins[1:])/2
plt.bar(center, hist, align = 'center', width = width)
plt.show()

Python OpenCV 直方图的计算与显示的方法示例

这里显示的是绿色通道的直方图。

来源:http://blog.csdn.net/sunny2038/article/details/9097989

标签:python,计算,直方图
0
投稿

猜你喜欢

  • distinct 多列问题结合group by的解决方法

    2024-01-21 11:18:23
  • adox 的vbs类,提取表名,列名等

    2008-07-02 12:37:00
  • PyTorch读取Cifar数据集并显示图片的实例讲解

    2021-03-24 11:07:55
  • python使用reportlab画图示例(含中文汉字)

    2022-10-22 17:14:18
  • Python的Scrapy爬虫框架简单学习笔记

    2023-09-25 06:41:44
  • 在go中使用omitempty的代码实例

    2024-04-25 15:12:47
  • python微信跳一跳游戏辅助代码解析

    2021-06-10 21:42:29
  • Tornado Application的实现

    2022-09-29 07:09:19
  • python星号(*)和双星号(**) 函数动态参数匹配及解包操作方法

    2023-04-09 19:55:03
  • 浅谈PHP的数据库接口和技术

    2024-05-02 17:13:49
  • 在 git 中取消 __pycache__ 文件的方法

    2022-09-14 20:00:17
  • mysql中max_allowed_packet参数的配置方法(避免大数据写入或者更新失败)

    2024-01-17 06:06:08
  • 深入理解go slice结构

    2024-04-26 17:27:07
  • python下载图片实现方法(超简单)

    2021-12-21 02:17:07
  • 关于vue3中setup函数的使用

    2024-06-05 09:16:16
  • Anaconda的安装及其环境变量的配置详解

    2022-08-31 19:21:11
  • python自带的http模块详解

    2021-11-03 08:59:22
  • linux系统使用python监控apache服务器进程脚本分享

    2021-10-15 00:15:41
  • Python计算双重差分模型DID及其对应P值使用详解

    2022-08-06 21:07:53
  • 手把手教你用SQL获取年、月、周几、日、时

    2024-01-24 05:04:12
  • asp之家 网络编程 m.aspxhome.com