图像增强(1)-- Retinex
Retinex方法
Retinex是由 Retina 和 Cortex 两个词组成,该理论认为物体的颜色是由物体对长波(红)、中波(绿)和短波(蓝)光线的反射能力决定的,而不是由反射光强度的绝对值决定的。
由此观察者看到的图像S是由物体表面对入射光L反射得到的,反射率R由物体本身决定与入射光L无关:
S(x,y) = R(x,y)L(x,y)
基于Retinex的图像增强就是从原始图像S中估计出光照L,从而分解出R,消除光照不均的影响。
一般对原图S做低通滤波 估计光照L,并将图像数据取对数将乘法转为加法方便计算
log(R(x,y))=log(S(x,y)) - log(L(x,y))
从后面的实验可以看到,这种算法对光照不均(过曝、阴影)有不错的改善 ,同时也有文章指出这类方法比较适合航空图像的去雾 。
SSR算法
单尺度视网膜(Singal Scale Retinex)算法是Retinex最基础的一个算法,步骤如下:
- 原图高斯滤波并取对数,得到L_{log}
- 原图取对数,得到S_{log}
- S_{log}-L_{log}并归一化到[0,255]得到恢复后的图像
这个过程跟顶帽变换矫正不均匀光线影响的算法我觉得本质上是一致的
R_{SSR} = log(S)-log(L*G(\sigma))
MSR算法
多尺度视网膜(Multi-Scale Retinex)算法是对SSR的改进,采用多个不同的高斯方差值,然后将各个结果做加权和
R_{MSR}=\sum_{k=1}^n{w_kR_{SSR}(\sigma_k)}
MSRCR算法
带色彩恢复的多尺度视网膜(Multi-Scale Retinex with Color Restoration)算法是对MSR的改进【1】
\left\{\begin{aligned}R_{MSRCR} & = & P_{gain}(R_{MSR}*R_{color}+P_{offset})\\ R_{color} & = & \beta log(\alpha L)-log(\sum_{c=1}^3{L(x,y,c)})\\ \end{aligned}\right.
代码&对比
以下代码参考光照问题之常见算法比较(附Python代码)
class retinex(object):
def repair(self, img, sigma, type):
if type == 0:
return self.repair_SSR(img, sigma)
if type == 1:
return self.repair_MSR(img, sigma)
if type == 2:
return self.repair_MSRCR(img, sigma, 5, 25, 125, 46, 0.01, 0.8)
def repair_SSR(self, img, sigma):
# 单尺度
# 其实感觉跟形态学顶帽差不多的意思
temp = cv2.GaussianBlur(img, (0,0), sigma)
gaussian = np.where(temp == 0, 0.01, temp)
retinex = np.log10(img+0.01) - np.log10(gaussian)
return retinex
def repair_MSR(self, img, sigma_list):
# 多尺度
retinex = np.zeros_like(img*1.0)
for sigma in sigma_list:
retinex += self.repair_SSR(img, sigma)
retinex = retinex / len(sigma_list)
return retinex
def repair_MSRCR(self, img, sigma_list, gain, offset, alpha, beta, low_clip, high_clip):
# 带颜色恢复的多尺度
img = np.float64(img) + 1.0
img_msr = self.repair_MSR(img, sigma_list)
img_color = self.color_restor(img, alpha, beta)
img_msrcr = gain * (img_msr * img_color + offset)
for ch in range(img_msrcr.shape[2]):
img_msrcr[:,:,ch] = (img_msrcr[:,:,ch] - np.min(img_msrcr[:,:,ch])) / \
(np.max(img_msrcr[:,:,ch]) - np.min(img_msrcr[:,:,ch]))*255
img_msrcr = np.uint8(np.minimum(np.maximum(img_msrcr, 0), 255))
img_msrcr = self.color_balance(img_msrcr, low_clip, high_clip)
return img_msrcr
def color_restor(self, img, alpha, beta):
img_sum = np.sum(img, axis=2, keepdims=True)
color_res = beta * (np.log10(alpha*img) - np.log10(img_sum))
return color_res
def color_balance(self, img, low, high):
area = img.shape[0]*img.shape[1]
for ch in range(img.shape[2]):
unique, counts = np.unique(img[:,:,ch], return_counts=True)
current = 0
low_val = 0
high_val = 0
for u, c in zip(unique, counts):
if float(current) / area < low:
low_val = u
if float(current) / area < high:
high_val = u
current += c
img[:,:,ch] = np.maximum(np.minimum(img[:,:,ch], high_val), low_val)
return img
python


图1. 左上:原图;右上:SSR;左下:MSR;右下:MSRCR

图2. 左上:原图;右上:SSR;左下:MSR;右下:MSRCR

图3. 左上:原图(过曝);右上:SSR;左下:MSR;右下:MSRCR
可以看到,MSRCR处理后颜色失真比较小
参考文献
【1】Jobson D J, Rahman Z, Woodell G A. A multiscale retinex for bridging the gap between color images and the human observation of scenes[J]. IEEE Transactions on Image processing, 1997, 6(7): 965-976.
