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字典排序实例详解
May 20 Python
Python实现截屏的函数
Jul 25 Python
python如何去除字符串中不想要的字符
Jul 05 Python
Python中defaultdict与lambda表达式用法实例小结
Apr 09 Python
TensorFlow打印tensor值的实现方法
Jul 27 Python
对python 匹配字符串开头和结尾的方法详解
Oct 27 Python
Python协程操作之gevent(yield阻塞,greenlet),协程实现多任务(有规律的交替协作执行)用法详解
Oct 14 Python
python tornado使用流生成图片的例子
Nov 18 Python
django实现web接口 python3模拟Post请求方式
Nov 19 Python
python为Django项目上的每个应用程序创建不同的自定义404页面(最佳答案)
Mar 09 Python
Python requests及aiohttp速度对比代码实例
Jul 16 Python
PyCharm设置注释字体颜色以及是否倾斜的操作
Sep 16 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基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
php使用ftp实现文件上传与下载功能
2017/07/21 PHP
JavaScript DOM学习第六章 表单实例
2010/02/19 Javascript
原生javascript和jquery判断浏览器版本等信息
2013/07/04 Javascript
在ASP.NET中使用JavaScript脚本的方法
2013/11/12 Javascript
js操作输入框提示信息且响应鼠标事件
2014/03/25 Javascript
js实现ArrayList功能附实例代码
2014/10/29 Javascript
JavaScript调用浏览器打印功能实例分析
2015/07/17 Javascript
jQuery实现的简单百分比进度条效果示例
2016/08/01 Javascript
微信小程序 自定义对话框实例详解
2017/01/20 Javascript
推荐VSCode 上特别好用的 Vue 插件之vetur
2017/09/14 Javascript
初探Vue3.0 中的一大亮点Proxy的使用
2018/12/06 Javascript
js中call()和apply()改变指针问题的讲解
2019/01/17 Javascript
微信小程序仿淘宝热搜词在搜索框中轮播功能
2020/01/21 Javascript
es6 super关键字的理解与应用实例分析
2020/02/15 Javascript
Python3实现的腾讯微博自动发帖小工具
2013/11/11 Python
python下如何查询CS反恐精英的服务器信息
2017/01/17 Python
python实现画五角星和螺旋线的示例
2019/01/20 Python
python UDP(udp)协议发送和接收的实例
2019/07/22 Python
Django使用中间件解决前后端同源策略问题
2019/09/02 Python
python实现批量处理将图片粘贴到另一张图片上并保存
2019/12/12 Python
opencv resize图片为正方形尺寸的实现方法
2019/12/26 Python
医学生个人求职信范文
2013/09/24 职场文书
寒假思想汇报
2014/01/10 职场文书
我未来的职业规划范文
2014/01/11 职场文书
土建专业大学生自荐信范文
2014/04/09 职场文书
房屋买卖协议书范本
2014/04/10 职场文书
精神文明建设先进工作者事迹材料
2014/05/02 职场文书
电子商务专业求职信
2014/07/10 职场文书
信用卡结清证明怎么写
2014/09/13 职场文书
国庆65周年演讲稿:回首往昔,展望未来
2014/09/21 职场文书
民事答辩状范本
2015/05/21 职场文书
喜迎建国70周年:有关爱国的名言名句
2019/09/24 职场文书
用Python提取PDF表格的方法
2021/04/11 Python
Python基础之tkinter图形化界面学习
2021/04/29 Python
HTML5页面音频自动播放的实现方式
2021/06/21 HTML / CSS