转载请详细注明原作者及出处,谢谢!

本篇文章介绍如何用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()

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

更进一步

这样做有点繁琐,参考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)

结果如下图所示:

代码说明:

这里的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()

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

未完待续。。。如有错误请指正,本人会虚心接受并改正!谢谢!

OpenCV Python教程(3、直方图的计算与显示)的更多相关文章

  1. Opencv python图像处理-图像相似度计算

    一.相关概念 一般我们人区分谁是谁,给物品分类,都是通过各种特征去辨别的,比如黑长直.大白腿.樱桃唇.瓜子脸.王麻子脸上有麻子,隔壁老王和儿子很像,但是儿子下巴涨了一颗痣和他妈一模一样,让你确定这是你 ...

  2. opencv python:图像直方图 histogram

    直接用matplotlib画出直方图 def plot_demo(image): plt.hist(image.ravel(), 256, [0, 256]) # image.ravel()将图像展开 ...

  3. OpenCV Python教程(1、图像的载入、显示和保存)

    原文地址:http://blog.csdn.net/sunny2038/article/details/9057415 转载请详细注明原作者及出处,谢谢! 本文是OpenCV  2 Computer ...

  4. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget (第一部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

  5. [OpenCV Qt教程] 在Qt图形界面中显示OpenCV图像的OpenGL Widget(第二部分)

    本文译自:http://www.robot-home.it/blog/en/software/tutorial-opencv-qt-opengl-widget-per-visualizzare-imm ...

  6. OpenCV/Python/dlib眨眼检测

    今天我们来使用面部标志和OpenCV 检测和计算视频流中的眨眼次数. 为了构建我们的眨眼检测器,我们将计算一个称为眼睛纵横比(EAR)的指标,由Soukupová和Čech在其2016年的论文&quo ...

  7. 《简明python教程》笔记一

    读<简明Python教程>笔记: 本书的官方网站是www.byteofpython.info  安装就不说了,网上很多,这里就记录下我在安装时的问题,首先到python官网下载,选好安装路 ...

  8. (原+转)简明 Python 教程:总结

     简明 Python 教程 说明:本文只是对<简明Python教程>的一个总结.请搜索该书查看真正的教程. 第3章 最初的步骤 1. Python是大小写敏感的. 2. 在#符号右面的内容 ...

  9. 【OpenCV新手教程之十二】OpenCV边缘检測:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/25560901 作者:毛星云(浅墨) ...

随机推荐

  1. CentOS安装rar及用法

    1.下载安装rar wget http://www.rarsoft.com/rar/rarlinux-x64-5.4.b3.tar.gztar -zxvf rarlinux-x64-.tar.gz - ...

  2. BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )

    做一次MST, 枚举不在最小生成树上的每一条边(u,v), 然后加上这条边, 删掉(u,v)上的最大边(或严格次大边), 更新答案. 树链剖分然后ST维护最大值和严格次大值..倍增也是可以的... - ...

  3. 【 D3.js 入门系列 — 2 】 绑定数据和选择元素

    1. 如何绑定数据 D3 有一个很独特的功能:能将数据绑定到 DOM 上,也就是绑定到文档上.这么说可能不好理解,例如网页中有段落元素<p>,我们可以将整数 5 与 <p>绑定 ...

  4. pyfits过滤数据更新文件。

    import pyfits as pf import numpy as np import matplotlib.pyplot as plt hdulist = pf.open("LE_ev ...

  5. php 取小数

  6. sobel流水线操作Verilog程序

    sobel算子的verilog实现,采用了流水线操作 module sobel_computer ( clock , reset, OrigDataEn, //SobelAluEn, OrigData ...

  7. 集合判断null

    Java 引用和指针差不多,null 引用 相当于 C++的空指针. isEmpty() 用于判断List内容是否为空,即表里一个元素也没有, 但是必须在 List<MallNews> g ...

  8. td

    http://jameswxx.iteye.com/blog/1041173 http://crane-ding.iteye.com/blog/968862 http://www.ibm.com/de ...

  9. vnc server配置、启动、重启与连接,图形管理linux系统

    环境:RedHat Linux 5企业版.Xwindows:gnome (红帽默认安装的图形界面) 尽管我们可以使用SSH连接远程通过字符界面来操作Linux,但是对于更多熟悉图形人来说是很不方便的, ...

  10. 敬请贤者:WEB、IOS开发(2年以上经验,大专);CTO、产品经理,运营专员 电商服装鞋饰买手(2年以上经验,服装或鞋类);体验店店长 (2年以上经验,服装或鞋类) 工作地点:丰台南苑路;有意者小窗QQ2211788980 - V2EX

    敬请贤者:WEB.IOS开发(2年以上经验,大专):CTO.产品经理,运营专员 电商服装鞋饰买手(2年以上经验,服装或鞋类):体验店店长 (2年以上经验,服装或鞋类) 工作地点:丰台南苑路:有意者小窗 ...