在理解直方图均衡化的过程中,参考了一些书籍和博客,让人困惑的是,笔者对于直方图的理解还是停留在表面,并没有深入理解其内涵。因此,本文拟结合图片对直方图的概念进行阐述,并给出其Python实现,最后对她背后所蕴含的一些科学思维,谈谈自己的一些看法。

什么是直方图?

对于一副灰度图像I,她的每一个像素点I(x,y)都有一个灰度值,一般情况下可能的灰度取值有2^8=256个(0,1,...,255)。如果我们统计出灰度值r在I中出现的次数n,并对其进行归一化(n/N,N是所有灰度值出现次数的总和),这样我们就可以得到像素r在I中出现的概率p(r)。如果对每一个可能的灰度取值r都做同样的处理,我们可以得到如图1左侧所示的概率分布曲线,该曲线就是我们常说的直方图。

图1 直方图均衡化目标

什么是直方图均衡化?

通常情况下一副图像I的直方图如图1左侧所示,每一个灰度值r出现的概率不是相等的,这样会导致图像的一些细节信息不够突出,而直方图均衡化就是对灰度值r进行如下变换s=T(r),使得变换后的灰度分布如图1右侧所示(也就是说,每一个灰度值出现的概率是想同的),这样能够发现一些原先肉眼很难发现的细节,如图2所示(读者可以自己体会下)。说到这里,一般也就结束了,但是我们真的理解了吗?如何更好的理解呢?下面简要介绍一下笔者的理解方式。

假设我们有四个灰度级a,b,c,d,做个类比的话可以将她们理解为四个描述情感的词喜、怒、哀、乐。一般情况下我们得到的直方图可认为是p(a)=0.5,p(b)=0.5,p(c)=0,p(d)=0,而均衡化后的直方图是p(a)=0.25,p(b)=0.25,p(c)=0.25,p(d)=0.25. 如果我们以均衡化前的词描述人的情感则只有喜、怒,而均衡化后的词则有喜、怒、哀、乐。试问,哪种情形能够描述人更细微的情感变化呢?这也是笔者认为直方图均衡化之后能够描述更多图像细节的原因。

更进一步,如果一般情况下我们得到的直方图是p(a)=0.4,p(b)=0.4,p(c)=0.1,p(d)=0.1,那这按我们的理解意味什么呢?意味着大部分情况用喜、怒描述人的情感,而哀、乐几乎不用,当然了,如果能够自由运用喜、怒、哀、乐来描述人的情感是最好的哦。

图2 直方图均衡化示意图(左图变换前,右图变换后)

直方图均衡化的数学原理

笔者曾经是个数学控,总是认为凡事都应该从数学的基本原理出发,然而运用数学推理得出我们期望的结论。然而此刻,觉得自己的想法从根本上是错误的。下面以直方图均衡化数学原理为例进行说明。

我们直方图均衡化的目标如图1所示,那么怎么做到呢?这中间的约束条件又是什么呢(世上没有绝对的自由)?

可以设r原始图像灰度级,s均衡化后图像灰度级,不失一般性可以假设r的取值范围为[0,1]。那么什么是必须满足的约束条件呢?均衡化前后灰度级的意义不能变,也就是说变换前灰度级的含义是由黑到白,那么变换后也应该如此。此外,最好变换前后灰度级的取值范围一致。为使变换后的灰度仍保持从黑到白的单一变化顺序,且变换范围与原先一致,以避免整体变亮或变暗。必须规定:

(1)变换函数T(r)在r属于[0,1]范围内是单值、单调增函数;

(2)对于r属于[0,1],s=T(r)也属于[0,1]

图3 直方图均衡化原理示意图

这两条规定是满足我们均衡化要求的数学化描述(如果要应用数学的话,就应该将我们要求、目标等转化为数学语言进行描述)。

直方图均衡就是通过灰度变换函数s=T(r)将原图像直方图p (r)改变为均匀分布的直方图p(s)。由图3可知,在满足两条规定的前提下,因为s=T(r)(也就是说,r确定,s确定),结合概率论可知p (r)dr=p(s)ds又因为直方图均衡化后,有:p(s) = 1, s属于[0,1],因此,ds=p(r)dr。两边取积分有

这样我们就找到了s、r之间的映射关系。

直方图均衡化Python实现

由s、r之间的映射关系

可知,对于一副输入灰度图像I,我们首先计算其p(r),然后计算每一个灰度级r对应的

def histeq(img,nbr_bins=256):
""" Histogram equalization of a grayscale image. """

# 获取直方图p(r)
imhist, bins = histogram(img.flatten(), nbr_bins, normed = True)

# 获取T(r)
cdf = imhist.cumsum() # cumulative distribution function
cdf = 255 * cdf /cdf[-1] # 获取s,并用s替换原始图像对应的灰度值
result = interp(img.flatten(),bins[:-1],cdf) return result.reshape(img.shape),cdf

一些思考

笔者以前有这样一种误解:以为所有的理论都可以从基本的数学原理推导得出,于是在碰到新问题的时候,总是试图搞清楚各个数学公式的来源及其物理含义,而忽略了这些数学运作背后的目的是什么!这样的一个缺点就是,今天能够理解的理论,过了几天就不理解了。

现在笔者的一些体会是,如果按照以下思路理解问题,能够起到事半功倍的效果(有点夸张的成分在里面):首先搞清楚问题的来源、其次知晓解决问题的目的是什么、然后将问题数学化描述(时刻注意约束条件)、最后求解该数学问题。

总结:通常情况下,如果我们能够将前三个步骤走完,最后的求解问题通过借助于现有软件、算法,应该是水到渠成的事。(本人非数学专业,对怎么求解一个数学问题,通常只关心输入、输出、以及约束条件)

参考文献:

《Programming Computer Vision with Python》

图解直方图均衡化及其Python实现的更多相关文章

  1. 数学之路-python计算实战(14)-机器视觉-图像增强(直方图均衡化)

    我们来看一个灰度图像,让表示灰度出现的次数,这样图像中灰度为 的像素的出现概率是  是图像中全部的灰度数, 是图像中全部的像素数,  实际上是图像的直方图,归一化到 . 把  作为相应于  的累计概率 ...

  2. Python实现图像直方图均衡化算法

    title: "Python实现图像直方图均衡化算法" date: 2018-06-12T17:10:48+08:00 tags: [""] categorie ...

  3. 灰度图的直方图均衡化(Histogram Equalization)原理与 Python 实现

    原理 直方图均衡化是一种通过使用图像直方图,调整对比度的图像处理方法:通过对图像的强度(intensity)进行某种非线性变换,使得变换后的图像直方图为近似均匀分布,从而,达到提高图像对比度和增强图片 ...

  4. python——直方图均衡化

    from PIL import Image from pylab import * from numpy import * def histeq(im,nbr_bins = 256): "& ...

  5. python实现直方图均衡化,理想高通滤波与高斯低通滤波

    写在前面 HIT大三上学期视听觉信号处理课程中视觉部分的实验二,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验二. 由于时间紧张,代码没有进行任何优化, ...

  6. 灰度直方图均衡化----python实现

    直方图均衡化是使用图像直方图进行对比度调整的图像处理的方法. 该方法通常会增加许多图像的整体对比度,尤其是当图像的可用数据由接近的对比度值表示时. 通过这种调整,强度可以更好地分布在直方图上. 这允许 ...

  7. OpenCV-Python教程(10、直方图均衡化)

    相比C++而言,Python适合做原型.本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV函数的不同之处.这篇文章介绍在Python中使用OpenCV和NumP ...

  8. 图像增强算法(直方图均衡化、拉普拉斯、Log、伽马变换)

    一.图像增强算法原理 图像增强算法常见于对图像的亮度.对比度.饱和度.色调等进行调节,增加其清晰度,减少噪点等.图像增强往往经过多个算法的组合,完成上述功能,比如图像去燥等同于低通滤波器,增加清晰度则 ...

  9. OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...

随机推荐

  1. Flask最佳实践

    https://zhuanlan.zhihu.com/p/22774028?refer=python-cn

  2. Tab切换

    代码 <!DOCTYPE html> <html lang="en"><head> <meta charset="UTF-8&q ...

  3. springmvc 接受特殊类型字段的处理方法

    springmvc接受前台传入的数据时如果该字段类型无法被封装(如Date),则会出现400 Bad Request错误,解决方法如下. 1.在需要处理的字段前加上注解: @DateTimeForma ...

  4. Linux学习一:安装/配置vi,熟悉gcc/vi

    1.安装的ubuntu14,进入桌面,ctrl+alt+t进入终端. 获得root权限: $sudo passwd root 输入密码 (注意:输入的和windows下不一样不会显示的,尽管输入就行. ...

  5. win7双系统安装ubuntu并配置常用软件

    首先在win7下磁盘清理出来空间具体方法找度娘就行了. 下面开始准备安装: 1.下载easyBCD 2.打开:添加新条目--NeoGub--安装 3.点击配置  修改menu.lst title In ...

  6. AX7: Get started developing

    This blog will show how you can start making a customization in AX 7 by showing you the steps needed ...

  7. 第一个ruby程序

    老实说不是很喜欢去讨论ruby和python的对比,似乎总是把两个语言放在对立的位置上,我觉得没有必要,同样是动态语言,同样是解释型脚本语言,很多特性都是互相影响的,语言本身也在不断进化,我们更应该关 ...

  8. 构建最小的docker容器

    创建一个最小的基本镜像: tar cv --files-from /dev/null | sudo docker import - skycn/base 建一个hello.go: package ma ...

  9. NHibernate系列文章二十五:NHibernate查询之Query Over查询(附程序下载)

    摘要 这一篇文章介绍在NHibernate 3.2里引入的Query Over查询,Query Over查询跟Criteria查询类似.首先创建IQueryOver对象,然后通过调用该对象的API函数 ...

  10. C# 调用Adodb对Access数据库执行批量插入

    public void BatchInsertIntoAccess(DataTable dt) { ADODB.Connection cn; ADODB.Recordset rs; string st ...