图像处理:Retinex算法

news2024/9/28 21:27:50

目录

前言

概念介绍

Retinex算法理论

单尺度Retinex(SSR)

多尺度Retinex(MSR)

多尺度自适应增益Retinex(MSRCR)

Opencv实现Retinex算法

SSR算法

MCR算法

MSRCR算法

效果展示

总结

参考文章


前言

这里将会介绍一种图像增强的算法——Retinex算法。在查找资料的过程中,我发现对于这一部分的讲解并不是很清楚,所以这里我觉得有必要写一篇通俗且清晰的介绍。这里主要介绍三种Retinex算法的变种,它们在原有的Retinex算法的基础上做了进一步的改进和优化。

概念介绍

Retinex是一种常用于图像增强的算法,其核心思想是在保留图像细节信息的前提下,调整图像的对比度和亮度。Retinex算法主要有三种不同的实现方式:单尺度Retinex(SSR)、多尺度Retinex(MSR)和多尺度自适应增益Retinex(MSRCR)。

  • 单尺度Retinex算法假设图像中的光照变化主要集中在低频分量上,因此只需对图像进行一次滤波处理即可去除低频分量,然后对得到的中高频分量进行增强。
  • 多尺度Retinex算法将图像分解成不同尺度的图像,对每个尺度的图像进行增强,以保留不同尺度的细节信息。
  • 多尺度自适应增益Retinex算法综合了前两种算法,先分解成不同尺度的图像,然后使用自适应增益函数对每个尺度的图像进行增强,最后重建图像以达到增强效果。

Retinex算法理论

Retinex的理论基础是三色理论和颜色恒常性。

这意味着物体的颜色是由它对红、绿、蓝三种光线的反射能力来决定的,而不是由反射光强度的绝对值来决定的。同时,物体的颜色也不会受到光照不均匀性的影响,具有一致性。

Retinex模型利用这种颜色恒常性,可以在动态范围压缩、边缘增强和颜色恒常三个方面打到平衡,因此可以对各种不同类型的图像进行自适应的增强,不同于传统的只能增强图像某一类特征的方法。

Retinex理论认为图像是由照度图像与反射图像组成。照度图像指的是物体的入射分量的信息,用L(x, y)表示;反射图像指的是物体的反射部分,用R(x, y)表示。公式:

I(x, y) =R(x, y) * L(x, y)

同时,由于对数形式与人类在感受亮度的过程属性最相近,因此将上述过程转换到对数域进行处理,这样做也将复杂的乘法转换为加法:

i(x, y) = r(x, y) + l(x, y)

Retinex算法的流程一般包括以下几个步骤:

  1. 高斯滤波:对输入图像进行高斯模糊处理,以消除图像中的噪声和细节。

  2. 计算照度图像:将处理后的图像转换为对数空间,并通过高斯滤波计算出照度图像,即物体的入射分量信息。

  3. 计算反射图像:通过计算原始图像和照度图像的差异得到反射图像,即物体的反射部分。

  4. 反对数变换:将照度图像和反射图像转换回线性空间。

  5. 图像拉伸:对输出图像进行亮度调整,以增强图像的对比度和细节。

当然,上面的流程是Retinex基本框架,不同的Retinex算法可能会有不同的细节处理方式。

单尺度Retinex(SSR)

单尺度视网膜算法是 Retinex 算法中最基础的一个算法。运用的就是上面的方法:

  • 将输入图像转换为对数空间:

I_{log}=In(I+1)

其中,I为输入图像,I_{log}为对数图像。

  • 对对数图像进行高斯平滑:

I_{g}=G*I_{log}

其中,I_{g}为平滑后的对数图像,G为高斯滤波核。

  • 计算照度图像:

L=I_{log}-I_{g}

其中,L为照度图像,即物体的入射分量信息。

  • 计算反射图像:

R=I_{log}-L

其中,R为反射图像,即物体的反射部分。

  • 将照度图像和反射图像进行指数变换:

L_{exp}=exp(L)-1\qquad R_{exp}=exp(R)-1

其中,L_{exp}R_{exp}分别为指数变换后的照度图像和反射图像。

  • 对输出图像进行亮度调整:

O=\frac{R_{exp}}{max(R_{exp})}x255

其中,O为输出图像,max(R_{exp})为反射图像中的最大值。通过将反射图像归一化到[0,1]区间,再将其放大到[0, 255]区间,可以增强图像的对比度和细节。

需要注意的是,SSR算法中只使用了一个固定的高斯滤波尺度(没有使用高斯滤波,只是高斯核),因此称为单尺度Retinex。虽然算法简单,但在一些场景下仍能取得较好的效果。

多尺度Retinex(MSR)

1.将原始图像分解为多个尺度的图像

I_{0}=G(I_{0},\sigma _{0})

I_{1}=G(I_{0},\sigma _{1})

......

I_{n}=G(I_{0},\sigma _{n})

其中G为高斯滤波器,\sigma_{i}表示第i层尺度的高斯核尺度,I_{i}表示第i层尺度的图像。

2.对每一层尺度图像进行 Retinex 处理

L_{i}=log(I_{i})-log{G(I_{i},\sigma _{g})}

S_{i}=log{G(I_{i},\sigma _{s})}-log{G(I_{i},\sigma _{g})}

R_{i}=exp(L_{i}+S_{i})

其中L_{i}表示第i层尺度的反射分量,S_{i}表示第i层尺度的光照分量,R_{i}表示第i层尺度的增强后的图像。

3.将各层增强后的图像进行加权融合,得到最终的增强图像

R_{f}=\frac{\sum _{i=0}^{n}w_{i}R_{i}}{\sum _{i=0}^{n}w_{i}}

其中w_{i}表示第i层尺度的权重。

综上所述,多尺度Retinex算法与单尺度Retinex算法的不同之处在于对图像的分解方式,它将原始图像分解为多个尺度的图像,然后对每一层尺度的图像进行Retinex处理,最后进行加权融合得到最终的增强图像。

多尺度自适应增益Retinex(MSRCR)

MSRCR算法是在MSR算法的基础上进一步改进而来的,主要是通过自适应增益控制算法的方式来实现对图像的增强。相对于MSR算法,MSRCR算法主要增加了以下步骤:

  • 多尺度分解:将原始图像分解成不同尺度的子图像。
  • 对数域操作:对每个尺度下的子图像进行对数变换,得到对数域图像。
  • 自适应增益控制:对于每个尺度下的对数域图像,通过计算每个像素点周围像素点的标准差,来确定该像素点的增益系数,即:

G_{i,j}=\frac{\sigma _{i,j}^{2}}{\sigma _{i,j}^{2}+k}

其中,G_{i,j}表示像素点(i,j)的增益系数,\sigma_{i,j}表示像素点(i,j)周围的像素点的标准差,k为一个常数,用于控制增益系数的大小。

  • 增强处理:对每个尺度下的对数域图像进行乘法增强,即:

L_{i,j}^{'}=G_{i,j}*L_{i,j}

其中,L_{i,j}^{'}为增强后的像素值,L_{i,j}为原始对数域图像的像素值。

  • 逆对数变换:对每个尺度下的增强后的对数域图像进行逆对数变换,得到增强后的子图像。
  • 尺度合成:将所有增强后的子图像进行合成,得到最终增强后的图像。

需要注意的是,MSRCR算法中的增益系数计算公式与MSR算法不同,增加了常数k,这样可以控制增益系数的大小,避免增益系数过大导致图像的过度增强。此外,MSRCR算法中还增加了多尺度分解、增强处理和尺度合成等步骤,进一步提高了对不同尺度、不同光照条件下图像的增强效果。

Opencv实现Retinex算法

在python中是没有集成的第三方库的函数(可能调查不到位),这里我们就根据它的这个原理来实现这三种Retinex算法。

在我这里我讲详细一点,尽量让大家去理解,而不是只是套代码去用。

SSR算法

def SSR(img, sigma):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    img_fft = np.fft.fft2(img_log)
    G_recs = sigma // 2 + 1
    result = np.zeros_like(img_fft)
    rows, cols, deep = img_fft.shape
    for z in range(deep):
        for i in range(rows):
            for j in range(cols):
                for k in range(1, G_recs):
                    G = np.exp(-((np.log(k) - np.log(sigma)) ** 2) / (2 * np.log(2) ** 2))
                    result[i, j] += G * img_fft[i, j]
    img_ssr = np.real(np.fft.ifft2(result))
    img_ssr = np.exp(img_ssr) - 1
    img_ssr = np.uint8(cv2.normalize(img_ssr, None, 0, 255, cv2.NORM_MINMAX))
    return img_ssr

实现思路:

将输入图像转换为了对数空间。/255将像素值归一化到0到1之间,np.log1p取对数并加1是为了避免出现对数运算中分母为0的情况。二维离散傅里叶变换将图像从空间域变换到频率域,可以提取出图像中的频率信息。G_recs是用于计算高斯核的半径,result用于最后三通道的叠加。然后循环用于计算加权后的频率域图像,再逆二维离散傅里叶变换,得到反射图像,对反射图像进行指数变换,得到最终的输出图像。

MCR算法

def MSR(img, scales):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    result = np.zeros_like(img_log)
    img_light = np.zeros_like(img_log)
    r, c, deep = img_log.shape
    for z in range(deep):
        for scale in scales:
            kernel_size = scale * 4 + 1
            # 高斯滤波器的大小,经验公式kernel_size = scale * 4 + 1
            sigma = scale
            img_smooth = cv2.GaussianBlur(img_log[:, :, z], (kernel_size, kernel_size), sigma)
            img_detail = img_log[:, :, z] - img_smooth
            result[:, :, z] += cv2.resize(img_detail, (c, r))
            img_light[:, :, z] += cv2.resize(img_smooth, (c, r))
    img_msr = np.exp(result+img_light) - 1
    img_msr = np.uint8(cv2.normalize(img_msr, None, 0, 255, cv2.NORM_MINMAX))
    return img_msr

实现思路:

MSR算法在图像增强中与SSR不同的是,它不需要进行频域变换,它主要是基于图像在多个尺度下的平滑处理和差分处理来提取图像的局部对比度信息和全局对比度信息,从而实现对图像的增强。

在 MSR 算法中,先对图像进行对数变换得到对数图像,然后在不同的尺度下,使用高斯滤波对图像进行平滑处理,得到不同尺度下的平滑图像。接着,通过将对数图像和不同尺度下的平滑图像进行差分,得到多个尺度下的细节图像。最后,将这些细节图像加权融合,输出最终的增强图像。

关于尺度选择

经验上来说,选择的尺度范围通常是1到10左右,也就是说选择3到4个不同的尺度值进行多尺度处理。尺度的大小可以取任意奇数或偶数,但是建议就选奇数尺度大小,这样可以保证在进行高斯滤波时,中心像素周围的权值更大,从而更好地保留图像的细节信息。

MSRCR算法

def MSRCR(img, scales, k):
    img_log = np.log1p(np.array(img, dtype="float") / 255)
    result = np.zeros_like(img_log)
    img_light = np.zeros_like(img_log)
    r, c, deep = img_log.shape
    for z in range(deep):
        for scale in scales:
            kernel_size = scale * 4 + 1
            # 高斯滤波器的大小,经验公式kernel_size = scale * 4 + 1
            sigma = scale
            G_ratio=sigma**2/(sigma**2+k)
            img_smooth = cv2.GaussianBlur(img_log[:, :, z], (kernel_size, kernel_size), sigma)
            img_detail = img_log[:, :, z] - img_smooth
            result[:, :, z] += cv2.resize(img_detail, (c, r))
            result[:, :, z]=result[:, :, z]*G_ratio
            img_light[:, :, z] += cv2.resize(img_smooth, (c, r))

    img_msrcr = np.exp(result+img_light) - 1
    img_msrcr = np.uint8(cv2.normalize(img_msrcr, None, 0, 255, cv2.NORM_MINMAX))
    return img_msrcr

实现思路:

这一部分我只是将MSR的实现进行了扩充,添加了自适应增益控制,即是对于每个尺度下的对数域图像,通过计算每个像素点周围像素点的标准差,来确定该像素点的增益系数。这里的k值为一个常数,我的建议是取10-20之间,当k取值较小时,图像的细节增强效果比较明显,但会出现较强的噪点,当k取值较大时,图像的细节增强效果不明显,但噪点会减少。因此,需要根据实际应用场景进行适当的调整。

效果展示

上(左)原图,上(右)SSR,下(左)MSR,下(左)MSRCR 
if __name__=="__main__":
    path=r'./Images/AI2.png'
    img=cv2.imread(path)
    imgSSR=SSR(img,7)
    imgMSR=MSR(img, [1, 3, 5])
    imgMSRCR=MSRCR(img,[1,3,5],12)
    imgStack=zjr.stackImages(0.6,([img,imgSSR],[imgMSR,imgMSRCR]))
    cv2.imshow("retinex",imgStack)
    cv2.waitKey(0)

总结

在尝试实现像Retinex这种没有集成函数的算法时,我遇到了一些困难。这些算法需要深入理解其原理和流程,并在代码具体实现。为了解决这些问题,我参考了其他大佬的代码,但大多数代码并不完整,经常出现报错。我也只能依照自己对算法的理解来实现其功能,可能存在部分错误。因此,我希望可以与大家共同讨论,一起学习和进步。

参考文章

(6条消息) Retinex 算法_chaiky的博客-CSDN博客

(7条消息) Retinex算法详解_ChenLee_1的博客-CSDN博客

(6条消息) Retinex图像增强算法——SSR,MSR,MSRCR,MSRCP,autoMSRCR_Chaoy6565的博客-CSDN博客

传统图像处理——图像增强Retinex - 知乎 (zhihu.com)

Retinex图像增强算法理论基础 - 知乎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/486482.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基频建模方法总结

基频F0建模方法 语音合成领域需要对基频进行建模,具体到文语转换TTS、语音转换VC、情感语音转换EVC领域等。 语音合成F0 包括文语转换,情感语音转换 TTEF:text-to-emotional-features synthesis EVC:emotional voice conversio…

这些你熟知的 app 和服务,都用上了人工智能

从微软在 Microsoft 365 服务中全面整合 GPT-4 能力 ,让 PPT、Word 文档、Excel 表格的制作变成了「一句话的事」,到 Adobe 刚刚发布 Adobe Firefly模型集合,让图形设计、字体风格、视频渲染乃至 3D 建模的门槛显著降低——你我熟知的那些工…

idea的快捷键

一.idea的快捷键: 递进选择&#xff1a;ctrl w复制行&#xff1a;ctrl d删除行&#xff1a;ctrl y大小写切换&#xff1a;ctrl shift u展开/折叠&#xff1a;ctrl shift 减号/加号向前/向后&#xff1a;ctrl <— / —>Live Template(例如 输入psvm会自动打出mai…

华为OD机试题,用 Java 解【最远足迹】问题

华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不要…

Python实战项目:手势识别控制电脑音量

今天给大家带来一个OpenCV的实战小项目——手势识别控制电脑音量 先上个效果图&#xff1a; 通过大拇指和食指间的开合距离来调节电脑音量&#xff0c;即通过识别大拇指与食指这两个关键点之间的距离来控制电脑音量大小 技术交流 技术要学会分享、交流&#xff0c;不建议闭…

石英晶体振荡器【Multisim】【高频电子线路】

目录 一、实验目的与要求 二、实验仪器 三、实验内容与测试结果 1、观察输出波形&#xff0c;测量振荡频率和输出电压幅度 2、测量静态工作点的变化范围(IEQmin~IEQmax) 3、测量当静态工作点在上述范围时输出频率和输出电压的变化 4、测量负载变化对振荡频率和输出电压幅…

SpringCloud:微服务保护之初识Sentinel

1.初识Sentinel Sentinel是阿里巴巴开源的一款微服务流量控制组件。Sentinel官网 Sentinel具有以下特征&#xff1a; 丰富的应用场景&#xff1a;Sentinel承接了阿里巴巴近 10 年的双十一大促流量的核心场景&#xff0c;例如秒杀&#xff08;即突发流量控制在系统容量可以承受…

JavaEE阶段测试复习

文章全部内容在个人站点内的置顶文章中,访问密码:AIIT 小凯的宝库 模块三、面向对象 继承: a. 单继承:Java只支持单继承,即一个子类只能有一个直接父类。但子类可以间接地继承多个父类。 b. 构造方法与继承:在子类中可以通过super()关键字调用父类的构造方法。如果子类没…

探索深度学习中的计算图:PyTorch的动态图解析

❤️觉得内容不错的话&#xff0c;欢迎点赞收藏加关注&#x1f60a;&#x1f60a;&#x1f60a;&#xff0c;后续会继续输入更多优质内容❤️ &#x1f449;有问题欢迎大家加关注私戳或者评论&#xff08;包括但不限于NLP算法相关&#xff0c;linux学习相关&#xff0c;读研读博…

Windows系统的JDK安装与配置

1 选择JDK版本 以在Windows 64位平台上安装JDK 8版本为例。JDK 8 Windows版官网下载地址&#xff1a;https://www.oracle.com/java/technologies/downloads/#java8-windows 现在下载需要先注册并登录Oracle的账号。 2 安装 双击jdk安装包&#xff0c;进入安装程序页面直接选择…

freetype用法

freetype用法 文章目录 freetype用法0.实现1.变量定义2.lcd操作获取屏幕信息3.freetype初始化4.绘画 1.字形度量2.类1.FT 中的面向对象2.FT_Library 类3.FT_Face 类4 FT_Size 类5 FT_GlyphSlot 类 3.函数1.把一个字符码转换为一个字形索引FT_Get_Char_Index函数2.从 face 中装…

银行家算法--申请资源

银行家算法–申请资源 问题描述&#xff1a; 输入N个进程(N<100)&#xff0c;以及M类资源&#xff08;M<100&#xff09;&#xff0c;初始化各种资源的总数&#xff0c;T0时刻资源的分配情况。例如&#xff1a; 假定系统中有5个进程{P0&#xff0c;P1&#xff0c;P2&…

文字的显示

文字的显示 文章目录 文字的显示1.文字编码方式2.英文和汉字的点阵显示3.显示中文“中”和“A”show_font.c结果 1.文字编码方式 数字>代表什么->显示为什么 GBK国标拓展 下列代码用不同编码方式保存utf-8.c ansi.c #include <stdio.h>int main(int argc ,char *…

MyBaits的注解开发

为什么要用MyBaits注解开发&#xff1f; 前面介绍了MyBatis的基本用法、关联映射、动态SQL和缓存机制等知识&#xff0c;所有的配置都是基于XML文件完成的&#xff0c;但在实际开发中&#xff0c;大量的XML配置文件的编写是非常繁琐的&#xff0c;为此&#xff0c;MyBatis提供…

《Netty》从零开始学netty源码(五十一)之PoolArena的内存释放与扩容

目录 释放空间free()destroyChunk()freeChunk() 扩容reallocate()memoryCopy() 释放空间free() 当chunk使用完毕后需要释放&#xff0c;如果是池化chunk则需要放回池中供下次循环利用&#xff0c;如果是非池化的则直接释放对应的物理空间。 下面继续分析释放具体物理空间的des…

代码随想录算法训练营(总结)|动态规划总结篇

一、动态规划五部曲 确定dp及其下标的含义确定递推关系式初始化值确定遍历顺序验证 二、01背包问题 1. 基本理解 理解&#xff1a;所谓的01背包问题&#xff0c;其关键在于物品只能放入1次&#xff0c;不能够重复利用&#xff0c;因此称呼为01背包问题。与完全背包的区别在…

【深度学习】计算机视觉(十)——Faster RCNN(实践篇)

文章目录 写在最前面 step1&#xff1a;相关说明step2&#xff1a;Prerequisites安装要求tensorflow-gpu1. 安装和测试2. 错误提示① numpy版本② tensorflow版本③TensorRT step3&#xff1a;Installation1. Update your -arch2. Install the Python COCO API3. setup VOC4. D…

【VM服务管家】VM4.2平台SDK_6.4 结果获取类

目录 2.4.1 数据结果&#xff1a;通过流程输出或者模块输出获取数据结果的方法2.4.2 流程回调&#xff1a;某个流程运行开始与结束的回调方法 2.4.1 数据结果&#xff1a;通过流程输出或者模块输出获取数据结果的方法 描述 环境&#xff1a;VM4.2 VS2013及以上 现象&#xff…

从不自量力到 AI 助力,我如何翻译完一整本英文书

披露和声明&#xff1a; 本文提及的翻译作品系使用 AI 技术制作&#xff0c;并经人工调整&#xff0c;具体步骤如文中所述。本文在后期修改过程中使用 ChatGPT 辅助&#xff0c;目的为精简原版中的口语化表述。我的英文水平有限&#xff0c;翻译这本书主要是为了自我学习&…

自动驾驶— Planning - Udacity Self-Driving Car Engineer

第六讲规划 6.1规划简介 在规划中&#xff0c;我们结合了高清地图、定位和预测来构建车辆的轨迹。规划的第一步是路线导航&#xff0c;重点是如何在地图上从A到B。路由以地图数据作为输入&#xff0c;并输出可导航路径。手机上的导航系统就是路线规划的一个例子。在Apollo中&…