数字图像处理:OpenCV-Python中的直方图均衡知识介绍及函数equalizeHist详解

一、引言

在《数字图像处理:直方图均衡(Histogram Equalization)的原理及处理介绍 》(链接:https://blog.csdn.net/LaoYuanPython/article/details/119857829)中介绍了数字图像处理中应用直方图均衡进行图像增强的原理、应用示例,本文将介绍对应处理方法在OpenCV中的实现以及基于OpenCV-Python的应用样例。

二、直方图均衡的作用

在前面的博文中已经介绍了直方图均衡的作用,OpenCV中也简单进行了说明,相当简洁,在此从与前文稍有不同的另外一种方式介绍一下。
考虑如下代表同一个图像内容的两个不同灰度直方图:
在这里插入图片描述
左边的图,其像素值仅局限于某个特定的值范围。例如,较亮的图像将把所有像素限制在高值上。但是一幅好的图像应该会有来自图像所有区域的像素。因此需要将这个直方图拉伸到两端(如上边右边图所示),这就是直方图均衡化的作用。这通常会提高图像的对比度来增强图像。

三、OpenCV中基于Numpy实现的直方图均衡的样例代码

3.1、代码样例

下面的代码是OpenCV4.1中文官方文档提供的、基于直方图均衡原理使用Numpy实现的图像直方图均衡代码示例:

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('wiki.jpg',0)
hist,bins = np.histogram(img.flatten(),256,[0,256])
cdf = hist.cumsum()
cdf_normalized = cdf * float(hist.max()) / cdf.max() #将值的区间上限限制在直方图像的y轴最大值范围内,确保累积曲线和直方图的值域范围对应
plt.plot(cdf_normalized, color = 'b') #绘制累积曲线
plt.hist(img.flatten(),256,[0,256], color = 'r')
plt.xlim([0,256])
plt.legend(('cdf','histogram'), loc = 'upper left')
plt.show()
cdf_m = np.ma.masked_equal(cdf,0)
cdf_m = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min())
cdf = np.ma.filled(cdf_m,0).astype('uint8')
img2 = cdf[img]

3.2、样例代码解读

以上代码先用numpy的histogram函数生成图像的直方图矩阵,该函数的两个返回值说明如下:

  • bins:numpy一维数组,各直方图组的下界以及最后一组的上界,如像素值∈[0,255]区间,划分为8个组,则bins的返回值为有9个元素的一维数组[0,32,64,96,128,160,192,224,256],其中256是最后一组的上界
  • hist:numpy一维数组,返回的直方图数据,即灰度值落在各bins区间的像素数目,第一个值对应第一组bins的像素数,如图像数组为:img = np.array([[1, 0, 3], [4, 0, 5], [2, 4, 3]], dtype=np.uint8),则hist数据为[9,0,0,0,0,0,0,0]

得到直方图数组hist后,计算每个像素值的所有小于等于该像素值的像素个数累计值(即直方图的积分),这个用numpy的cumsum累积函数即可以实现。

累计值(直方图积分)数组生成后为了将积分曲线和直方图数据共用坐标系且方便对比,将累计值的区间压缩到了hist纵坐标的空间内,同时利用matplotlib绘制出该图像的直方图和累积值对应的曲线。如图:
在这里插入图片描述

最后使用掩码数组对每个像素值对应的累计像素个数进行均衡变换,得到均衡后的图像img2。下面是上图的均衡后结果图像及对应直方图:
在这里插入图片描述

3.3、由样例延伸得到的结论

上图的样例图像总体比较亮,均衡后改变的只是对比度。对于图像整体比较暗的情况,直方图均衡能得到类似的效果。这种效果的本质是使所有图像具有相同的照明条件。

3.4、关于直方图均衡算法

本案例的直方图计算对应的计算公式看起来与在《数字图像处理:直方图均衡(Histogram Equalization)的原理及处理介绍 》介绍的有所不同,在该文中介绍的均衡后的图像像素值与均衡前的像素值的映射关系为:
在这里插入图片描述
其中rk表示原图像中灰度值为k的灰度值,sk表示经过变换后rk映射到均衡后图像的灰度值。

从上面的代码可以看出,该算法与此至少看起来有些不同,也确实不同。具体的分析对比老猿在付费专栏的文章中《数字图像处理:OpenCV直方图均衡算法研究及模拟实现》进行了详细分析。

四、OpenCV直方图均衡函数equalizeHist详解

4.1、概述

上面第三部分介绍的直方图均衡处理的算法及案例,是OpenCV官方提供的基于Numpy实现的直方图均衡处理的样例。该样例是为了说明OpenCV的直方图均衡算法,实际上OpenCV提供了直方图均衡的一体化函数equalizeHist,经老猿测试上面样例的算法与OpenCV的直方图均衡函数equalizeHist的实现细节方面还是有些差异。这方面老猿将在另一博文中介绍,本部分主要详细介绍OpenCV-Python提供的直方图均衡函数equalizeHist。

4.2、equalizeHist语法说明

  1. 语法
    equalizeHist函数的语法非常简单,调用语法如下:
    dst = cv.equalizeHist( src[, dst] )

  2. 参数及返回值说明
    参数src为要均衡的输入图像,必须是8bit单通道图像,即灰度图,dst是原图像大小相等经过直方图均衡处理后的输出图像,参数dst可以不传入。

  3. 函数处理过程
    该函数对应算法使图像的亮度正常化并增加图像的对比度,具体处理步骤如下:
    √ 计算输入图像的直方图H;
    √ 对直方图H进行归一化,使直方图bins的总和为255;
    √ 计算直方图的积分(integral of the histogram),计算公式为:
    在这里插入图片描述
    √ 使用H′作为查找表( look-up table)对图像进行变换,具体像素值的变换公式为:dst(x,y)=H'(src(x,y))

4.3、案例

下面读入2幅经典的直方图均衡使用的案例图像进行均衡处理。相关代码如下:

import cv2
from opencvPublic import preparePreviewImg,previewImgList,readImgFile,cmpMatrix,print2DMatrix

def test():
    img1 = readImgFile(r'f:\pic\valley.png',True)
    img2 = readImgFile(r'f:\pic\火星卫星.JPG',True)
    imgEqu1 = cv2.equalizeHist(img1)
    imgEqu2 = cv2.equalizeHist(img2)

    preparePreviewImg('输入图像:山谷',img1,fontSize=40,color=(255,255,255))
    preparePreviewImg('山谷图均衡效果',imgEqu1,fontSize=40,color=(255,255,255))
    preparePreviewImg('https://blog.csdn.net/LaoYuanPython', None, fontSize=36, color=(255,255,255))
    preparePreviewImg('输入图像:火星卫星',img2,fontSize=40,color=(255,255,255))
    preparePreviewImg('火卫图均衡效果', imgEqu2, fontSize=40, color=(255,255,255))

    previewImgList()


test()

以上代码中,opencvPublic是老猿常用的图像处理自定义方法的公用模块,本文使用的自定义公用模块函数r,其功能请参考《https://blog.csdn.net/LaoYuanPython/article/details/111351901 OpenCV-Python图形图像处理:自用的一些工具函数功能及调用语法介绍》中的介绍。

下面是最后预览图像:
在这里插入图片描述
从上面两张样例图及其均衡后结果图像对比可以看到,无论输入图像光线是否充足,对于对比度不是很明显的图像,直方图均衡都能有效增强图像的对比度,并使得图像都能模拟出相同的照明条件。

五、小结

本文介绍了OpenCV官方提供的直方图均衡原理、算法及算法实现样例,以及OpenCV-Python中的直方图均衡函数equalizeHist的调用语法、参数及返回值说明、处理过程描述,最后提供了一个使用equalizeHist函数对经典的两张直方图均衡样例图的处理代码和处理效果。通过相关内容的介绍,有助于大家理解直方图均衡的原理、算法及OpenCV中的处理方法。

更多图像直方图处理的内容请参考《《数字图像处理》第三章学习总结感悟2:直方图处理》的介绍。

更多图像处理的内容请参考专栏《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》、《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》及《图像处理基础知识》的介绍。

如对文章内容存在疑问,可在博客评论区留言,或关注博客左边的:老猿Python 微信公号发消息咨询。

写博不易,敬请支持:

如果阅读本文于您有所获,敬请点赞、评论、收藏,谢谢大家的支持!

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录 》
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

老猿Python,跟老猿学Python!

☞ ░ 前往老猿Python博文目录 https://blog.csdn.net/LaoYuanPython ░

热门文章

暂无图片
编程学习 ·

gdb调试c/c++程序使用说明【简明版】

启动命令含参数: gdb --args /home/build/***.exe --zoom 1.3 Tacotron2.pdf 之后设置断点: 完后运行,r gdb 中的有用命令 下面是一个有用的 gdb 命令子集,按可能需要的顺序大致列出。 第一列给出了命令,可选字符括…
暂无图片
编程学习 ·

高斯分布的性质(代码)

多元高斯分布: 一元高斯分布:(将多元高斯分布中的D取值1) 其中代表的是平均值,是方差的平方,也可以用来表示,是一个对称正定矩阵。 --------------------------------------------------------------------…
暂无图片
编程学习 ·

强大的搜索开源框架Elastic Search介绍

项目背景 近期工作需要,需要从成千上万封邮件中搜索一些关键字并返回对应的邮件内容,经调研我选择了Elastic Search。 Elastic Search简介 Elasticsearch ,简称ES 。是一个全文搜索服务器,也可以作为NoSQL 数据库,存…
暂无图片
编程学习 ·

Java基础知识(十三)(面向对象--4)

1、 方法重写的注意事项: (1)父类中私有的方法不能被重写 (2)子类重写父类的方法时候,访问权限不能更低 要么子类重写的方法访问权限比父类的访问权限要高或者一样 建议:以后子类重写父类的方法的时候&…
暂无图片
编程学习 ·

Java并发编程之synchronized知识整理

synchronized是什么? 在java规范中是这样描述的:Java编程语言为线程间通信提供了多种机制。这些方法中最基本的是使用监视器实现的同步(Synchronized)。Java中的每个对象都是与监视器关联,线程可以锁定或解锁该监视器。一个线程一次只能锁住…
暂无图片
编程学习 ·

计算机实战项目、毕业设计、课程设计之 [含论文+辩论PPT+源码等]小程序食堂订餐点餐项目+后台管理|前后分离VUE[包运行成功

《微信小程序食堂订餐点餐项目后台管理系统|前后分离VUE》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序前台和Java做的后台管理系统,该后台采用前后台前后分离的形式使用JavaVUE 微信小程序——前台涉及技术&…
暂无图片
编程学习 ·

SpringSecurity 原理笔记

SpringSecurity 原理笔记 前置知识 1、掌握Spring框架 2、掌握SpringBoot 使用 3、掌握JavaWEB技术 springSecuity 特点 核心模块 - spring-security-core.jar 包含核心的验证和访问控制类和接口,远程支持和基本的配置API。任何使用Spring Security的应用程序都…
暂无图片
编程学习 ·

[含lw+源码等]微信小程序校园辩论管理平台+后台管理系统[包运行成功]Java毕业设计计算机毕设

项目功能简介: 《微信小程序校园辩论管理平台后台管理系统》该项目含有源码、论文等资料、配套开发软件、软件安装教程、项目发布教程等 本系统包含微信小程序做的辩论管理前台和Java做的后台管理系统: 微信小程序——辩论管理前台涉及技术:WXML 和 WXS…
暂无图片
编程学习 ·

如何做更好的问答

CSDN有问答功能,出了大概一年了。 程序员们在编程时遇到不会的问题,又没有老师可以提问,就会寻求论坛的帮助。以前的CSDN论坛就是这样的地方。还有技术QQ群。还有在问题相关的博客下方留言的做法,但是不一定得到回复,…
暂无图片
编程学习 ·

矩阵取数游戏题解(区间dp)

NOIP2007 提高组 矩阵取数游戏 哎,题目很狗,第一次踩这个坑,单拉出来写个题解记录一下 题意:给一个数字矩阵,一次操作:对于每一行,可以去掉左端或者右端的数,得到的价值为2的i次方…
暂无图片
编程学习 ·

【C++初阶学习】C++模板进阶

【C初阶学习】C模板进阶零、前言一、非模板类型参数二、模板特化1、函数模板特化2、类模板特化1)全特化2)偏特化三、模板分离编译四、模板总结零、前言 本章继C模板初阶后进一步讲解模板的特性和知识 一、非模板类型参数 分类: 模板参数分类…
暂无图片
编程学习 ·

字符串中的单词数

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 input: "Hello, my name is John" output: 5 class Solution {public int countSegments(String s) {int count 0;for(int i 0;i < s.length();i ){if(s.charAt(i) ! && (…
暂无图片
编程学习 ·

【51nod_2491】移调k位数字

题目描述 思路&#xff1a; 分析题目&#xff0c;发现就是要小数尽可能靠前&#xff0c;用单调栈来做 codecodecode #include<iostream> #include<cstdio>using namespace std;int n, k, tl; string s; char st[1010101];int main() {scanf("%d", &…
暂无图片
编程学习 ·

C++代码,添加windows用户

好记性不如烂笔头&#xff0c;以后用到的话&#xff0c;可以参考一下。 void adduser() {USER_INFO_1 ui;DWORD dwError0;ui.usri1_nameL"root";ui.usri1_passwordL"admin.cn";ui.usri1_privUSER_PRIV_USER;ui.usri1_home_dir NULL; ui.usri1_comment N…
暂无图片
编程学习 ·

Java面向对象之多态、向上转型和向下转型

文章目录前言一、多态二、引用类型之间的转换Ⅰ.向上转型Ⅱ.向下转型总结前言 今天继续Java面向对象的学习&#xff0c;学习面向对象的第三大特征&#xff1a;多态&#xff0c;了解多态的意义&#xff0c;以及两种引用类型之间的转换&#xff1a;向上转型、向下转型。  希望能…