图像直方图以及灰度与彩色图像的直方图均衡化
图像直方图:

图像的直方图用来表征该图像像素值的分布情况。用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目。

图像直方图图形化显示不同的像素值在不同的强度值上的出现频率,对于灰度图像来说强度范围为[0~255]之间,对于RGB的彩色图像可以独立显示三种颜色的图像直方图。

同时直方图是用来寻找灰度图像二值化阈值常用而且是有效的手段之一,如果一幅灰度图像的直方图显示为两个波峰,则二值化阈值应该是这两个波峰之间的某个灰度值。

并且直方图是调整图像对比度的重要依据,直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。

下面我将介绍如何用python绘制图像直方图,以及直方图均衡化的原理并给出灰度图与彩色图的直方图均衡化。

使用python绘制图像直方图:

在之前写的《python基本图像操作》中已经提到了如何用python去绘制图像的直方图,python的优点就是具有众多扩展库和更加易用,所以可以避免陷入算法细节从更宏观的角度实现自己的想法,所以用python绘制直方图非常简单:

使用Matplotlib绘制直方图

(灰度)图像的直方图可以使用 hist() 函数绘制:

hist() 函数的第二个参数指定小区间的数目。需要注意的是,因为 hist() 只接受一维数组作为输入,所以我们在绘制图像直方图之前,必须先对图像进行压平处理。flatten() 方法将任意数组按照行优先准则转换成一维数组。

# -*- coding: utf-8 -*-from PIL import Imagefrom pylab import *# 读取图像到数组中,并灰度化
im = array(Image.open('./source/test.jpg').convert('L'))# 直方图图像
hist(im.flatten(),128)# 显示
show()

测试图片

Test.jpg

运行结果

直方图的原理也很简单了,自己实现也非常简单,所以也没有必要再过多叙述,具体细节可以去看一下C++的实现。

直方图均衡化(Histogram Equalization):

概述:

直方图均衡化是非常有用的一种变换,直方图均衡化是指将一幅图像的灰度直方图变平,使变换后的图像中每个灰度值的分布概率都相同。在对图 
像做进一步处理之前,直方图均衡化通常是对图像灰度值进行归一化的一个非常好的方法,并且可以增强图像的对比度。

如果一副图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。直方图均衡化就是一种能仅靠输入图像直方图信息自动达到这种效果的变换函数。它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像原取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。

图像对比度增强的方法可以分成两类:一类是直接对比度增强方法;另一类是间接对比度增强方法。直方图拉伸和直方图均衡化是两种最常见的间接对比度增强方法。直方图拉伸是通过对比度拉伸对直方图进行调整,从而“扩大”前景和背景灰度的差别,以达到增强对比度的目的,这种方法可以利用线性或非线性的方法来实现;直方图均衡化则通过使用累积函数对灰度值进行“调整”以实现对比度的增强。

直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法。这种方法通常用来增加许多图像的局部对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。

这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。 
这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景杂讯的对比度并且降低有用信号的对比度;变换后图像的灰度级减少,某些细节消失;某些图像,如直方图有高峰,经处理后对比度不自然的过分增强。

实现:

直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。

直方图均衡化的基本思想是把原始图的直方图变换为均匀分布的形式,这样就增加了象素灰度值的动态范围从而可达到增强图像整体对比度的效果。设原始图像在(x,y)处的灰度为f,而改变后的图像为g,则对图像增强的方法可表述为将在(x,y)处的灰度f映射为g。在灰度直方图均衡化处理中对图像的映射函数可定义为:g = EQ (f),这个映射函数EQ(f)必须满足两个条件(其中L为图像的灰度级数):

  • (1)EQ(f)在0≤f≤L-1范围内是一个单值单增函数。这是为了保证增强处理没有打乱原始图像的灰度排列次序,原图各灰度级在变换后仍保持从黑到白(或从白到黑)的排列。

  • (2)对于0≤f≤L-1有0≤g≤L-1,这个条件保证了变换前后灰度值动态范围的一致性。

累积分布函数(cumulative distribution function,CDF)即可以满足上述两个条件,并且通过该函数可以完成将原图像f的分布转换成g的均匀分布。此时的直方图均衡化映射函数为:

累计分布函数(CDF)就是是概率密度函数(probability density function/pdf)的积分,相信学过概率论的同学对他一定不陌生:

累积分布函数(cumulative distribution function)定义 对连续函数,所有小于等于a的值,其出现概率的和。F(a)=P(x<=a)

所以总结一下灰度图直方图均衡化算法的步骤就是:

  • (1) 根据输入的灰度图像计算其原始直方图
  • (2) 对输入的原始直方图进行累加,计算其cdf
  • (3) 使用累计分布函数的插值计算新的灰度值(这里我使用比较常用的线性插值)

使用python及其数学库的话求直方图和cdf的方法已经为我们封装好了,所以实现起来代码量是很少的:

# -*- coding: utf-8 -*-from PIL import Imagefrom pylab import *#读取图像到数组中,并灰度化
im = array(Image.open('./source/test.jpg').convert('L'))#绘制原始直方图
subplot(231)hist(im.flatten(),256)#计算图像直方图(每个bins数组的区间值对应一个imhist数组中的强度值)
imhist,bins = histogram(im.flatten(),256,normed=True)#计算累积分布函数
cdf = imhist.cumsum()#累计函数归一化(由0~1变换至0~255)
cdf = cdf*255/cdf[-1]#绘制累计分布函数
subplot(232)plot(bins[:256],cdf)#依次对每一个灰度图像素值(强度值)使用cdf进行线性插值,计算其新的强度值
#interp(x,xp,yp) 输入原函数的一系列点(xp,yp),使用线性插值方法模拟函数并计算f(x)
im2 = interp(im.flatten(),bins[:256],cdf)#将压平的图像数组重新变成二维数组
im2 = im2.reshape(im.shape)# 显示均衡化之后的直方图图像
subplot(233)hist(im2.flatten(),256)#显示原始图像
gray()subplot(234)imshow(im)#显示变换后图像
subplot(236)imshow(im2)show()

运行结果

其中线性插值公式是最常用、最简单的插值公式。线性插值和双线性插值是图形学中常用的技术,旋转变换后图片会有一些不连续点,就是通过双线性插值法解决的,之后我会单独写一篇博客进行详细介绍,这里简单介绍一下线性插值的原理:

处理分离的数据,如果想知道分离点之间的某些值,需要用到某种类型的插值。

使用线性插值,通过连接两点的线段找到X=2.7对应的Y值

0.7* (maxY-min Y)+minY=0.7*(20-10)+10=0.7*10+10=17

(14-minX)/(maxX-minX) =(14-13)/(16-13)=0.33

0.33* (maxY-minY)+minY=0.33*(46-35)+35=0.33*11+35=3.67+35=38.67

顺便说一下,基本所有的线性插值返回的都是浮点数。

所以我们使用插值技术利用离散的cdf得出新的灰度强度值。

彩色图像的直方图均衡化(Histogram Equalization):

一幅彩色图像由RGB三色通道构成,每个通道都是描述了该种颜色的强度(0-255)的一幅灰度图,所以比较简单的应用于彩色图像的均衡化就是把每个颜色通道均衡化之后进行合成,下面是我的具体实现:

# -*- coding: utf-8 -*-from PIL import Imagefrom pylab import *import copy# 读取图像到数组中
im = array(Image.open('./source/test.jpg'))#获取通道
r = im[:,:,0]g = im[:,:,1]b = im[:,:,2]#显示各个通道原始直方图,均值化之后的直方图以及累计分布函数
figure()#计算各通道直方图
imhist_r,bins_r = histogram(r,256,normed=True)
imhist_g,bins_g = histogram(g,256,normed=True)
imhist_b,bins_b = histogram(b,256,normed=True)subplot(331)hist(r.flatten(),256)subplot(332)hist(g.flatten(),256)subplot(333)hist(b.flatten(),256)#各通道累积分布函数
cdf_r = imhist_r.cumsum()
cdf_g = imhist_g.cumsum()
cdf_b = imhist_b.cumsum()#累计函数归一化(由0~1变换至0~255)
cdf_r = cdf_r*255/cdf_r[-1]
cdf_g = cdf_g*255/cdf_g[-1]
cdf_b = cdf_b*255/cdf_b[-1]#绘制累计分布函数subplot(334)plot(bins_r[:256],cdf_r)subplot(335)plot(bins_g[:256],cdf_g)subplot(336)plot(bins_b[:256],cdf_b)#绘制直方图均衡化之后的直方图im_r = interp(r.flatten(),bins_r[:256],cdf_r)im_g = interp(g.flatten(),bins_g[:256],cdf_g)im_b = interp(b.flatten(),bins_b[:256],cdf_b)# 显示直方图图像
subplot(337)hist(im_r,256)subplot(338)hist(im_g,256)subplot(339)hist(im_b,256)#显示原始通道图与均衡化之后的通道图
figure()gray()#原始通道图
im_r_s = r.reshape([im.shape[0],im.shape[1]])im_g_s = g.reshape([im.shape[0],im.shape[1]])im_b_s = b.reshape([im.shape[0],im.shape[1]])#均衡化之后的通道图
im_r = im_r.reshape([im.shape[0],im.shape[1]])im_g = im_g.reshape([im.shape[0],im.shape[1]])im_b = im_b.reshape([im.shape[0],im.shape[1]])subplot(231)imshow(im_r_s)subplot(232)imshow(im_g_s)subplot(233)imshow(im_b_s)subplot(234)imshow(im_r)subplot(235)imshow(im_g)subplot(236)imshow(im_b)#显示原始图像与均衡化之后的图像
figure()#均衡化之后的图像
im_p = copy.deepcopy(im)im_p[:,:,0] = im_rim_p[:,:,1] = im_gim_p[:,:,2] = im_bsubplot(121)imshow(im)subplot(122)imshow(im_p)show()

运行结果

figure1:RGB通道的原始直方图,cdf,均衡化后的直方图 

figure2:RGB通道的原始图像,均衡化后的图像 

figure3:原始图像,均衡化后的图像 

结语:

本篇博客介绍了图像直方图和图像直方图均衡化的原理和方法,希望我的博客对大家有所帮助~

python图像直方图与直方图均衡化相关推荐

  1. python图像直方图、获取每一个柱的个数_python数字图像处理实现直方图与均衡化...

    在图像处理中,直方图是非常重要,也是非常有用的一个处理要素. 在skimage库中对直方图的处理,是放在exposure这个模块中. 1.计算直方图 函数:skimage.exposure.histo ...

  2. python绘制灰度图片直方图-python数字图像处理实现直方图与均衡化

    在图像处理中,直方图是非常重要,也是非常有用的一个处理要素. 在skimage库中对直方图的处理,是放在exposure这个模块中. 1.计算直方图 函数:skimage.exposure.histo ...

  3. python绘制灰度图片直方图-python数字图像处理(9):直方图与均衡化

    在图像处理中,直方图是非常重要,也是非常有用的一个处理要素. 在skimage库中对直方图的处理,是放在exposure这个模块中. 1.计算直方图 函数:skimage.exposure.histo ...

  4. python计算机视觉-1.2.2 图像轮廓与直方图

    2018.6.30-http://python.jobbole.com/84956/ 备注:python-2.7.14 IDE:pycharm 1.2.2 图像轮廓和直方图 图像轮廓:因为绘制轮廓需要 ...

  5. opencv-python 绘制图像直方图及直方图均衡化

    1. 绘制图像的直方图   下面的程序给出了如何绘制一幅图像整体的直方图和每个通道的直方图 #-*- coding:utf-8 -*-import cv2 from matplotlib import ...

  6. Matlab数字图像处理 02 灰度变化(图像直方图、直方图均衡化、直方图匹配)

    第二章 灰度变化 2.1 图像的亮度.对比度和动态范围 2.1.1 亮度 2.1.2 对比度 2.1.3 动态范围 2.2 线性灰度变换 2.2.1 具有饱和处理的线性灰度变换 2.2.2 分段线性灰 ...

  7. Python,OpenCV进行直方图反投影

    Python,OpenCV进行直方图反投影 1. 效果图 2. 源码 参考 这篇博客将介绍Python,OpenCV中的直方图反投影.直方图反投影用于图像分割或在图像中查找感兴趣的对象. 简单地说,它 ...

  8. OpenCV(十九)直方图(直方图计算、掩膜、均衡化、自适应均衡化)

    目录 一.基础理论 1.原理及作用 2.专业术语 二.直方图计算 函数介绍: 1.灰度图 代码: 效果: 2.彩色图 代码: 三.直方图掩膜的应用(mask) 1.基础理论 2.代码 3.效果 四.直 ...

  9. opencv进阶学习笔记7:直方图,直方图均衡化,直方图比较,直方图反向投影

    基础版传送门: python3+opencv学习笔记汇总目录(适合基础入门学习) 进阶版笔记目录链接: python+opencv进阶版学习笔记目录(适合有一定基础) 直方图基础讲解: opencv学 ...

最新文章

  1. 区块链将重新定义世界
  2. JAVA基础实例(一)
  3. 图论 —— 网络流 —— 最大流 —— Dinic 算法
  4. 7.9模拟赛T1图的遍历(dfs)
  5. Windows10配置Git远程连接到github(全网简单教程)
  6. BP神经网络(手写数字识别)
  7. 树莓派教程 - 1.2 树莓派GPIO库wiringPi 软件PWM
  8. Indeterminate ProgressBar
  9. 备份文件时,添加时间戳
  10. extjs java 教程,JAVA开发工具 - 在IntelliJ IDEA下开发ExtJS应用指南
  11. 微软2011年10月最有价值专家(MVP)名单 51CTO十三位用户当选
  12. BZOJ3680 吊打XXX
  13. csdn积分怎么获得
  14. 我的读书笔记 -《裸猿》
  15. 【云驻共创】华为云助力加速构建企业数据资产和数据治理生产线
  16. 触摸式开关简单入门教程
  17. Centos7 切换为163 网易yum
  18. num find matlab,matlab中find函数的使用说明
  19. 对List中的对象的模糊查询
  20. 【夜读】一个人保持年轻的5个好习惯

热门文章

  1. 计算机网络本地连接被禁用说明什么,win10系统网络被禁用重新启用本地连接的设置技巧...
  2. 网页开发需要先学java吗_先学java还是javascript?
  3. php截取剩余部分,PHP从字串中截取一部分,支持使用(*)模糊截取
  4. java 空格乱码_java 中文乱码以及空格乱码解决方案总结
  5. python3 列表倒叙_python的列表、元组、字典、集合
  6. java maven清理打包运行
  7. Java里optionsMenu.add_Android中OptionMenu的使用总结
  8. matlab如何求传递函数的幅值_自动控制原理2.2.1 什么是传递函数,为什么要使用传递函数的概念...
  9. 皮一皮:中文汉字真是博大精深...
  10. 赠书:“替代Linux”?!全球技术海啸来临!