搜文章
推荐 原创 视频 Java开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发
Lambda在线 > 机器视觉 > OpenCV Python教程(3、直方图的计算与显示)

OpenCV Python教程(3、直方图的计算与显示)

机器视觉 2017-10-30

限时干货下载回复“资料”获取获取机器视觉教程,行业报告等资源百度盘群组分享链接更新时间:2017-07-18,失效请在文末留言,不要在后台留言,你也可以在后台菜单“资源搜索”搜索更多你想要的网盘资源!

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


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


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


计算并显示直方图


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

cv2.calcHist的原型为:

[python] view plain copy

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

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

[python] view plain copy

  1. #coding=utf-8  

  2. import cv2  

  3. import numpy as np  

  4.   

  5. image = cv2.imread("D:/histTest.jpg"0)  

  6. hist = cv2.calcHist([image],  

  7.     [0], #使用的通道  

  8.     None#没有使用mask  

  9.     [256], #HistSize  

  10.     [0.0,255.0]) #直方图柱的范围  

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


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


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


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


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


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


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

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


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


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

[python] view plain copy

  1. import cv2      

  2. import numpy as np      

  3.       

  4. img = cv2.imread("D:/lena.jpg")      

  5. b, g, r = cv2.split(img)   


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

[python] view plain copy

  1. def calcAndDrawHist(image, color):    

  2.     hist= cv2.calcHist([image], [0], None, [256], [0.0,255.0])    

  3.     minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(hist)    

  4.     histImg = np.zeros([256,256,3], np.uint8)    

  5.     hpt = int(0.9256);    

  6.         

  7.     for h in range(256):    

  8.         intensity = int(hist[h]*hpt/maxVal)    

  9.         cv2.line(histImg,(h,256), (h,256-intensity), color)    

  10.             

  11.     return histImg;   

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



接着在主函数中使用:

[python] view plain copy

  1. if __name__ == '__main__':    

  2.     img = cv2.imread("D:/lena.jpg")    

  3.     b, g, r = cv2.split(img)    

  4.     

  5.     histImgB = calcAndDrawHist(b, [25500])    

  6.     histImgG = calcAndDrawHist(g, [02550])    

  7.     histImgR = calcAndDrawHist(r, [00255])    

  8.         

  9.     cv2.imshow("histImgB", histImgB)    

  10.     cv2.imshow("histImgG", histImgG)    

  11.     cv2.imshow("histImgR", histImgR)    

  12.     cv2.imshow("Img", img)    

  13.     cv2.waitKey(0)    

  14.     cv2.destroyAllWindows()   

这样就能得到三个通道的直方图了,如下:OpenCV Python教程(3、直方图的计算与显示)


更进一步

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

[python] view plain copy

  1. #coding=utf-8    

  2. import cv2    

  3. import numpy as np    

  4.          

  5. img = cv2.imread('D:/lena.jpg')    

  6. h = np.zeros((256,256,3)) #创建用于绘制直方图的全0图像    

  7.          

  8. bins = np.arange(256).reshape(256,1#直方图中各bin的顶点位置    

  9. color = [ (255,0,0),(0,255,0),(0,0,255) ] #BGR三种颜色    

  10. for ch, col in enumerate(color):    

  11.     originHist = cv2.calcHist([img],[ch],None,[256],[0,256])    

  12.     cv2.normalize(originHist, originHist,0,255*0.9,cv2.NORM_MINMAX)    

  13.     hist=np.int32(np.around(originHist))    

  14.     pts = np.column_stack((bins,hist))    

  15.     cv2.polylines(h,[pts],False,col)    

  16.          

  17. h=np.flipud(h)    

  18.          

  19. cv2.imshow('colorhist',h)    

  20. cv2.waitKey(0)    

结果如下图所示:


OpenCV Python教程(3、直方图的计算与显示)

代码说明:

这里的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也实现了相同的效果。如下:

[python] view plain copy

  1. #coding=utf-8  

  2. import cv2  

  3. import numpy as np  

  4.   

  5. img = cv2.imread('D:/lena.jpg')  

  6. h = np.zeros((300,256,3))  

  7. bins = np.arange(257)  

  8. bin = bins[0:-1]  

  9. color = [ (255,0,0),(0,255,0),(0,0,255) ]  

  10.   

  11. for ch,col in enumerate(color):  

  12.     item = img[:,:,ch]  

  13.     N,bins = np.histogram(item,bins)  

  14.     v=N.max()  

  15.     N = np.int32(np.around((N*255)/v))  

  16.     N=N.reshape(256,1)  

  17.     pts = np.column_stack((bin,N))  

  18.     cv2.polylines(h,[pts],False,col)  

  19.   

  20. h=np.flipud(h)  

  21.   

  22. cv2.imshow('img',h)  

  23. cv2.waitKey(0)  

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


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

[python] view plain copy

  1. import matplotlib.pyplot as plt  

  2. import numpy as np  

  3. import cv2  

  4.   

  5. img = cv2.imread('D:/lena.jpg')  

  6. bins = np.arange(257)  

  7.   

  8. item = img[:,:,1]  

  9. hist,bins = np.histogram(item,bins)  

  10. width = 0.7*(bins[1]-bins[0])  

  11. center = (bins[:-1]+bins[1:])/2  

  12. plt.bar(center, hist, align = 'center', width = width)  

  13. plt.show()  



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




限时干货下载回复“资料”获取机器视觉教程,行业报告等资源。持续更新中。。。

> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > >

如何分享到朋友圈 点击右上角“...” 三个点,在弹出菜单选择“分享到朋友圈
机器视觉--订阅号 机器视觉‘公众号 机器视觉,工业自动化,机器人,图像处理技术等领域新媒体信息平台。
热门文章推荐

回复下面数字,获取相关文章

001:计算机视觉领域研究资源及期刊、会议介绍

002:德国kuka机器人与世界冠军乒乓对决

003:人脸检测的C/C++源代码

004:人工智能眼中的世界,竟然如此诡(魔)异(性)?!

005:机器人视觉中的物体表达问题-摄像机标定-视觉计算理论

006:三维计算机视觉技术

007:无奈与迷茫-30岁以上电子工程师请进

008:逆天科技小制作 自制迷你“磁悬浮列车”玩具方法图解,快动手给孩子做一个

009:Google 以图搜图 - 相似图片搜索原理 - Java实现

010:关于机器学习中的一些数学方法

011:双远心工业镜头的原理简述

012哥们花20万从德国带回来一工具箱,亮瞎了!!全铝头盔一次成型!!

013:工业相机在汽车零部件检测中的应用

版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《OpenCV Python教程(3、直方图的计算与显示)》的版权归原作者「机器视觉」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注机器视觉微信公众号

机器视觉微信公众号:www_51qudong_com

机器视觉

手机扫描上方二维码即可关注机器视觉微信公众号

机器视觉最新文章

精品公众号随机推荐