自动色彩均衡(ACE)快速算法

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代码

import cv2
import numpy as np
import math

def stretchImage(data, s=0.005, bins = 2000):    #线性拉伸,去掉最大最小0.5%的像素值,然后线性拉伸至[0,1]
    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

def zmIce(I, ratio=4, radius=300):                     #常规的ACE实现
    para = getPara(radius)
    height,width = I.shape
    zh,zw = [0]*radius + range(height) + [height-1]*radius, [0]*radius + range(width)  + [width -1]*radius
    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

def zmIceFast(I, ratio, radius):                #单通道ACE快速增强实现
    height, width = I.shape[:2]
    if min(height, width) <=2:
        return np.zeros(I.shape)+0.5
    Rs = cv2.resize(I, ((width+1)/2, (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)    

def zmIceColor(I, ratio=4, radius=3):               #rgb三通道分别增强,ratio是对比度增强因子,radius是卷积模板半径
    res = np.zeros(I.shape)
    for k in range(3):
        res[:,:,k] = stretchImage(zmIceFast(I[:,:,k], ratio, radius))
    return res

if __name__ == ‘__main__‘:
    m = zmIceColor(cv2.imread(‘p4.bmp‘)/255.0)*255
    cv2.imwrite(‘zmIce.jpg‘, m)

  

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

时间: 2024-10-14 03:57:54

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

实现负载均衡的基本算法

平衡算法设计的好坏直接决定了集群在负载均衡上的表现,设计不好的算法,会导致集群的负载失衡.一般的平衡算法主要任务是决定如何选择下一个集群节点,然后将新的服务请求转发给它.有些简单平衡方法可以独立使用,有些必须和其它简单或高级方法组合使用.而一个好的负载均衡算法也并不是万能的,它一般只在某些特殊的应用环境下才能发挥最大效用.因此在考察负载均衡算法的同时,也要注意算法本身的适用面,并在采取集群部署的时候根据集群自身的特点进行综合考虑,把不同的算法和技术结合起来使用. 一.轮转法: 轮转算法是所有调度

图像放大快速算法

图像放大快速算法实现的原理主要有以下两点: 1.横向缩放与纵向缩放分开,而先后顺序取决于缩放前后的图像比例: 若SrcHeight/DstWidth>SrcWidth/DstWidth,则先纵向缩放,否则横向缩放. 2.利用整数运算代替浮点运算,由于是分步缩放,以横向缩放为例,利用二次线性插值公式,再变形一下如下: f(i,j+v) = (1-v)f(i,j) +vf(i,j+1); 其中i为第i行,j为第j列,v表示求得放大后坐标的小数部分. 这里最重要的并没有直接用小数运算,而是通过将小数区

负载均衡的那些算法们

上周发了问卷,想了解一下大家对老王有没有什么建议,然后好多朋友都投了票,想了解编程技术和服务器架构的干货,所以接下来会先聊聊编程和架构相关的算法,然后大概在6月下旬会跟大家聊聊面试那些事儿(老王到目前大约参加了几百次的面试,可以从面试官的角度来聊聊不一样的面试).老王聊技术有个特点,就是绝不假大空,只求贴地飞行.所以,聊的东西一定会跟实际有关联,大家在平时也有可能用得着. 今天跟大伙儿聊的是负载均衡相关的一些算法.老王在百度的时候(估计是5-6年前),写过一个通用的基础库(不知道现在还有没有部门

十进制转二进制-快速算法

#include<iostream> #include<string> #include<algorithm> using namespace std; int main(int agrc, char *agrv[]) { int iInPut = 0; while (cin >> iInPut) { string sBinary;//转换后的二进制存储为字符串,调用了默认构造函数初试化为空串 int temp = abs(iInPut); if (temp

负载均衡的基本算法

负载均衡的基本算法,主要有以下几种(参考F5产品): 随机:负载均衡方法随机的把负载分配到各个可用的服务器上,通过随机数生成算法选取一个服务器,然后把连接发送给它.虽然许多均衡产品都支持该算法,但是它的有效性一直受到质疑,除非把服务器的可运行时间看的很重. 轮询:轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器.轮询算法在大多数情况下都工作的不错,但是如果负载均衡的设备在处理速度.连接速度和内存等方面不是完全均等,那么效果会更好. 加权轮询:该算法中,每个机器

快速算法的两个实现方法

今天调试了快速算法的代码,当然网上这样的代码一大堆,只是这个是自己一点点写的,中间易错点都出现并调试出来.留着以后自己复习用了. 交换代码: void sw(int *a,int *b)//交换数据{ int temp; temp=*a; *a=*b; *b=temp;} 实现方法1: ////由大到小排序 void sort(int a[],int low,int high){ if(low>=high)/////递归出口 return; int key=a[low];//// int fir

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

利用nginx实现负载均衡 | 哈希算法,sticky模块实现session粘滞 2018年08月02日 10:06:03 Minza 阅读数 483 https://blog.csdn.net/ha_weii/article/details/81350087 学习一下如何使用sticky 版权声明:创作不易,转载请注明出处 https://blog.csdn.net/ha_weii/article/details/81350087 一,普通的负载均衡 1,启动nginx服务器 之前已经把/us

负载均衡的常用算法

1.随机算法: 负载均衡方法随机的把负载分配到各个可用的服务器上,通过随机数生成算法选取一个服务器,然后把连接发送给它.同样一个请求一会落到机器A,一会落到机器B上,Cache会被频繁淘汰,使得cache命中率低. 2.轮询算法: 轮询算法按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器.轮询算法在大多数情况下都工作的不错,但是如果负载均衡的设备在处理速度.连接速度和内存等方面不是完全均等,那么效果就会不好.当然cache命中率也不高 3.加权轮询算法: 每个机器接受

nginx 负载均衡(默认算法)

使用 nginx 的upstream模块只需要几步就可以实现一个负载均衡: 在 nginx 配置文件中添加两个server server { listen 81; server_name 192.168.1.129; root /var/www/html1; } server { listen 82; server_name 192.168.1.129; root /var/www/html2; } 使用upstream把这两个 server 绑定到一个负载sever上提供统一入口: upstr