文章目录

  • 前言
  • 原理
  • 发展
    • 单尺度算法(SSR)
    • 多尺度算法(MSR)
    • 带有色彩恢复的多尺度
  • 实现

前言

Retinex算法由Land于1986年在《An alternative technique for the computation of the designator in the retinex theory of color vision》一文中提出,其实质上是一种基于光照补偿的图像增强算法。图像处理领域主要应用在:

  1. 光照不均匀图像的抑制
  2. 图像亮度增强,细节的保护,色彩的保护,自然度的恢复等等
  3. 图像去噪(噪声属于高频信息,可将噪声留在反射分量中再去噪)
  4. 细节提取(类似于Canny边缘提取)
  5. 图像结构和纹理的单部分获取

原理

输入图像由照度分量和反射分量两部分组成,即:
I(x,y)=L(x,y)R(x,y)I(x,y)=L(x,y)R(x,y)I(x,y)=L(x,y)R(x,y)
其中,LLL为亮度分量,描述照明,变化缓慢,处于低频部分;RRR为反射分量,描述景物细节,变化较快,处于高频部分。
Retinex算法对图像的处理目的就是从图像III中获取反射分量RRR。算法流程如下:

发展

Retinex算法理论有两个经典算法:基于路径的Retinex以及基于中心环绕Retinex。基于中心环绕Retinex又从单尺度(Single Scale Retinex)到多尺度(Multi Scale Retinex),再发展至带有色彩恢复的多尺度(Multi Scale Retinex with Color Restoration)以及其他更多的改进。在此只学习基于中心环绕的三个典型算法。

单尺度算法(SSR)

步骤:
第一步:输入原图像I(x,y)I(x,y)I(x,y),分离三个颜色分量;
第二步:构建高斯环绕函数G(x,y)=Ke−x2+y2σ2G(x,y)=K e^{-\frac{x^{2}+y^{2}}{\sigma^{2}}}G(x,y)=Ke−σ2x2+y2​,确定尺度参数σ\sigmaσ,一般取80至100,K为归一化常数,满足∫∫G(x,y,σ)dxdy=1\int\int G(x,y,\sigma)dxdy=1∫∫G(x,y,σ)dxdy=1;
第三步:利用高斯环绕分别对B、G、R三个通道进行滤波L(x,y)=I(x,y)∗G(x,y)L(x,y)=I(x,y)\ast G(x,y)L(x,y)=I(x,y)∗G(x,y),滤波后的图像便是所估计的光照分量L(x,y)L(x,y)L(x,y);
第四步:取对数并对原始图像和光照分量进行相减log⁡R(x,y)=log⁡I(x,y)L(x,y)=log⁡I(x,y)−log⁡L(x,y)\log R(x,y)=\log \frac{I(x,y)}{L(x,y)}=\log I(x,y)-\log L(x,y)logR(x,y)=logL(x,y)I(x,y)​=logI(x,y)−logL(x,y);
第五步:做指数变换elog⁡R(x,y)=R(x,y)e^{\log R(x,y)}=R(x,y)elogR(x,y)=R(x,y),但实际操作中一般先计算出log⁡R(x,y)\log R(x,y)logR(x,y)的最大值Max和最小值Min,然后对每个值Value进行线性量化:R(x,y)=(Value−Min)(255−0)(Max−Min)R(x,y)=\frac{(Value-Min)(255-0)}{(Max-Min)}R(x,y)=(Max−Min)(Value−Min)(255−0)​;
第六步:输出反射分量作为结果图像。

注: 高斯函数σ\sigmaσ是唯一可调的参数,和高斯滤波一样,对结果有直接影响。

多尺度算法(MSR)

SSR算法在动态范围压缩和色调恢复的两种效果中不能兼得,只能牺牲一种来得到另一种,因此基于该缺点提出了不同尺度下的增强结果线性地组合在一起,将局部信息和整体信息考虑进去的多尺度算法,最终能得到具有良好动态范围压缩、色彩稳定性和色彩恢复的图片。
其基本思想是:将图像依照灰度值分为若干级,分别使用单尺度风阀,最后使用系数加权得到处理结果。
步骤:
第一步:输入原图像I(x,y)I(x,y)I(x,y),按灰度值分为若干尺度级,并分离三个颜色分量;
第二步:构建尺度参数不同的高斯环绕函数:Gk(x,y)G_{k}(x,y)Gk​(x,y),一般建立三个尺度比例为15:80:25015:80:25015:80:250较为合适;
第三步:利用高斯环绕函数分别对B、G、R三个通道进行卷积滤波,并加权平均得到照度分量L(x,y)=∑k=1Nωk(Ii(x,y)∗Gk(x,y))L(x,y)=\sum_{k=1}^{N}\omega_{k}(I_{i}(x,y)\ast G_{k}(x,y))L(x,y)=∑k=1N​ωk​(Ii​(x,y)∗Gk​(x,y)),其中,∑k=1Nωk=1\sum_{k=1}^{N}{\omega_{k}}=1∑k=1N​ωk​=1;
第四步:取对数并对原始图像和光照分量进行相减log⁡Ri(x,y)=∑k=1Nωk(log⁡(Ii(x,y))−log⁡(Ii(x,y)∗Gk(x,y)))\log R_{i}(x,y)=\sum_{k=1}^{N}\omega_{k}(\log(I_{i}(x,y))-\log(I_{i}(x,y)\ast G_{k}(x,y)))logRi​(x,y)=∑k=1N​ωk​(log(Ii​(x,y))−log(Ii​(x,y)∗Gk​(x,y)));
第五步:将对数域转变到实数域R(x,y)R(x,y)R(x,y);
第六步:输出反射分量作为结果图像。

可以发现相对于单尺度,多尺度算法对第二和第三两个步骤进行了改进。

带有色彩恢复的多尺度

MSRCR
在前两种方法中图像可能会有局部细节色彩失真,不能显出物体的真正颜色,所以针对这点Daniel J. Jobson等人于1997年在《A Multiscale Retinex for Bridging the Gap Between Color Images and the Human Observation of Scenes》一文提出了MSRCR该算法在MSR的基础上增加了一个色彩恢复的步骤。

色彩恢复ci(x,y)=Ii(x,y)∑j=1NIj(x,y)c_{i}(x,y)=\frac{I_{i}(x,y)}{\sum_{j=1}^{N}I_{j}(x,y)}ci​(x,y)=∑j=1N​Ij​(x,y)Ii​(x,y)​,其中,Ii(x,y)I_{i}(x,y)Ii​(x,y)是原图像像素值,在RGB色彩空间中N=3,i,ji,ji,j表示三个色彩通道。
对其做对数变换可得:
Ci(x,y)=β⋅log⁡[α⋅ci(x,y)]=β⋅{log⁡[α⋅Ii(x,y)]−log⁡[∑j=1NIj(x,y)]}C_{i}(x,y)=\beta \cdot \log[\alpha \cdot c_{i}(x,y)]=\beta \cdot\{\log[\alpha \cdot I_{i}(x,y)]-\log[\sum_{j=1}^{N}I_{j}(x,y)]\}Ci​(x,y)=β⋅log[α⋅ci​(x,y)]=β⋅{log[α⋅Ii​(x,y)]−log[j=1∑N​Ij​(x,y)]}
其中,α\alphaα 用来调节非线性变换,β\betaβ是增益常数。
MSRCR计算公式为:
log⁡RMSRCRi(x,y)=Ci(x,y)⋅log⁡RMSRi(x,y)=β⋅log⁡RMSRi(x,y){log⁡[α⋅Ii(x,y)]−log⁡[∑j=1NIj(x,y)]}\log R_{MSRCR_{i}}(x,y)=C_{i}(x,y)\cdot \log R_{MSR_{i}}(x,y)=\beta \cdot \log R_{MSR_{i}}(x,y)\{\log[\alpha \cdot I_{i}(x,y)]-\log[\sum_{j=1}^{N}I_{j}(x,y)]\}logRMSRCRi​​(x,y)=Ci​(x,y)⋅logRMSRi​​(x,y)=β⋅logRMSRi​​(x,y){log[α⋅Ii​(x,y)]−log[j=1∑N​Ij​(x,y)]}
实际中需要对对数域中的像素值进行拉伸处理,可得到MSRCR计算公式为:
log⁡RMSRCRi(x,y)=G[Ci(x,y)⋅log⁡RMSRi(x,y)+b]=G[Ci(x,y){log⁡Ii(x,y)−log⁡[Ii(x,y)∗Gn(x,y)]}+b]\log R_{MSRCR_{i}}(x,y)=G[C_{i}(x,y)\cdot \log R_{MSR_{i}}(x,y)+b]=G[C_{i}(x,y)\{\log I_{i}(x,y)-\log[I_{i}(x,y)\ast G_{n}(x,y)]\}+b]logRMSRCRi​​(x,y)=G[Ci​(x,y)⋅logRMSRi​​(x,y)+b]=G[Ci​(x,y){logIi​(x,y)−log[Ii​(x,y)∗Gn​(x,y)]}+b]
其中,G和b为经验参数。

具有颜色恢复的多尺度 Retinex (MSRCR) 将小尺度 Retinex 的动态范围压缩和大规模 Retinex 的色调再现与普遍应用的颜色恢复相结合。

实现

SSR:

# SSR
import cv2
from numpy import nonzero
from numpy import float32
from skimage.metrics import peak_signal_noise_ratio
from skimage.metrics import structural_similarity
import csvdef replaceZeroes(data):min_nonzero = min(data[nonzero(data)])##data中不为0数字的位置中的最小值data[data == 0] = min_nonzero##data中为0的位置换为最小值return datadef SSR(img, sigma):B, G, R = cv2.split(img)def channel(C):L_C = cv2.GaussianBlur(C, (5, 5), sigma)##L(x,y)=I(x,y)∗G(x,y)h, w = C.shape[:2]C = replaceZeroes(C)C = C.astype(float32) / 255L_C = replaceZeroes(L_C)L_C = L_C.astype(float32) / 255dst_C = cv2.log(C)  ##logI(x,y)dst_L_C = cv2.log(L_C)  ##logL(x,y)log_R_C = cv2.subtract(dst_C, dst_L_C)  ##logR(x,y)=logI(x,y)−logL(x,y)minvalue, maxvalue, minloc, maxloc = cv2.minMaxLoc(log_R_C)  ##量化处理for i in range(h):for j in range(w):log_R_C[i, j] = (log_R_C[i, j] - minvalue) * 255.0 / (maxvalue - minvalue)  ##R(x,y)=(value-min)(255-0)/(max-min)C_uint8 = cv2.convertScaleAbs(log_R_C)return C_uint8B_uint8 = channel(B)G_uint8 = channel(G)R_uint8 = channel(R)image = cv2.merge((B_uint8, G_uint8, R_uint8))return image##存储数据
def writeCsv(image, psnr, ssin):row = [image, psnr, ssim]out = open("D:/Retinex/SSR/result.csv", "a", newline="")csv_writer = csv.writer(out, dialect="excel")csv_writer.writerow(row)##输入图片执行
for j in range(10, 100):test = cv2.imread("D:/Infrared_image/00{}.jpg".format(str(j)))print(f"00{j}.jpg:")result = SSR(test, 80)#cv2.imshow("test", test)#cv2.imshow("result", result)cv2.imwrite("D:/Retinex/SSR/result/00{}.jpg".format(str(j)), result)key = cv2.waitKey(0)cv2.destroyAllWindows()#writeCsv("image", "psnr", "ssim")  ##表头# 计算psnr及ssimtest = cv2.cvtColor(test, cv2.COLOR_BGR2GRAY)  # 转换为灰度图片result = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)psnr = peak_signal_noise_ratio(test, result)ssim = structural_similarity(test, result)# print(f"psnr={psnr}")# print(f"ssim={ssim}")writeCsv(j, psnr, ssim)

输入图像:

σ\sigmaσ为80时输出为:

对应psnr为:13.1918870131122
对应ssim为:0.673577787550732
MSR:

# MSR
def MSR(img, sigma_list):B, G, R = cv2.split(img)weight = 1 / 3.0scales_size = 3def channel(C, sigma_list):for i in range(0, scales_size):C = replaceZeroes(C)C = C.astype(float32) / 255L_C = cv2.GaussianBlur(C, (5, 5), sigma_list[i])##L(x,y)=I(x,y)∗G(x,y)print(sigma_list[i])h, w = C.shape[:2]log_R_C = zeros((h, w), dtype=float32)L_C = replaceZeroes(L_C)L_C = L_C.astype(float32) / 255log_C = cv2.log(C)##logI(x,y)log_L_C = cv2.log(L_C)##logL(x,y)log_R_C += weight * cv2.subtract(log_C, log_L_C)##=logR(x,y)=w(logI(x,y)−logL(x,y))minvalue, maxvalue, minloc, maxloc = cv2.minMaxLoc(log_R_C)for i in range(h):for j in range(w):log_R_C[i, j] = (log_R_C[i, j] - minvalue) * 255.0 / (maxvalue - minvalue)  ##R(x,y)=(value-min)(255-0)/(max-min)C_uint8 = cv2.convertScaleAbs(log_R_C)return C_uint8B_uint8 = channel(B, sigma_list)G_uint8 = channel(G, sigma_list)R_uint8 = channel(R, sigma_list)image = cv2.merge((B_uint8, G_uint8, R_uint8))return image

输入图片与SSR一样,
sigma_list为15,80,250时输出为:

对应psnr为:13.2062748786571
对应ssim为:0.67356703973411
MSRCR:


def replaceZeroes(data):min_nonzero = min(data[nonzero(data)])data[data == 0] = min_nonzeroreturn datadef colorRestoration(img, alpha, beta):img_sum = np.sum(img, axis=None, keepdims=True)color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum))#求取Creturn color_restorationdef simplestColorBalance(img, low_clip, high_clip):total = img.shape[0] * img.shape[1]for i in range(img.shape[2]):unique, counts = np.unique(img[:, :, i], return_counts=True)current = 0for u, c in zip(unique, counts):if float(current) / total < low_clip:low_val = uif float(current) / total < high_clip:high_val = ucurrent += cimg[:, :, i] = np.maximum(np.minimum(img[:, :, i], high_val), low_val)return imgdef MSR(img, sigma_list):B, G, R = cv2.split(img)weight = 1 / 3.0scales_size = 3def channel(C, sigma_list):for i in range(0, scales_size):C = replaceZeroes(C)C = C.astype(float32) / 255L_C = cv2.GaussianBlur(C, (5, 5), sigma_list[i])##L(x,y)=I(x,y)∗G(x,y)#print(sigma_list[i])h, w = C.shape[:2]log_R_C = zeros((h, w), dtype=float32)L_C = replaceZeroes(L_C)L_C = L_C.astype(float32) / 255log_C = cv2.log(C)##logI(x,y)log_L_C = cv2.log(L_C)##logL(x,y)log_R_C += weight * cv2.subtract(log_C, log_L_C)##=logR(x,y)=w(logI(x,y)−logL(x,y))minvalue, maxvalue, minloc, maxloc = cv2.minMaxLoc(log_R_C)for i in range(h):for j in range(w):log_R_C[i, j] = (log_R_C[i, j] - minvalue) * 255.0 / (maxvalue - minvalue)  ##R(x,y)=(value-min)(255-0)/(max-min)C_uint8 = cv2.convertScaleAbs(log_R_C)return C_uint8B_uint8 = channel(B, sigma_list)G_uint8 = channel(G, sigma_list)R_uint8 = channel(R, sigma_list)image = cv2.merge((B_uint8, G_uint8, R_uint8))return imagedef MSRCR(img, sigma_list, G, b, alpha, beta, low_clip, high_clip):img = np.float64(img) + 1.0img_retinex = MSR(img, sigma_list)#先做MSR处理img_color = colorRestoration(img, alpha, beta)#计算色彩恢复Cimg_msrcr = G * (img_retinex * img_color + b)#MSRCR处理for i in range(img_msrcr.shape[2]):img_msrcr[:, :, i] = (img_msrcr[:, :, i] - np.min(img_msrcr[:, :, i])) / \(np.max(img_msrcr[:, :, i]) - np.min(img_msrcr[:, :, i])) * \255 #转换为实数域img_msrcr = np.uint8(np.minimum(np.maximum(img_msrcr, 0), 255))#图片格式恢复img_msrcr = simplestColorBalance(img_msrcr, low_clip, high_clip)#色彩平衡处理return img_msrcr

输入图片同上
输出结果为:

对应psnr为:5.7753713026592
对应ssim为:0.0997847741077085

个人学习笔记分享,错误望请指正!

(学习笔记)图像处理——Retinex增强相关推荐

  1. PyTorch学习笔记——图像处理(transforms.Normalize 归一化)

    PyTorch学习笔记--图像处理 transforms.Normalize 归一化 回顾 torchvision.ToTensor 归一化 transforms.Normalize 公式 回顾 to ...

  2. Opencv学习笔记——图像伪色彩增强

    以下均为github上opencv的个人学习笔记,原路径如下: https://github.com/JimmyHHua/opencv_tutorials 源码示例: import cv2 as cv ...

  3. 数字图像处理学习笔记-图像处理基础1

    该学习笔记主要参考<数字图像处理(冈萨雷斯 第三版)>,该笔记主要分为"图像处理基础""图像频率域处理""图像分割"" ...

  4. 【Pytorch学习笔记】数据增强

    前言 torchvision 模块包含常用的数据集,模型建构,图像变换算法,分别是torchvision.datasets,torchvision.models,torchvision.transfo ...

  5. spring学习笔记(14)引介增强详解:定时器实例:无侵入式动态增强类功能

    引介增强实例需求 在前面我们已经提到了前置.后置.环绕.最终.异常等增强形式,它们的增强对象都是针对方法级别的,而引介增强,则是对类级别的增强,我们可以通过引介增强为目标类添加新的属性和方法,更为诱人 ...

  6. 数字图像处理学习笔记(三)——空间分辨率和灰度分辨率、等偏爱曲线

    数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声.增强.复原.分割.提取特征等处理的方法和技术.本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结 ...

  7. 基于python的数字图像处理--学习笔记(三)

    基于python的数字图像处理--学习笔记(三) 前言 一.灰度拉伸 二.幂律(伽马)变换 三.对数变换 前言 进入冈萨雷斯的第三章内容,并用python实现功能.我更改了代码源,之前找到太烂了,代码 ...

  8. 数字图像处理MATLAB学习笔记(五)

    数字图像处理MATLAB学习笔记(五) Color Image Processing 1 Color Image Representation in MATLAB 这里不多说了,彩色图片在计算机中以R ...

  9. 数字图像处理学习笔记(一)

    文章目录 前言 第一章绪论 1.1 什么是数字图像处理 数字图像: 数字图像处理: 像素: 图像处理的三种典型计算处理: 1.2 数字图像处理起源 1.3 数字图像处理应用 1.4 数字图像处理基本内 ...

  10. 数字图像处理学习笔记(十五)——图像复原与重建

    数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声.增强.复原.分割.提取特征等处理的方法和技术.本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结 ...

最新文章

  1. C++中最好不要在构造函数和析构函数中调用虚函数!!!
  2. HDU 3336 Count the string KMP
  3. 数据存储之属性列表Plist
  4. 【LeetCode从零单排】No21.MergeTwoSortedLists
  5. a*算法流程图_学好流程控制结构轻松应对高考数学程序算法题
  6. linux samba服务器
  7. 关于Python爬虫,一条高效的学习路径
  8. ImportError: cannot import name ‘Optional‘
  9. 社会网络分析-python_体育社 - 运动让生活更有乐趣 - 俱乐部活动在线管理系统...
  10. 【基础】吴恩达机器学习笔记 - 线性回归 代价函数 梯度下降
  11. Vim 实用技术,第 2 部分: 常用插件(转)
  12. 程序内购买 图文攻略
  13. vue-pdf分页预览
  14. oracle中锁表是什么,oracle锁表查询和解锁方法是什么,oracle锁表和解锁
  15. 数据分析实战——二手房信息分布分析
  16. 英语发音规则之26个字母发音规则(A字母)
  17. uboot引导kernel - 4 -gd bd详解
  18. 面对来势汹汹的AI大潮,你该如何应对?
  19. 万字长文让您搞懂云原生!
  20. python 跳跃游戏

热门文章

  1. unity for 易接IOSsdk
  2. Ubuntu下编译nanomsg库
  3. 海康威视录像机(DVR)卡在开机画面
  4. 2017cad光标大小怎么调_把cad光标变大的方法步骤详解
  5. PLSQL官网下载地址
  6. JVM垃圾回收机制详解
  7. 逻辑回归算法原理及python实现
  8. sql server数据库导出表结构和数据
  9. Android gpuimage美颜滤镜,基于GPUImage的实时美颜滤镜
  10. radon变换(c++、OpenCV实现)