深入探究Retinex
-
- 导读
- Retinex
-
- 动态范围增强
- Retinex核心理论
- 带色彩恢复的Retinex->MSRCR
导读
Retinex理论是建立在人对颜色感知的恒常性上,真实物体都是无色的,所有颜色的产生都是光和物体相互作用,再被人眼感知的过程。在这样的理论基础下,Retinex模仿人类视觉系统,衍生出了很多简单实用的算法。Retinex相关算法,兼顾了动态范围增强,细节增强,颜色恒常性等方面。我自己在看这些算法的时候,其实遇到了不少问题,特此记录。
本文不再叙述算法模型,而从上面提到的几个方面出发,从最基础的图像处理知识入手,结合自己的理解,深入探究Retinex算法。如对Retinex还不太了解,可以先去自行搜索相关博客等。
Retinex
Retinex算法在色偏、低照度、雾图等成像环境恶劣的情况下有显著效果,因此着重于这几个点对Retinex算法进行分解,从个人理解的角度详解算法中的每个步骤。
首先回顾一下单尺度Retinex(Single Scale Retinex)算法框架,对输入图像 I I I,若是多通道就分通道处理:
- 将 I I I变换到log域,得到 I l o g I_{log} Ilog。
- 用尺度为 α \alpha α的高斯核对 I I I卷积来估计光照 G G G,并变换到log域,得到 G l o g G_{log} Glog。
- 在log域相减,得到 R l o g = I l o g − G l o g R_{log}=I_{log}-G_{log} Rlog=Ilog−Glog。
- 从log域还原。
- 线性拉伸。
动态范围增强
Retinex算法能处理低照度图像,主要依赖于log变换。log变换作为一个非线性变换,很适合用来处理较暗的图像,它能大幅拉伸暗的部分。但是在处理有暗有亮的图像时候,会牺牲一部分亮处的动态范围。所以一般在用Retinex算法时,不再从log域还原,即上述划去的第四步。我们将上述算法中的第一步和最后一步拿出来,只做一个log变换和Retinex算法作一个对比,如下图所示,从左到右依次是原图、SSR、简单log拉伸。
可以看见,log函数基本承担了低照度图像增强的部分。以上图为例,在SSR算法上修改,去除第一步,去除第二步的log变换,将第三步在log域相减,改为 I . / G I./G I./G原图和估计出来的光照直接点除。得到如下效果,以下分别为原图和处理后的图。
可以确认在没有log的处理下,Retinex算法是处理不了低照度图像的。但是log函数可以提高亮度,但是解决不了非正常照度的影响,而这部分也是Retinex理论最核心的思想。如下图,分别是原图、SSR、简单log拉伸。
Retinex核心理论
对于上图这种严重色偏的图像,首先从图像本身开始探究,下面是将RGB三通道单独拿出来作为灰度显示。显而易见的是,绿色通道的强度明显大于红通道和蓝通道。知道了原因,想要恢复色偏,只要将三个通道统一成接近的灰度级别就可以了。经典的白平衡算法如灰度世界算法等就是在同一个标准下对三个通道作对比度拉伸来解决问题。
而Retinex理论从光照角度出发,去除光照影响,还原物体本身的反射属性。对一幅已获得的图像 I I I,假设存在这样一个模型 I = R • G I=R•G I=R•G,其中R是物体的反射属性,G则是光照。在这样的假设下,要得到R,算法主要部分就是如何估计G,其中最主要的一种方法就是进行高斯滤波。原文中用的是卷积,但是高斯核本身是各向同性的,因此滤波和卷积的效果是一致的。因此在算法处理的时候,可以在空域进行滤波,也可以转化到频域相乘。
至于为什么高斯滤波能代替光照?又如何选择滤波参数?以下主要是一些个人理解。
依旧是上面三通道的灰度图,对它们进行高斯滤波来感受一下所谓的光照到底是什么。以下3列分别是sigma为10,80,250的滤波结果。
随着sigma增大,高斯曲线不断变得平坦,滤波结果也越来越接近均值滤波,当sigma足够大的时候,高斯滤波也就退化成均值滤波,光照就成了整个灰度图所有点的均值。根据上述的光照模型, R = I / G R=I/G R=I/G,这样绿通道将除以一个比较大的光照,对每一个通道消除光照影响,从而获得没有色偏的图像。同理,对于雾图,雾的存在导致光线的透射率下降,可以认为这是一种异常的光照,经过Retinex以后同样可以很大程度上消除雾的影响。
对应上面的不同sigma下的光照估计,根据 R = I / G R=I/G R=I/G,并线性拉伸到[0-1]范围,显示去除光照后每个通道的效果。
可见,现在每个通道的亮度等级都接近了,因此消除了严重的色偏问题,以下是3个尺度下的彩色结果。
可以明显地看到不同sigma带来的影响。在sigma较小的时候,估计出来的光照局部性越强,导致平滑区域的信息大部分丢失,只留下了边缘信息。至于为什么会这样,可以考虑极端情况,直接将原图作为光照相除,那样的话每一个点都有自己的光照,去除光照后只剩一片白色。但是显然,光照实际上是具有连续性的,至少在某个邻域内的光照是一致的,所以,既要考虑光照的空间连续性和空间变化性,sigma为80左右的高斯滤波结果显然优于其余两个。
因此,较小的sigma强调图像的边缘信息,较大的sigma可以更好的保留图像的整体颜色。
至于高斯核,在sigma确定的情况下,滤波器尺寸可以选择 6 σ ∗ 6 σ 6\sigma*6\sigma 6σ∗6σ,对于高斯曲线来说,以 3 σ 3\sigma 3σ为半径的自变量区域基本涵盖了高斯函数的值域。
至此,单尺度Retinex算法的几个问题都已提及,多尺度的Retinex就是对上面多个尺度下得到的结果取平均就行。下面给出单尺度Retinex算法的matlab测试代码。
clc
clear
filename = '文件名';
I = double(imread(filename));
out = SSR(I,80);
imshow([I out])
% ---------------Single Scale Retinex-----------------
function out = SSR(im, sigma)
%Single Scale Retinex
%分通道处理
if ~exist('sigma', 'var')
sigma = 80;
end
hsize = floor(sigma*3)*2+1;%确定高斯核尺寸
out = zeros(size(im));
k = fspecial('gaussian', hsize, sigma);%生成高斯核
G = imfilter(im, k, 'replicate');%高斯滤波
%分通道处理
for i=1:size(im, 3)
L = G(:,:,i);
R = log(im(:,:,i)+1)-log(L+1);% +1控制像素值>1
Max = max(R(:));
Min = min(R(:));
out(:,:,i) = (R-Min)/(Max-Min);
end
end
带色彩恢复的Retinex->MSRCR
无论是单尺度还是多尺度的Retinex算法,由于都是分通道单独进行,因此没有考虑到不同颜色通道之间的关系,导致有些图像处理完后发生色偏,失真等现象。