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(Https)Post登录百度的实现代码
May 18 Python
Python修改MP3文件的方法
Jun 15 Python
Python简单检测文本类型的2种方法【基于文件头及cchardet库】
Sep 18 Python
python 上下文管理器使用方法小结
Oct 10 Python
对Python中一维向量和一维向量转置相乘的方法详解
Aug 26 Python
tesserocr与pytesseract模块的使用方法解析
Aug 30 Python
Python3实现配置文件差异对比脚本
Nov 18 Python
Python二维数组实现求出3*3矩阵对角线元素的和示例
Nov 29 Python
PyCharm 2019.3发布增加了新功能一览
Dec 08 Python
Python HTMLTestRunner库安装过程解析
May 25 Python
新手学python应该下哪个版本
Jun 11 Python
使用keras时input_shape的维度表示问题说明
Jun 29 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
一个简单的php路由类
2016/05/29 PHP
php利用递归实现删除文件目录的方法
2016/09/23 PHP
YII2框架中excel表格导出的方法详解
2017/07/21 PHP
10个新的最有前途的JavaScript框架
2009/03/12 Javascript
用Javascript数组处理多个字符串的连接问题
2009/08/20 Javascript
Javascript解决常见浏览器兼容问题的12种方法
2010/01/04 Javascript
一些mootools的学习资源
2010/02/07 Javascript
判断字符串的长度(优化版)中文占两个字符
2014/10/30 Javascript
javascript中callee与caller的区别分析
2015/04/20 Javascript
javascript中的 object 和 function小结
2016/08/14 Javascript
Bootstrap字体图标无法正常显示的解决方法
2016/10/08 Javascript
JavaScript实现图像模糊化的方法实例
2017/01/15 Javascript
理解 JavaScript EventEmitter
2018/03/29 Javascript
nodejs npm错误Error:UNKNOWN:unknown error,mkdir 'D:\Develop\nodejs\node_global'at Error
2019/03/02 NodeJs
Vue表单之v-model绑定下拉列表功能
2019/05/14 Javascript
iview实现图片上传功能
2020/06/29 Javascript
python机器学习之决策树分类详解
2017/12/20 Python
Python中常见的异常总结
2018/02/20 Python
python中dict使用方法详解
2019/07/17 Python
Pytorch 抽取vgg各层并进行定制化处理的方法
2019/08/20 Python
Python Gluon参数和模块命名操作教程
2019/12/18 Python
Python安装tar.gz格式文件方法详解
2020/01/19 Python
Python join()函数原理及使用方法
2020/11/14 Python
如何用 Python 制作 GitHub 消息助手
2021/02/20 Python
浅谈HTML5 & CSS3的新交互特性
2016/07/19 HTML / CSS
车间班组长岗位职责
2013/11/13 职场文书
竞选演讲稿范文
2013/12/28 职场文书
新领导上任欢迎词
2014/01/13 职场文书
先进事迹报告会感言
2014/01/24 职场文书
旅游个人求职信范文
2014/01/30 职场文书
组织鉴定材料
2014/06/02 职场文书
纪律教育学习心得体会
2014/09/02 职场文书
税务干部群众路线教育实践活动对照检查材料
2014/09/20 职场文书
教师党员个人剖析材料
2014/09/29 职场文书
授权委托书协议书
2014/10/16 职场文书
寻找成龙观后感
2015/06/12 职场文书