MSRCR(Multi-Scale Retinex with Color Restore)

2024-08-25 23:38

本文主要是介绍MSRCR(Multi-Scale Retinex with Color Restore),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

引言

始于Edwin Herbert Land(埃德温·赫伯特·兰德)于1971年提出的一种被称为色彩恒常的理论,并基于此理论的图像增强方法。Retinex这个词由视网膜(Retina)和大脑皮层(Cortex)合成而来.之所以这样设计,表明Land他也不清楚视觉系统的特性究竟取决于此两个生理结构中的哪一个,抑或两者都有关系。不同于传统的图像增强算法,如线性、非线性变换、图像锐化等只能增强图像的某一类特征,如压缩图像的动态范围,或增强图像的边缘等,Retinex可以在动态范围压缩、边缘增强和颜色恒常三方面达到平衡,可以对各种不同类型的图像进行自适应性地增强,在很多方面得到了广泛的应用。

算法概述

Retinex 理论的基本内容是物体的颜色是由物体对长波(红)、中波(绿)和短波(蓝)光线的反射能力决定的,而不是由反射光强度的绝对值决定的;物体的色彩不受光照非均性的影响,具有一致性,即Retinex理论是以色感一致性(颜色恒常性)为基础的。如下图所示,观察者所看到的物体的图像S是由物体表面对入射光L反射得到的,反射率R由物体本身决定,不受入射光L变化。
这里写图片描述
对于观察图像S,有公式表示为:

S(x,y)=R(x,y)L(x,y)(1)

其中, L(x,y) 表示亮度分量, R(x,y) 表示物体反射分量, S(x,y)
Retinex理论增强算法的思想就是利用式(1),去除亮度分量 L 求得反射分量 R ,从而达到图像增强效果。
对(1)式两边取对数
log(S(x,y))=log(L(x,y))+log(R(x,y))(2)

由(2)得
log(R(x,y))=log(S(x,y))log(L(x,y))(3)

由式(3)可知,只需要估计亮度分量 L 就能求得反射分量,因此L的估计直接决定图像恢复效果.Jobson等论证了高斯卷积函数可以从已知图像 S 中更好地估计出亮度分量,即
L(x,y)=S(x,y)G(x,y)(4)

其中,’*’代表卷积操作,高斯函数 G(x,y)=kexp(x2+y2σ2) σ 是高斯函数尺度参数, k 为归一化因子,使 G(x,y)dxdy=1 。对于RGB彩色图像的某一个通道,
log(Rc(x,y))=log(Sc(x,y))log(Sc(x,y))G(x,y)(5)

其中, c 表示RGB3个通道的某一个通道; σ 为尺度函数,取值大时,颜色失真小但细节恢复差,取值小时,细节恢复好,但颜色失真大。
为弥补SSR算法不足,MSR算法对每一个通道进行3次不同尺度滤波,加权求和,处理时间也会变长,且使用不同的尺度,导致恢复的RGB比值与原图比值不太一样,颜色失真。
log(R(x,y))=Weight1log(Rσ1(x,y))+Weight2log(Rσ2(x,y))+Weight3log(Rσ3(x,y))(6)

Rehman等提出MSRCR算法,引入分量比值调整因子从而降低色彩失真的影响。
RMSRCR(x,y)=C(x,y)RMSR(x,y)(7)

其中 C(x,y)=G{log[αIc(x,y)]log[c=13Ic(x,y)]}

流程

  1. 按照(4)式,计算入射分量 L
  2. 按照(3)式,计算单一尺度下的 log(Rσ(x,y))
  3. 按照(6)式,对不同尺度进行加权求和;
  4. 按照(7)式,进行色彩恢复;
  5. RMSRCR 量化为0到255范围,输出。

入射分量获取

Retinex算法核心在于入射分量的获取,简单来说,这个可以对原图像进行高斯卷积获取。当图像比较大的时候,其计算过程是非常复杂的, O(MNPQ) M N 是原图像的高度和宽度, P Q 是卷积核大小。实现的时候可以使用递归高斯滤波,复杂度 O(MN) (参见paper:Recursive implementation of the Gaussian filter,源码在GIMP中有)。下面我给出在3种不同尺度下获取的亮度图,等分权重。
这里写图片描述

色彩恢复

GIMP中色彩恢复代码如下:

<pre name="code" class="cpp">/*  Final calculation with original value and cumulated filter values.  The parameters gain, alpha and offset are constants.  */   /* Ci(x,y)=log[a Ii(x,y)]-log[ Ei=1-s Ii(x,y)] */   alpha  = 128.0f;   gain   = 1.0f;   offset = 0.0f;   for ( i = 0; i < size; i += bytes )   {   float logl;   psrc = src+i;   pdst = dst+i;   logl = (float)log( (float)psrc[0] + (float)psrc[1] + (float)psrc[2] + 3.0f );   pdst[0] = gain * ((float)(log(alpha * (psrc[0]+1.0f)) - logl) * pdst[0]) + offset;   pdst[1] = gain * ((float)(log(alpha * (psrc[1]+1.0f)) - logl) * pdst[1]) + offset;   pdst[2] = gain * ((float)(log(alpha * (psrc[2]+1.0f)) - logl) * pdst[2]) + offset;   }


 

另外,最后一步代码又增加了调节项,用于控制饱和度和颜色,最后将其量化到[0~255],详细代码如下。

 <pre name="code" class="cpp">  /*  Adapt the dynamics of the colors according to the statistics of the first and second order.  The use of the variance makes it possible to control the degree of saturation of the colors.  */   pdst = dst;compute_mean_var( pdst, &mean, &var, size, bytes );   mini = mean - rvals.cvar*var;   maxi = mean + rvals.cvar*var;   range = maxi - mini;   if ( !range ) range = 1.0;   for ( i = 0; i < size; i+= bytes )   {   psrc = src + i;   pdst = dst + i;   for (j = 0 ; j < 3 ; j++)   {   float c = 255 * ( pdst[j] - mini ) / range;   psrc[j] = (unsigned char)clip( c, 0, 255 );   }   }   free (dst);

 

效果

我依据GIMP中插件contrast-retinex.c用Matlab实现了一遍,效果如下

宽动态图像

这里写图片描述
这里写图片描述

水下图像

这里写图片描述
这里写图片描述

低照度图像

这里写图片描述

雾天图像

这里写图片描述
这里写图片描述

评论

Retinex算法在图像增强诸多领域应用广泛,如上述宽动态图像增强,水下图像增强,雾天图像增强,低照度图像增强等等,更多可以参考NASA关于Retinex的介绍。Retinex的实现,C语言用了递归高斯滤波器,我不知道Matlab是否有对应的函数,我在这里是将图像转换到频率域高斯低通滤波处理的,因此算法时间耗费也并不大。OpenCV版本的Retinex算法已传到CSDN上共享,下载请点击这里,记得给好评哦。

更多阅读

http://dragon.larc.nasa.gov/
http://www.cnblogs.com/Imageshop/archive/2013/04/17/3026881.html
A multiscale retinex for bridging the gap between color images and the human observation of scenes

转载请保留以下信息

作者日期联系方式
风吹夏天2015年5月13日wincoder@qq.com

这篇关于MSRCR(Multi-Scale Retinex with Color Restore)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1106957

相关文章

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int

三色标记(Tri-color marking)

维基百科部分 原文 https://en.wikipedia.org/wiki/Tracing_garbage_collection#TRI-COLOR Because of these performance problems, most modern tracing garbage collectors implement some variant of the tri-color ma

[论文笔记]LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale

引言 今天带来第一篇量化论文LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale笔记。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 大语言模型已被广泛采用,但推理时需要大量的GPU内存。我们开发了一种Int8矩阵乘法的过程,用于Transformer中的前馈和注意力投影层,这可以将推理所需

android xml之动画篇 alpha、scale、translate、rotate、set的属性及用法 和

1.简介 Android的补间动画TweenAnimation由四种类型组成:alpha、scale、translate、rotate,对应android官方文档地址:《Animation Resources》 逐帧动画 FrameAnimation(也称 Drawable Animation  ):animation-list alpha 渐变透明度动画效果 scale 渐变

Android AnimationDrawable资源 set[translate,alpha,scale,rotate]

本文内容摘自《疯狂Android讲义 第三版-李刚著作》 xml <?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"android:duration="1000"android:fillAfter="true"android:f

HDU 1556 Color the ball (树状数组-- 区间更新,单点求值)

OJ题目 :点这里~~ 与 单点更新,区间求值 稍有不同,需要理解注意。 AC_CODE int n;int num[100002];int lowbit(int x){return x&(-x);}int sum(int x){int ret = 0;while(x > 0){ret += num[x];x -= lowbit(x);}return ret;}void ad

【硬刚ES】ES基础(二十一) 单字符串多字段查询:Multi Match

本文是对《【硬刚大数据之学习路线篇】从零到大数据专家的学习指南(全面升级版)》的ES部分补充。

Android canvas save restore saveLayer的异同点

一、基础操作 drawText、drawRect、drawColor等 对于这些基础操作,相信每一个安卓开发者都能说上个一二点出来,这些就不多做介绍,api 工程师必备技能之一。 在进阶之前,先回答这个问题:    问:canvas既然大家都理解为画布,那如果先在画布上绘制了某些内容,然后再canvas.rotate旋转了画布,为什么这些已经绘制在画布上的内容不会跟随着旋转?    答:由此可