ACE算法源自retinex算法,可以调整图像的对比度,实现人眼色彩恒常性和亮度恒常性,通过差分来计算目标点与周围像素点的相对明暗关系来校正最终像素值,有很好的增强效果。但是计算复杂度非常高,本文提出一种有效的快速实现方法。

为叙述方便,这里假设后面的图像都是归一化到[0,1]之间的浮点数图像。

ACE算法的计算公式为:

Y =   ∑(g(I(x0)-I(x))w(x0,x))  / ∑(w(x0,x))                                    x属于I                                (1)

其中,w是权重参数,离中心点像素越远w值越小,可以直接取值欧氏距离的倒数。g()是相对对比度调节参数,非线性的,简单取如下计算方法:

g(x) = max(min(ax, 1.0), -1.0)                                                                                        (2)

这里a是控制参数,值越大,细节增强越明显。计算完后,还要对Y进行一次归一化即可得到最终的增强图像。

ACE的增强效果普遍与retinex好。需要注意的是,ACE中当前像素是与整个图像的其他像素做差分比较,计算复杂度非常非常高,这也是限制它应用的最主要原因,本文主要基于两个假设:(1)对一副图像ACE增强后得到输出Y,如果对Y再进行一次ACE增强,输出仍然是Y本身;(2)对一副图像的ACE增强结果进行尺寸缩放得到Y,对Y进行ACE增强,输出仍然是Y本身。这两个假设我没法证实,呵呵,就算臆想的吧。

如果上面假设成立,我们就可以对图像进行缩放得到I1,对I1的ACE增强结果进行尺度放大(与I尺寸一样)得到Y1,那么Y和Y1是非常接近的,我们只需要在Y1基础上进一步处理即可。这里就又引申了两个细节问题:1)如何快速的求I1的ACE增强结果? 其实很简单,对它再次缩放得到I2,求I2的增强结果,依次类推,就是金字塔结构思想。2)如何在Y1基础上进一步处理得到Y? 因为是在整个图像域进行差分比较运算,与近处邻域像素的比较构成了Y的细节信息,与远处像素的比较构成了Y的全局背景信息,那么我们合理假设,Y和Y1的全局背景信息相同,只更新细节信息即可,也就是,我们需要在Y1基础上加上I中邻近像素的差分结果,并减去Y1中邻近像素的差分结果就是最终的输出Y。

上面说的有点绕,慢慢看吧。

下面是python代码

  1. import cv2
  2. import numpy as np
  3. import math
  4.  
  5. def stretchImage(data, s=0.005, bins = 2000): #线性拉伸,去掉最大最小0.5%的像素值,然后线性拉伸至[0,1]
  6. ht = np.histogram(data, bins);
  7. d = np.cumsum(ht[0])/float(data.size)
  8. lmin = 0; lmax=bins-1
  9. while lmin<bins:
  10. if d[lmin]>=s:
  11. break
  12. lmin+=1
  13. while lmax>=0:
  14. if d[lmax]<=1-s:
  15. break
  16. lmax-=1
  17. return np.clip((data-ht[1][lmin])/(ht[1][lmax]-ht[1][lmin]), 0,1)
  18.  
  19. g_para = {}
  20. def getPara(radius = 5): #根据半径计算权重参数矩阵
  21. global g_para
  22. m = g_para.get(radius, None)
  23. if m is not None:
  24. return m
  25. size = radius*2+1
  26. m = np.zeros((size, size))
  27. for h in range(-radius, radius+1):
  28. for w in range(-radius, radius+1):
  29. if h==0 and w==0:
  30. continue
  31. m[radius+h, radius+w] = 1.0/math.sqrt(h**2+w**2)
  32. m /= m.sum()
  33. g_para[radius] = m
  34. return m
  35.  
  36. def zmIce(I, ratio=4, radius=300): #常规的ACE实现
  37. para = getPara(radius)
  38. height,width = I.shape
  39. zh,zw = [0]*radius + range(height) + [height-1]*radius, [0]*radius + range(width) + [width -1]*radius
  40. Z = I[np.ix_(zh, zw)]
  41. res = np.zeros(I.shape)
  42. for h in range(radius*2+1):
  43. for w in range(radius*2+1):
  44. if para[h][w] == 0:
  45. continue
  46. res += (para[h][w] * np.clip((I-Z[h:h+height, w:w+width])*ratio, -1, 1))
  47. return res
  48.  
  49. def zmIceFast(I, ratio, radius): #单通道ACE快速增强实现
  50. height, width = I.shape[:2]
  51. if min(height, width) <=2:
  52. return np.zeros(I.shape)+0.5
  53. Rs = cv2.resize(I, ((width+1)/2, (height+1)/2))
  54. Rf = zmIceFast(Rs, ratio, radius) #递归调用
  55. Rf = cv2.resize(Rf, (width, height))
  56. Rs = cv2.resize(Rs, (width, height))
  57.  
  58. return Rf+zmIce(I,ratio, radius)-zmIce(Rs,ratio,radius)
  59.  
  60. def zmIceColor(I, ratio=4, radius=3): #rgb三通道分别增强,ratio是对比度增强因子,radius是卷积模板半径
  61. res = np.zeros(I.shape)
  62. for k in range(3):
  63. res[:,:,k] = stretchImage(zmIceFast(I[:,:,k], ratio, radius))
  64. return res
  65.  
  66. if __name__ == '__main__':
  67. m = zmIceColor(cv2.imread('p4.bmp')/255.0)*255
  68. cv2.imwrite('zmIce.jpg', m)

  

下面是实验结果,上边是原图,下边是增强结果。

自动色彩均衡(ACE)快速算法的更多相关文章

  1. Consul-template+nginx实现自动负载均衡

    前言 consul-template 是 Consul 的一个守护程序,使用 consul-template 可以方便快速的实现对 Consul Key/Value 存储系统的访问,可以从 KV 系统 ...

  2. Op-level的快速算法

    十岁的小男孩 本文为终端移植的一个小章节. 目录 引言 FFT Conv2d (7x7, 9x9) Winograd Conv2d (3x3, 5x5) 引言 本节针对CNN进行加速计算的,主要有以下 ...

  3. MinFilter(MaxFilter)快速算法C++实现

    目录 1.算法简述 1.1.MinFilter(MaxFilter) 算法简述 1.2.MinFilter(MaxFilter) 快速算法简述 2.实现代码 2.1.MinFilterOneRow 单 ...

  4. 从大整数乘法的实现到 Karatsuba 快速算法

    Karatsuba 快速乘积算法是具有独特合并过程(combine/merge)的分治算法(Karatsuba 是俄罗斯人).此算法主要是对两个整数进行相乘,并不适用于低位数(如 int 的 32 位 ...

  5. [转帖]利用nginx实现负载均衡 | 哈希算法,sticky模块实现session粘滞

    利用nginx实现负载均衡 | 哈希算法,sticky模块实现session粘滞 2018年08月02日 10:06:03 Minza 阅读数 483 https://blog.csdn.net/ha ...

  6. 深度学习框架如何自动选择最快的算法?Fast Run 让你收获最好的性能!

    作者:王博文 | 旷视 MegEngine 架构师 一.背景 对于深度学习框架来说,网络的训练/推理时间是用户非常看中的.在实际生产条件下,用户设计的 NN 网络是千差万别,即使是同一类数学计算,参数 ...

  7. LVS负载均衡理论以及算法概要

    一. LVS简介 LVS是Linux Virtual Server的简称,也就是Linux虚拟服务器, 由章文嵩博士发起的自由软件项目,它的官方站点是www.linuxvirtualserver.or ...

  8. nginx系列11:负载均衡哈希算法ip_hash与hash模块

    使用默认的round-robin负载均衡算法无法保证某一类请求只能由上游的某一台应用服务器处理,它只适用于AKF扩展中的水平扩展,如果要保证某一类请求只能由上游的某一台应用服务器处理,就需要用到AKF ...

  9. nginx 负载均衡(默认算法)

    使用 nginx 的upstream模块只需要几步就可以实现一个负载均衡: 在 nginx 配置文件中添加两个server server { listen ; server_name 192.168. ...

随机推荐

  1. 远程连接MySQL服务器

    在CentOS虚拟机上安装好了MySQL服务以后,在windows上用Workbench客户端去连接时碰到很多问题,现在把解决过程记录一下. 1.在Windows上ping CentOS IP是可以p ...

  2. Python学习---Django的request.post源码分析

    request.post源码分析: 可以看到传递json后会帮我们dumps处理一次最后一字节形式传递过去

  3. 《C++ Primer Plus》读书笔记之十二—C++中的代码重用

    第14章 C++中的代码重用 1.C++代码重用方法:公有继承.使用本身是另一个类的对象的类成员(这种方法称为包含.组合或层次化).私有或保护继承.类模板等. 2.模板特性意味着声明对象时,必须指定具 ...

  4. 铁乐学Python_Day34_Socket模块2和黏包现象

    铁乐学Python_Day34_Socket模块2和黏包现象 套接字 套接字是计算机网络数据结构,它体现了C/S结构中"通信端点"的概念. 在任何类型的通信开始之前,网络应用程序必 ...

  5. zabbix之自动发现Tomcat多实例(第一种:已经部署完成,后续不再添加;第二种:后续或根据需要添加Tomcat实例)

    单一实例手动部署:https://www.cnblogs.com/huangyanqi/p/8522526.html 注释:参考的一位博主的博客后续做的修改,那个博主的网址找不到了!!!! 背景: 1 ...

  6. 实践和感悟 - scala向下转型和减少穷举

    工作中的问题总结: 问题一:scala 之向下转型 引言:假如在复杂的业务逻辑中,变量的类型不能确认,只能给个接口类型,这样数据类型推导不会错误,但是后面要使用实现类的类型时,你却发现转不过来了? 对 ...

  7. python SQLAlchemy复习

    下面的代码主要使用SQLAlchemy的ORM思想实现查询单词的功能: 实现输入一个单词,查询出与输入单词接近的单词以及单词的意思. 主要有以下三步: 1.创建数据表 2.插入数据 3.查询数据 1. ...

  8. iOS网络缓存的系统实现是一个烂尾工程

    烂尾的原因是request的一致性比较接口没有开放出来.

  9. HBase学习之路 (十一)HBase的协过滤器

    协处理器—Coprocessor 1. 起源 Hbase 作为列族数据库最经常被人诟病的特性包括:无法轻易建立“二级索引”,难以执 行求和.计数.排序等操作.比如,在旧版本的(<0.92)Hba ...

  10. PAT02-线性结构3 Reversing Linked List

    题目:https://pintia.cn/problem-sets/1010070491934568448/problems/1037889290772254722 先是看了牛客(https://ww ...