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


Posted in Python onFebruary 08, 2018

本篇文章介绍如何用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 直方图的计算与显示的方法示例

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python之Socket网络编程详解
Sep 29 Python
Django安装配置mysql的方法步骤
Oct 15 Python
在python中利用KNN实现对iris进行分类的方法
Dec 11 Python
在Python中将函数作为另一个函数的参数传入并调用的方法
Jan 22 Python
学习python分支结构
May 17 Python
python绘制评估优化算法性能的测试函数
Jun 25 Python
python安装scipy的方法步骤
Jun 26 Python
python 将日期戳(五位数时间)转换为标准时间
Jul 11 Python
Python将文字转成语音并读出来的实例详解
Jul 15 Python
在django admin中配置搜索域是一个外键时的处理方法
May 20 Python
解决keras backend 越跑越慢问题
Jun 18 Python
Python json解析库jsonpath原理及使用示例
Nov 25 Python
python OpenCV学习笔记之绘制直方图的方法
Feb 08 #Python
Python列表推导式与生成器表达式用法示例
Feb 08 #Python
详解python OpenCV学习笔记之直方图均衡化
Feb 08 #Python
python OpenCV学习笔记实现二维直方图
Feb 08 #Python
Python数据分析之双色球基于线性回归算法预测下期中奖结果示例
Feb 08 #Python
Python编程argparse入门浅析
Feb 07 #Python
PyQt5主窗口动态加载Widget实例代码
Feb 07 #Python
You might like
Yii2简单实现多语言配置的方法
2016/07/23 PHP
PHP数据的提交与过滤基本操作实例详解
2016/11/11 PHP
Swoole 5将移除自动添加Event::wait()特性详解
2019/07/10 PHP
php报错502badgateway解决方法
2019/10/11 PHP
prettify 代码高亮着色器google出品
2010/12/28 Javascript
javascript学习笔记(三)BOM和DOM详解
2014/09/30 Javascript
JS判断网页广告是否被浏览器拦截过滤的代码
2015/04/05 Javascript
Bootstrap每天必学之基础排版
2015/11/20 Javascript
AngularJs directive详解及示例代码
2016/09/01 Javascript
jquery删除table当前行的实例代码
2016/10/07 Javascript
JavaScript操作文件_动力节点Java学院整理
2017/06/30 Javascript
Angular在模板驱动表单中自定义校验器的方法
2017/08/09 Javascript
Bootstrap 模态框(Modal)带参数传值实例
2017/08/20 Javascript
Vue通过WebSocket建立长连接的实现代码
2019/11/05 Javascript
vue操作dom元素的3种方法示例
2020/09/20 Javascript
使用Python下载Bing图片(代码)
2013/11/07 Python
python遍历 truple list dictionary的几种方法总结
2016/09/11 Python
Python编程实现粒子群算法(PSO)详解
2017/11/13 Python
Python+matplotlib实现计算两个信号的交叉谱密度实例
2018/01/08 Python
pandas 实现将重复表格去重,并重新转换为表格的方法
2018/04/18 Python
Python 网络爬虫--关于简单的模拟登录实例讲解
2018/06/01 Python
Python代理IP爬虫的新手使用教程
2019/09/05 Python
Python 面向对象之封装、继承、多态操作实例分析
2019/11/21 Python
Tensorflow分批量读取数据教程
2020/02/07 Python
python继承threading.Thread实现有返回值的子类实例
2020/05/02 Python
HTML5 Canvas——用路径描画线条实例介绍
2013/06/09 HTML / CSS
H&M美国官网:欧洲最大的服饰零售商
2016/09/07 全球购物
JD Sports马来西亚:英国领先的运动鞋和运动服饰零售商
2018/03/13 全球购物
编写strcpy函数
2014/06/24 面试题
能否解释一下XSS cookie盗窃是什么意思
2012/06/02 面试题
公司活动方案范文
2014/03/06 职场文书
公司大门门卫岗位职责
2014/06/11 职场文书
挂职学习心得体会
2014/09/09 职场文书
勤俭节约主题班会
2015/08/13 职场文书
Java实现斗地主之洗牌发牌
2021/06/14 Java/Android
Win11 Beta 预览版 22621.575 和 22622.575更新补丁KB5016694发布(附更新内容大全)
2022/08/14 数码科技