相比C++而言,Python适合做原型。本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV函数的不同之处。这篇文章介绍在Python中使用OpenCV和NumPy对直方图进行均衡化处理。

提示:

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

本文不介详细的理论知识,读者可从其他资料中获取相应的背景知识。笔者推荐清华大学出版社的《 》,对于本节的内容,建议直接参考 维基百科直方图均衡化 ,只需看下页面最后的两幅图就能懂了。

本文内容:

使用查找表拉伸直方图

使用OpenCV和NumPy的函数以不同的方式进行直方图均衡化

在某些情况下,一副图像中大部分像素的强度都集中在某一区域,而质量较高的图像中,像素的强度应该均衡的分布。为此,可将表示像素强度的直方图进行拉伸,将其平坦化。如下:

图来自维基百科

实验数据

本节的实验数据来自维基百科,原图如下:

其直方图为:

使用查找表来拉伸直方图

在图像处理中,直方图均衡化一般用来均衡图像的强度,或增加图像的对比度。在介绍使用直方图均衡化来拉伸图像的直方图之前,先介绍使用查询表的方法。

观察上图中原始图像的直方图,很容易发现大部分强度值范围都没有用到。因此先检测图像非 0 的最低( imin )强度值和最高( imax )强度值。将最低值 imin 设为 0 ,最高值 imax 设为 255 。中间的按255.0*(i-imin)/(imax-imin)+0.5)的形式设置。

实现的任务主要集中在查询表的创建中,代码如下:

minBinNo, maxBinNo = 0, 255#计算从左起第一个不为0的直方图位置for binNo, binValue in enumerate(hist): if binValue != 0:minBinNo = binNobreak#计算从右起第一个不为0的直方图位置for binNo, binValue in enumerate(reversed(hist)): if binValue != 0:maxBinNo = 255-binNobreakprint minBinNo, maxBinNo#生成查找表,方法来自参考文献1第四章第2节for i,v in enumerate(lut):print iif i < minBinNo:lut[i] = 0elif i > maxBinNo:lut[i] = 255else:lut[i] = int(255.0*(i-minBinNo)/(maxBinNo-minBinNo)+0.5)

查询表创建完成后,就直接调用相应的OpenCV函数即可,这里调用的是cv2.LUT函数:#计算result = cv2.LUT(image, lut)

cv2.LUT函数只有两个参数,分别为输入图像和查找表,其返回处理的结果,完整代码如下:

#coding=utf-8import cv2import numpy as npimage = cv2.imread("D:/test/unequ.jpg", 0)lut = np.zeros(256, dtype = image.dtype )#创建空的查找表hist= cv2.calcHist([image], #计算图像的直方图 [0], #使用的通道 None, #没有使用mask [256], #it is a 1D histogram [0.0,255.0])minBinNo, maxBinNo = 0, 255#计算从左起第一个不为0的直方图柱的位置for binNo, binValue in enumerate(hist): if binValue != 0:minBinNo = binNobreak#计算从右起第一个不为0的直方图柱的位置for binNo, binValue in enumerate(reversed(hist)): if binValue != 0:maxBinNo = 255-binNobreakprint minBinNo, maxBinNo#生成查找表,方法来自参考文献1第四章第2节for i,v in enumerate(lut):print iif i < minBinNo:lut[i] = 0elif i > maxBinNo:lut[i] = 255else:lut[i] = int(255.0*(i-minBinNo)/(maxBinNo-minBinNo)+0.5)#计算result = cv2.LUT(image, lut)cv2.imshow("Result", result)cv2.imwrite("LutImage.jpg", result)cv2.waitKey(0)cv2.destroyAllWindows()

直方图结果如下,可以看到原来占的区域很小的直方图尖峰被移动了:

处理结果为:

关于直方图的绘制,请参考 这篇文章 。

直方图均衡化

介绍

有时图像的视觉上的缺陷并不在强度值集中在很窄的范围内。而是某些强度值的使用频率很大。比如第一幅图中,灰度图中间值的占了很大的比例。

在完美均衡的直方图中,每个柱的值都应该相等。即 50% 的像素值应该小于 128 , 25% 的像素值应该小于 64 。总结出的经验可定义为:在标准的直方图中 p% 的像素拥有的强度值一定小于或等于 255×p% 。将该规律用于均衡直方图中:强度i 的灰度值应该在对应的像素强度值低于 i 的百分比的强度中。因此,所需的查询表可以由下面的式子建立:

lut[i] = int(255.0 *p[i]) #p[i]是是强度值小于或等于i的像素的数目。

p[i]即直方图累积值,这是包含小于给点强度值的像素的直方图,以代替包含指定强度值像素的数目。比如第一幅图像的累计直方图如下图中的蓝线:

而完美均衡的直方图,其累积直方图应为一条斜线,如上图中均衡化之后的红线。

更专业一点 ,这种累积直方图应称为累积分布(cumulative distribition)。在NumPy中有一个专门的函数来计算。这在NumPy实现直方图均衡化一节中介绍。

通过上面的介绍,应该可以明白,直方图均衡化就是对图像使用一种特殊的查询表。在第三个例子中可以看到使用查询表来获得直方图均衡化的效果。 通常来说,直方图均衡化大大增加了图像的表象。但根据图像可视内容的不同,不同图像的直方图均衡化产生的效果不尽相同。

直方图均衡化之OpenCV函数实现

用OpenCV实现直方图均衡化很简单,只需调用一个函数即可:

img = cv2.imread('图像路径',0)equ = cv2.equalizeHist(img)cv2.imshow('equ',equ)

这样图像就均衡化了。可以通过 直方图的计算与显示 这篇文章中介绍的方法将结果绘制出来。

直方图均衡化之NumPy函数实现

通过前面的介绍,可以明白直方图均衡化就是用一种特殊的查找表来实现的。所以这里用NumPy函数,以查找表的方式手动实现图像直方图的均衡化:

#coding=utf-8import cv2import numpy as npimage = cv2.imread("D:/test/unequ.jpg", 0)lut = np.zeros(256, dtype = image.dtype )#创建空的查找表hist,bins = np.histogram(image.flatten(),256,[0,256]) cdf = hist.cumsum() #计算累积直方图cdf_m = np.ma.masked_equal(cdf,0) #除去直方图中的0值cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())#等同于前面介绍的lut[i] = int(255.0 *p[i])公式cdf = np.ma.filled(cdf_m,0).astype('uint8') #将掩模处理掉的元素补为0#计算result2 = cdf[image]result = cv2.LUT(image, cdf)cv2.imshow("OpenCVLUT", result)cv2.imshow("NumPyLUT", result2)cv2.waitKey(0)cv2.destroyAllWindows()

最终结果

验证

比较查找表和OpenCV直方图均衡化生成的直方图:

可以看出,总体上来看是吻合的,但OpenCV中函数的实现 可能 还有一些细微的差别(有空去翻下源码,不过今天就先到这里了)。

参考资料:

1、《Opencv2 Computer Vision Application Programming Cookbook》

2、《OpenCV References Manule》

如果觉得本文写的还可以的话,请轻点“顶”,您的支持是我写下去的动力之一。未完待续。。。如有错误请指正,本人会虚心接受并改正!谢谢!欢迎加入我爱机器学习QQ14群:336582044

微信扫一扫,关注我爱机器学习公众号

python opencv 直方图均衡_OpenCV-Python教程(10、直方图均衡化)相关推荐

  1. Python+OpenCV:图像对比度受限自适应直方图均衡化(CLAHE, Contrast Limited Adaptive Histogram Equalization)

    Python+OpenCV:图像对比度受限自适应直方图均衡化(CLAHE, Contrast Limited Adaptive Histogram Equalization) ############ ...

  2. Python OpenCV学习笔记之:图像直方图均衡化

    # -*- coding: utf-8 -*- """ 图像直方图均衡化 """ import cv2 import numpy as np ...

  3. vs python opencv配置_OPENCV入门教程二:opencv+VS2015开发环境配置

    在该cpp文件中输入一下代码 #include #include #include #include #include using namespace cv; using namespace std; ...

  4. python opencv 摄像头_opencv python中摄像头参数的设置

    我正在使用Windows7 64位操作系统以及Python3和OpenCV.我的电脑连接到以下型号的两个罗技网络摄像头: 1)罗技高清网络摄像头C615 2) 罗技QuickCam Pro 9000 ...

  5. python opencv保存图片_OpenCV Python 保存图片

    By 凌顺 2019年9月12日 本示例使用的OpenCV版本是:4.1.1 运行Python的编辑器:Jupyter notebook 示例目的 通过无损和有损的方式进行图片保存. 实现代码 1,加 ...

  6. Python+Opencv图像处理新手入门教程(二):颜色空间转换,图像大小调整,灰度直方图

    一步一步来吧 上一节:Python+Opencv图像处理新手入门教程(一):介绍,安装与起步 1.什么是图像 对于计算机而言,图像的本质是一个由像素点构成的矩阵. 例如我们用肉眼很容易分辨一辆汽车的后 ...

  7. Python+Opencv图像处理新手入门教程(三):阈值与二值化

    一步一步来吧 上一节: Python+Opencv图像处理新手入门教程(二):颜色空间转换,图像大小调整,灰度直方图 1.Intro 今天这节我们主要研究利用阈值处理图像.例如对于输入图像: 如何做一 ...

  8. python做直方图-python OpenCV学习笔记实现二维直方图

    本文介绍了python OpenCV学习笔记实现二维直方图,分享给大家,具体如下: 官方文档 – https://docs.opencv.org/3.4.0/dd/d0d/tutorial_py_2d ...

  9. Python+Opencv图像处理新手入门教程(四):视频内容的读取与导出

    一步一步来吧 上一节: Python+Opencv图像处理新手入门教程(三):阈值与二值化 1.Intro 今天这节我们主要看怎么利用opencv读取并处理视频中的内容. 2.VideoCapture ...

  10. 【OpenCV 例程200篇】46. 直方图均衡化

    [OpenCV 例程200篇]46. 直方图均衡化 欢迎关注 『OpenCV 例程200篇』 系列,持续更新中 欢迎关注 『Python小白的OpenCV学习课』 系列,持续更新中 图像直方图是反映图 ...

最新文章

  1. Access外键 级联更新、删除
  2. 【scala初学】scala 控制 for while match if
  3. 枣庄三中高考2021成绩查询,2021枣庄中考成绩查询系统入口
  4. Linux怎么更新镜像,利用 Zsync 更新已有的 Ubuntu ISO 镜像
  5. java word转html 乱码 poi,java word转html poi
  6. 20个正则表达式必知(前端开发)
  7. 监听程序当前无法识别连接符中请求的服务_[Servlet] 18 监听器
  8. 理论应用实例水杯_PLC应用,3个PID控制实例讲解,想不会都难!
  9. Android快速批量打渠道包(AndroidManifestModifier)
  10. 商品包含资源和劳动两部分内容
  11. python随机出题_什么软件可以自制题库随机出题?怎么操作
  12. linux下kegg注释软件,KEGG pathway注释过程
  13. 什么是云服务和云服务端开发?
  14. 基于CH340G的STC单片机一键下载电路
  15. 洛谷P2178 [NOI2015]品酒大会 后缀数组+单调栈
  16. 对话系统调查:近期进展与新前沿
  17. Python心形图-采用turtle模块画心形
  18. 5个值得关注的L1公链
  19. EMI-EMC设计注意事项
  20. 已搭建独立博客,请移步下面网址

热门文章

  1. 阿里云IoT投入智物智造战略 三年赋能10亿设备改造10万家数字工厂
  2. FreeNAS 简介
  3. Settings Preference 的理解
  4. Unix/Linux下的Curses库开发指南——第一章 Curses库开发简介
  5. java中的持有引用
  6. python地产成本_Python3抓取 深圳房地产均价数据,通过真实数据为购置不动产做决策分析(二)...
  7. web项目打war包方法 两步解决(极其简单方便)
  8. 渗透测试-越权漏洞之垂直越权和水平越权
  9. 区块链入门者的五本必读书籍
  10. LNK1181:无法打开输入文件“release/.obj“