摘要:本文主要讲解图像局部直方图均衡化和自动色彩均衡化处理。这些算法可以广泛应用于图像增强、图像去噪、图像去雾等领域。

本文分享自华为云社区《[Python从零到壹] 五十四.图像增强及运算篇之局部直方图均衡化和自动色彩均衡化处理》,作者: eastmount。

一.局部直方图均衡化

前文通过调用OpenCV中equalizeHist()函数实现直方图均衡化处理,该方法简单高效,但其实它是一种全局意义上的均衡化处理,很多时候这种操作不是很好,会把某些不该调整的部分给均衡处理了。同时,图像中不同的区域灰度分布相差甚远,对它们使用同一种变换常常产生不理想的效果,实际应用中,常常需要增强图像的某些局部区域的细节。

为了解决这类问题,Pizer等提出了局部直方图均衡化的方法(AHE),但AHE方法仅仅考虑了局部区域的像素,忽略了图像其他区域的像素,且对于图像中相似区域具有过度放大噪声的缺点。为此K. Zuiderveld等人提出了对比度受限CLAHE的图像增强方法,通过限制局部直方图的高度来限制局部对比度的增强幅度,从而限制噪声的放大及局部对比度的过增强,该方法常用于图像增强,也可以被用来进行图像去雾操作[1-2]。

在OpenCV中,调用函数createCLAHE()实现对比度受限的局部直方图均衡化。它将整个图像分成许多小块(比如按10×10作为一个小块),那么对每个小块进行均衡化。这种方法主要对于图像直方图不是那么单一的(比如存在多峰情况)图像比较实用。其函数原型如下所示:

retval = createCLAHE([, clipLimit[, tileGridSize]])

  • clipLimit参数表示对比度的大小
  • tileGridSize参数表示每次处理块的大小

调用createCLAHE()实现对比度受限的局部直方图均衡化的代码如下:

# -*- coding: utf-8 -*-
# By:Eastmount
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('lena.bmp')
#灰度转换
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#局部直方图均衡化处理
clahe = cv2.createCLAHE(clipLimit=2, tileGridSize=(10,10))
#将灰度图像和局部直方图相关联, 把直方图均衡化应用到灰度图
result = clahe.apply(gray)
#显示图像
plt.subplot(221)
plt.imshow(gray, cmap=plt.cm.gray), plt.axis("off"), plt.title('(a)')
plt.subplot(222)
plt.imshow(result, cmap=plt.cm.gray), plt.axis("off"), plt.title('(b)')
plt.subplot(223)
plt.hist(img.ravel(), 256), plt.title('(c)')
plt.subplot(224)
plt.hist(result.ravel(), 256), plt.title('(d)')
plt.show()

输出结果如图1所示,图1(a)为原始图像,对应的直方图为图1,图1(b)和图1(d)为对比度受限的局部直方图均衡化处理后的图像及对应直方图,它让图像的灰度值分布更加均衡。可以看到,相对于全局的直方图均衡化,这个局部的均衡化似乎得到的效果更自然一点。

二.自动色彩均衡化

Retinex算法是代表性的图像增强算法,它根据人的视网膜和大脑皮层模拟对物体颜色的波长光线反射能力而形成,对复杂环境下的一维条码具有一定范围内的动态压缩,对图像边缘有着一定自适应的增强。自动色彩均衡(Automatic Color Enhancement,ACE)算法是在Retinex算法的理论上提出的,它通过计算图像目标像素点和周围像素点的明暗程度及其关系来对最终的像素值进行校正,实现图像的对比度调整,产生类似人体视网膜的色彩恒常性和亮度恒常性的均衡,具有很好的图像增强效果[3-4]。

ACE算法包括两个步骤,一是对图像进行色彩和空域调整,完成图像的色差校正,得到空域重构图像;二是对校正后的图像进行动态扩展。ACE算法计算公式如下:

其中,W是权重参数,离中心点像素越远的W值越小;g是相对对比度调节参数,其计算方法如公式(22-2)所示,a表示控制参数,值越大细节增强越明显。

图2是条形码图像进行ACE图像增强后的效果图,通过图像增强后的图(b)对比度更强,改善了原图像的明暗程度,增强的同时保持了图像的真实性。

由于OpenCV中暂时没有ACE算法包,下面的代码是借鉴“zmshy2128”老师的文章,修改实现的彩色直方图均衡化处理[5]。

# -*- coding: utf-8 -*-
# By:Eastmount
# 参考zmshy2128老师文章
import cv2
import numpy as np
import math
import matplotlib.pyplot as plt
#线性拉伸处理
#去掉最大最小0.5%的像素值 线性拉伸至[0,1]
def stretchImage(data, s=0.005, bins = 2000):
ht = np.histogram(data, bins);
d = np.cumsum(ht[0])/float(data.size)
lmin = 0; lmax=bins-1
while lmin<bins:
if d[lmin]>=s:
break
lmin+=1
while lmax>=0:
if d[lmax]<=1-s:
break
lmax-=1
return np.clip((data-ht[1][lmin])/(ht[1][lmax]-ht[1][lmin]), 0,1)
#根据半径计算权重参数矩阵
g_para = {}
def getPara(radius = 5):
global g_para
m = g_para.get(radius, None)
if m is not None:
return m
size = radius*2+1
m = np.zeros((size, size))
for h in range(-radius, radius+1):
for w in range(-radius, radius+1):
if h==0 and w==0:
continue
m[radius+h, radius+w] = 1.0/math.sqrt(h**2+w**2)
m /= m.sum()
g_para[radius] = m
return m
#常规的ACE实现
def zmIce(I, ratio=4, radius=300):
para = getPara(radius)
height,width = I.shape
#Python3报错如下 使用列表append修改
zh = []
zw = []
n = 0
while n < radius:
zh.append(0)
zw.append(0)
n += 1
for n in range(height):
zh.append(n)
for n in range(width):
zw.append(n)
n = 0
while n < radius:
zh.append(height-1)
zw.append(width-1)
n += 1
#print(zh)
#print(zw)
Z = I[np.ix_(zh, zw)]
res = np.zeros(I.shape)
for h in range(radius*2+1):
for w in range(radius*2+1):
if para[h][w] == 0:
continue
res += (para[h][w] * np.clip((I-Z[h:h+height, w:w+width])*ratio, -1, 1))
return res
#单通道ACE快速增强实现
def zmIceFast(I, ratio, radius):
print(I)
height, width = I.shape[:2]
if min(height, width) <=2:
return np.zeros(I.shape)+0.5
Rs = cv2.resize(I, (int((width+1)/2), int((height+1)/2)))
Rf = zmIceFast(Rs, ratio, radius) #递归调用
Rf = cv2.resize(Rf, (width, height))
Rs = cv2.resize(Rs, (width, height))
return Rf+zmIce(I,ratio, radius)-zmIce(Rs,ratio,radius)
#rgb三通道分别增强 ratio是对比度增强因子 radius是卷积模板半径
def zmIceColor(I, ratio=4, radius=3):
res = np.zeros(I.shape)
for k in range(3):
res[:,:,k] = stretchImage(zmIceFast(I[:,:,k], ratio, radius))
return res
#主函数
if __name__ == '__main__':
img = cv2.imread('test01.png')
res = zmIceColor(img/255.0)*255
cv2.imwrite('Ice.jpg', res)

运行结果如图3和图4所示,ACE算法能有效进行图像去雾处理,实现图像的细节增强。

三.总结

本文主要讲解图像局部直方图均衡化和自动色彩均衡化处理。这些算法可以广泛应用于图像增强、图像去噪、图像去雾等领域。

点击关注,第一时间了解华为云新鲜技术~

跟我学Python丨图像增强及运算:局部直方图均衡化和自动色彩均衡化处理的更多相关文章

  1. 小白学 Python 数据分析(10):Pandas (九)数据运算

    人生苦短,我用 Python 前文传送门: 小白学 Python 数据分析(1):数据分析基础 小白学 Python 数据分析(2):Pandas (一)概述 小白学 Python 数据分析(3):P ...

  2. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  3. 简学Python第一章__进入PY的世界

    #cnblogs_post_body h2 { background: linear-gradient(to bottom, #18c0ff 0%,#0c7eff 100%); color: #fff ...

  4. 小朋友学Python(4)

    Mac下安装Python 3 Mac系统会自带Python 2.7.x.安装Python 3时,不要卸载Python 2.7.x,因为有Mac系统有一些库会依赖于Python 2.7.x. 安装步骤: ...

  5. D10——C语言基础学PYTHON

    C语言基础学习PYTHON——基础学习D10 20180906内容纲要: 1.协程 (1)yield (2)greenlet (3)gevent (4)gevent实现单线程下socket多并发 2. ...

  6. 《趣学Python编程》

    <趣学Python编程> 基本信息 作者: (美)Jason Briggs 译者: 尹哲 出版社:人民邮电出版社 ISBN:9787115335951 上架时间:2014-2-21 出版日 ...

  7. Python的自增运算与Python变量的浅析

    一.关于Python的自增运算 学了C/C++后再学习Python,不自觉地就打出了自增运算符++,但是发现Python解释器不认识,查了下资料,发现Python中没有这个运算符.这里暂时不探讨自增运 ...

  8. 小白学 Python(2):基础数据类型(上)

    人生苦短,我选Python 引言 前文传送门 小白学 Python(1):开篇 接触一门新的语言,肯定要先了解它的基础数据类型.啥?你问我为啥要先了解基础数据类型? 为了你的生命安全,还是乖乖听我 B ...

  9. 小白学 Python(4):变量基础操作

    人生苦短,我选Python 引言 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 前面的文章中,我们介绍了 ...

  10. 小白学 Python(5):基础运算符(上)

    人生苦短,我选Python 前文传送门 小白学 Python(1):开篇 小白学 Python(2):基础数据类型(上) 小白学 Python(3):基础数据类型(下) 小白学 Python(4):变 ...

随机推荐

  1. python3使用libpcap库进行抓包及数据处理

    python版本:python 3.9 libpcap版本:1.11.0b7 python libpcap库是底层绑定c语言libpcap库的开发包,旨在提供python应用可访问的unix c li ...

  2. 深度剖析Java的volatile实现原理,再也不怕面试官问了

    上篇文章我们讲了synchronized的用法和实现原理,我们总爱说synchronized是重量级锁,volatile是轻量级锁.为什么volatile是轻量级锁,体现在哪些方面?以及volatil ...

  3. Android开发 对接微信分享SDK总结

    原文:Android开发 对接微信分享SDK总结 - Stars-One的杂货小窝 公司项目需要对接微信分享,本来之前准备对接友盟分享的,但友盟的分享实际参数太多,而我又只需要对接一个微信分享,于是便 ...

  4. Python基础部分:11、文件和光标移动

    目录 一.文件操作 1.文件的概念 2.代码打开文件的方式 二.文件读写模式 1.'r' 只读模式 read 2.'w' 只写模式 write 3.'a' 尾部追写模式 add 三.文件操作模式 1. ...

  5. ES6 学习笔记(八)基本类型Symbol

    1.前言 大家都知道,在ES5的时候JavaScript的基本类型有Number.String.Boolean.undefined.object.Null共6种,在es6中,新增了Symbol类型,用 ...

  6. 一次SpringBoot版本升级,引发的血案

    前言 最近项目组升级了SpringBoot版本,由之前的2.0.4升级到最新版本2.7.5,却引出了一个大Bug. 到底是怎么回事呢? 1.案发现场 有一天,项目组的同事反馈给我说,我之前有个接口在新 ...

  7. 【题解】CF1215C Swap Letters

    题面传送门 解决思路 首先容易得知,两个字符串中 \(b\)(或 \(a\)) 的个数为偶数时,一定有解.为奇数则一定无解. 其次考虑怎么交换.对照样例三: in: 8 babbaabb ababab ...

  8. C#结构体大小问题

    using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServi ...

  9. 【云原生 · Kubernetes】Kubernetes运维

    (1)Node的隔离与恢复 在硬件升级.硬件维护等情况下,需要将某些Node隔离.使用kubectl cordon <node_name>命令可禁止Pod调度到该节点上,在其上运行的Pod ...

  10. ifconfig命令的使用

    ifconfig命令 用途:配置或显示TCP/IP网络的网络接口参数. *1.通过--help学习ifconfig的使用 点击查看代码 [root@rocky8 ~]# ifconfig --help ...