图像增强算法Retinex原理与实现详解

news2024/11/26 4:36:35

文章目录

    • 1. 引言
    • 2. Retinex算法原理
      • 2.1 单尺度Retinex
        • 示例代码
      • 2.2 多尺度Retinex
        • 示例代码
      • 2.3 颜色恢复
        • 示例代码
      • 2.4 最终图像处理
        • 代码示例
    • 3. Retinex算法的Python实现
    • 4. 完结

1. 引言

图像增强是图像处理中的重要技术之一,它可以改善图像的亮度、对比度和颜色等视觉效果,使图像更加清晰、鲜明。Retinex是一种经典的图像增强算法,它通过对图像进行多尺度高斯模糊处理和颜色恢复操作来改善图像的视觉效果。本文将详细介绍Retinex算法的原理,并给出了Python实现的示例代码和测试结果。
在这里插入图片描述

2. Retinex算法原理

 Retinex算法原理

Retinex算法是基于人眼视觉系统特性的图像增强算法,它通过对图像进行多尺度的处理来提高图像的亮度和颜色表现。

2.1 单尺度Retinex

在这里插入图片描述

单尺度Retinex算法是Retinex算法的基本操作,它通过对图像进行高斯模糊处理和对数运算来得到增强后的图像。具体步骤如下:

  1. 对输入图像进行高斯模糊处理,使用cv2.GaussianBlur()函数实现,其中参数sigma表示高斯核的标准差。
  2. 对模糊后的图像和原图像分别进行对数运算,得到两个对数图像。
  3. 将两个对数图像相减,得到增强后的图像。

示例代码

import cv2  # 导入OpenCV库,用于图像处理
import numpy as np  # 导入NumPy库,用于科学计算和数组操作

def single_scale_retinex(img, sigma):
    retinex = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), sigma))
    # 计算图像的单尺度Retinex算法
    # np.log10(img) 对输入图像img进行log10变换,将像素值转换为对数域
    # cv2.GaussianBlur(img, (0, 0), sigma) 对输入图像img进行高斯模糊处理,sigma为高斯核的标准差
    # np.log10(...) - np.log10(...) 执行两个结果之间的减法运算,得到Retinex结果
    return retinex

解释说明
这段代码实现了基于单尺度Retinex算法的图像增强

  • import cv2:导入OpenCV库,用于图像处理。

  • import numpy as np:导入NumPy库,用于科学计算和数组操作。

  • def single_scale_retinex(img, sigma)::定义了一个函数single_scale_retinex,接收两个参数imgsigma,分别代表输入的图像和高斯核的标准差。

  • retinex = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), sigma)):计算图像的单尺度Retinex算法。

    • np.log10(img)对输入图像img进行log10变换,将像素值转换为对数域。
    • cv2.GaussianBlur(img, (0, 0), sigma)对输入图像img进行高斯模糊处理,使用高斯核进行图像平滑,其中(0, 0)表示核的大小为自动计算。
    • np.log10(...) - np.log10(...)执行两个结果之间的减法运算,得到Retinex结果。
  • return retinex:返回计算得到的Retinex结果。

2.2 多尺度Retinex

多尺度Retinex

多尺度Retinex是在单尺度Retinex的基础上进一步改进的算法,它通过对不同尺度下的图像进行单尺度Retinex增强,并将结果累加求平均得到最终的增强图像。具体步骤如下:

  1. 定义一个尺度列表sigma_list,包含不同的标准差值。
  2. 循环遍历尺度列表中的每个标准差sigma,调用单尺度Retinex算法对图像进行增强,并将结果逐步累加。
  3. 将累加后的图像除以尺度列表的长度,得到最终的增强图像。

示例代码

def multi_scale_retinex(img, sigma_list):
    retinex = np.zeros_like(img)  # 创建与输入图像相同大小的全零数组,用于存储Retinex结果
    for sigma in sigma_list:
        retinex += single_scale_retinex(img, sigma)
        # 调用single_scale_retinex函数计算单尺度Retinex,并将结果累加到retinex数组中
    retinex = retinex / len(sigma_list)
    # 将累加的Retinex结果除以sigma_list的长度,得到平均Retinex结果
    return retinex

解释说明
这段代码实现了基于多尺度Retinex算法的图像增强。

  • def multi_scale_retinex(img, sigma_list)::定义了一个函数multi_scale_retinex,接收两个参数imgsigma_list,分别代表输入的图像和高斯核的标准差列表。

  • retinex = np.zeros_like(img):创建了一个与输入图像img相同大小的全零数组retinex,用于存储Retinex结果。

  • for sigma in sigma_list::遍历sigma_list中的每个标准差值。

  • retinex += single_scale_retinex(img, sigma):调用single_scale_retinex函数计算单尺度Retinex,并将结果累加到retinex数组中。

  • retinex = retinex / len(sigma_list):将累加的Retinex结果除以sigma_list的长度,得到平均Retinex结果。

  • return retinex:返回计算得到的平均Retinex结果。

2.3 颜色恢复

颜色恢复
颜色恢复是Retinex算法中的一个重要步骤,它通过对各通道像素值进行对数运算,并乘以系数alpha和beta来实现颜色的恢复。具体步骤如下:

  1. 对输入图像的R、G、B三个通道进行分离。
  2. 分别对三个通道的像素值进行对数运算,得到对数图像。
  3. 将对数图像乘以系数alpha和beta,得到颜色恢复后的图像。

示例代码

def color_restoration(img, alpha, beta):
    img_sum = np.sum(img, axis=2, keepdims=True)
    # 对输入图像img沿着第二个维度求和,即对每个像素的RGB通道进行求和操作
    # keepdims=True表示保持结果的维度数量与原图像相同

    color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum))
    # 计算颜色恢复后的图像
    # np.log10(...) 对输入图像alpha * img 进行log10变换,将像素值转换为对数域
    # np.log10(img_sum) 对输入图像img_sum进行log10变换,将像素值转换为对数域
    # np.log10(...) - np.log10(...) 执行两个结果之间的减法运算

    return color_restoration

解释说明
这段代码实现了颜色恢复的功能。

  • def color_restoration(img, alpha, beta)::定义了一个函数color_restoration,接收三个参数imgalphabeta,分别代表输入的图像、颜色强度调整系数和颜色平衡系数。

  • img_sum = np.sum(img, axis=2, keepdims=True):对输入图像img沿着第二个维度(RGB通道)进行求和操作,即对每个像素的RGB通道进行求和。keepdims=True表示保持结果的维度数量与原图像相同,得到一个具有相同大小但通道数为1的数组img_sum

  • color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum)):根据给定的公式计算颜色恢复后的图像。np.log10(alpha * img)对输入图像alpha * img进行log10变换,将像素值转换为对数域;np.log10(img_sum)对输入图像img_sum进行log10变换,将像素值转换为对数域;最后通过一系列运算得到颜色恢复的结果存储在color_restoration变量中。

  • return color_restoration:返回颜色恢复后的图像。

2.4 最终图像处理

最终图像处理是将多尺度Retinex和颜色恢复两个操作结合起来,得到最终的增强图像。具体步骤如下:

  1. 将输入图像转换为浮点数类型,并加上1.0,避免出现除零错误。
  2. 调用多尺度Retinex算法对图像进行增强,得到增强后的图像。
  3. 调用颜色恢复算法对图像进行颜色恢复,得到颜色恢复后的图像。
  4. 对增强后的图像进行亮度和颜色的调整,得到最终的增强图像。
  5. 对最终的增强图像进行像素范围的限制,确保像素值在0-255之间。
  6. 将最终的增强图像转换为无符号整数类型,并返回。

代码示例

def retinex_process(img, sigma_list, G, b, alpha, beta):
    img = np.float64(img) + 1.0
    # 将输入图像转换为float64类型,并加上1.0,用于防止log运算时出现零值

    img_retinex = multi_scale_retinex(img, sigma_list)
    # 调用multi_scale_retinex函数对输入图像进行多尺度Retinex增强处理,
    # 得到增强后的图像img_retinex

    img_color = color_restoration(img, alpha, beta)
    # 调用color_restoration函数对输入图像进行颜色恢复处理,
    # 得到恢复后的图像img_color

    img_retinex = G * (img_retinex * img_color + b)
    # 对增强后的图像img_retinex与恢复后的图像img_color按照一定的公式进行加权融合,
    # 并加上一个常数b,得到最终的Retinex结果img_retinex

    for i in range(img_retinex.shape[2]):
        img_retinex[:, :, i] = np.clip(img_retinex[:, :, i], 0, 255)
    # 对每个通道的像素值进行裁剪,将超过0和255的值限制在0-255范围内

    img_retinex = np.uint8(img_retinex)
    # 将增强后的图像转换为uint8类型,即8位无符号整型

    return img_retinex

解释说明
这段代码实现了Retinex图像处理的流程。

  • def retinex_process(img, sigma_list, G, b, alpha, beta)::定义了一个函数retinex_process,接收六个参数imgsigma_listGbalphabeta,分别代表输入的图像、高斯核的标准差列表、融合权重系数G、常数b、颜色强度调整系数alpha和颜色平衡系数beta。

  • img = np.float64(img) + 1.0:将输入的图像img转换为float64类型,并加上1.0,用于防止log运算时出现零值。

  • img_retinex = multi_scale_retinex(img, sigma_list):调用multi_scale_retinex函数对输入图像进行多尺度Retinex增强处理,得到增强后的图像img_retinex

  • img_color = color_restoration(img, alpha, beta):调用color_restoration函数对输入图像进行颜色恢复处理,得到恢复后的图像img_color

  • img_retinex = G * (img_retinex * img_color + b):对增强后的图像img_retinex与恢复后的图像img_color按照一定的公式进行加权融合,并加上一个常数b,得到最终的Retinex结果img_retinex

  • for i in range(img_retinex.shape[2])::遍历图像img_retinex的第三个维度,即通道数。

  • img_retinex[:, :, i] = np.clip(img_retinex[:, :, i], 0, 255):对每个通道的像素值进行裁剪,将超过0和255的值限制在0-255范围内,使用np.clip函数实现。

  • img_retinex = np.uint8(img_retinex):将增强后的图像img_retinex转换为uint8类型,即8位无符号整型。

  • return img_retinex:返回处理后的Retinex结果图像。

3. Retinex算法的Python实现

基于OpenCV和NumPy库,我们可以很方便地实现Retinex算法。下面是Retinex算法的Python代码实现:

import cv2
import numpy as np

# 对图像进行单尺度 Retinex 处理
def single_scale_retinex(img, sigma):
    retinex = np.log10(img) - np.log10(cv2.GaussianBlur(img, (0, 0), sigma))
    return retinex

# 对图像进行多尺度 Retinex 处理
def multi_scale_retinex(img, sigma_list):
    retinex = np.zeros_like(img)
    for sigma in sigma_list:
        retinex += single_scale_retinex(img, sigma)
    retinex = retinex / len(sigma_list)
    return retinex

# 进行颜色恢复
def color_restoration(img, alpha, beta):
    img_sum = np.sum(img, axis=2, keepdims=True)
    color_restoration = beta * (np.log10(alpha * img) - np.log10(img_sum))
    return color_restoration

# 图像增强主函数,包括图像增强和颜色恢复
def retinex_process(img, sigma_list, G, b, alpha, beta):
    img = np.float64(img) + 1.0
    img_retinex = multi_scale_retinex(img, sigma_list)
    img_color = color_restoration(img, alpha, beta)
    img_retinex = G * (img_retinex * img_color + b)

    # 将像素值限制在范围内
    for i in range(img_retinex.shape[2]):
        img_retinex[:, :, i] = np.clip(img_retinex[:, :, i], 0, 255)
    img_retinex = np.uint8(img_retinex)

    return img_retinex

def main():
    # 读取图像
    img = cv2.imread('WechatIMG9.jpeg')

    # 尺度列表
    sigma_list = [15, 80, 250]
    # 增益参数
    G = 5.0
    # 偏置参数
    b = 25.0
    # 颜色恢复参数
    alpha = 125.0
    # 颜色恢复参数
    beta = 46.0

    # 进行图像增强
    img_retinex = retinex_process(img, sigma_list, G, b, alpha, beta)

    # 显示原始图像
    cv2.imshow('1', img)
    # 显示增强后的图像
    cv2.imshow('Retinex', img_retinex)
    # 等待按键
    cv2.waitKey(0)
    # 保存增强后的图片
    cv2.imwrite('a.jpg', img_retinex)

if __name__ == "__main__":
    main()

代码通过 Retinex 算法对图像进行增强,包括单尺度 Retinex 处理、多尺度 Retinex 处理和颜色恢复。

  • single_scale_retinex 函数:对图像进行单尺度 Retinex 处理,使用对数域操作计算图像的亮度分量。
  • multi_scale_retinex 函数:对图像进行多尺度 Retinex 处理,将多个尺度的 Retinex 处理结果相加并取平均。
  • color_restoration 函数:进行颜色恢复,计算图像的颜色分量。
  • retinex_process 函数:图像增强的主要函数,包括图像增强和颜色恢复操作。
  • main 函数:主函数,在这里读取输入图像,并设定参数,然后调用 retinex_process 函数进行图像增强。
  • 在窗口中显示原始图像和增强后的图像,并保存增强后的图像到文件。

效果展示
原图:

在这里插入图片描述

执行之后的图

在这里插入图片描述

对比图

在这里插入图片描述

4. 完结

期待下一次的更新哦!!!
在这里插入图片描述

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

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

相关文章

微信开发者工具模拟器中不显示鼠标问题

前言 在使用微信开发者工具开发微信小程序时,使用到了第二屏幕,在第一屏幕上,微信开发者工具模拟器中,可以正常显示鼠标,而在第二屏幕上不显示鼠标。 解决方案: 方案1:设置指针轨迹&#xff…

【JMeter分布式压测连接Jenkins生成测试报告报错:Data exporter “html“ is unable to export data】

An error occurred: Data exporter “html” is unable to export data. Build step “Execute shell” marked build as failure 发生了一个错误:数据导出器“html”无法导出数据。 构建步骤“执行shell”将构建标记为失败 查看JMeter-master日志jmeter.log 发现是由于没有r…

基于springboot+vue的文物收藏系统(源代码+数据库+13000字论文)082

基于springbootvue的文物收藏系统(源代码数据库13000字论文)082 一、系统介绍 本项目前后端分离(本项目有ssmvue版本) 本系统分为管理员、用户两种角色 用户角色包含以下功能: 登录、文物查看、文物资料下载、文物收藏管理、文物维护管理、文物封存管理、个人中…

赛效:电子书可以转换成TXT吗

1:在“其他功能”菜单里点击“电子书转TXT”。 2:点击页面中间的号或者拖拽电子书上传。常规格式的电子书,都可以上传。 3:文件添加成功后,点击右下角的“开始转换”。 4:文件转换成功后,点击下…

Vue element admin git安装失败-2023年7月6日

Vue element admin-2023年7月6日 Vue element admin官网安装失败,是由于依赖包,所nodejs要求版本很低,导致和新版的18、16版本不兼容,git下安装失败。解决办法 Vue element admin官网 https://panjiachen.gitee.io/vue-element-a…

大数据的薪资怎么样?是真的很高么

既然提到了数据的问题,其实不妨看一下各大招聘平台在不同城市给出的薪资,百闻不如一见,自己真正看到了就知道能拿多少了。当然,是否能高薪,很大一部分还是取决于自身的能力的 猎聘大数据研究院发布了《2022未来人才就…

【yolov5】训练自己的数据集-实践笔记

【yolov5】训练自己的数据集-实践笔记 使用yolov5训练自己的数据集,以RSOD数据集为例,图像数量976,一共四类。 yolov5源码:https://github.com/ultralytics/yolov5 官网的代码会一直更新,相关依赖环境也会变&#xf…

嵌套和递归使用模板类

嵌套和递归使用模板类 模板栈模板数组栈中嵌套数组数组中嵌套栈数组中嵌套数组 模板栈 #pragma once #include <iostream> // 包含头文件。 using namespace std; // 指定缺省的命名空间。template<class DataType> class mystack2 { private:Data…

Java面向对象程序开发——文件与流

文章目录 前言File类IO字符流与字节流字符流字节流打印流缓冲流 前言 File类 是文件和目录路径名的抽象表示&#xff0c;主要用于文件和目录的创建、查找和删除等操作。 方法有三类&#xff1a;1获取、2判断、3创建或删除 public String getAbsolutePath() &#xff1a;返回…

ELK部署安装

目录 一、环境准备 1.准备三台服务器&#xff08;带图形化的linuxCentOS7&#xff0c;最小化缺少很多环境&#xff09; 2.修改主机名 3.关闭防火墙 4.elk-node1、elk-node2 用系统自带的java 5.上传软件包到node1和node2 二、部署elasticsearch 1、node1、node2操作 2.no…

《华尔街幽灵》的三大交易规则

规则1&#xff1a;只持有正确的仓位 如果你下单后经过一段时间&#xff0c;市场没有证明你的交易是正确的&#xff0c;那么应该立即平仓。交易者在每次建仓后&#xff0c;首先应关注保护本金&#xff0c;及早平掉不正确的仓位&#xff0c;而不是过多考虑盈利金额。 如何判断交…

生命在于学习——风险评估

风险评估的目录 一、网络安全风险评估概述1、概念2、意义3、步骤4、基本原则5、评估要素6、网络安全风险评估方法 二、网络安全风险评估方法三、网络安全风险评估方案1、确定评估范围和目标2、收集信息3、评估威胁和漏洞4、评估安全控制5、评估风险和制定建议6、报告和沟通 四、…

匿名苏丹的网络攻击仍在继续: 继微软之后拳头游戏成为最新目标

黑客组织 "匿名苏丹 "声称&#xff0c;它对美国视频游戏开发商和出版商Riot Games发起了分布式拒绝服务&#xff08;DDoS&#xff09;攻击。 据称匿名苏丹的目标是Riot Games的登录门户&#xff0c;该组织在Telegram帖子中宣布&#xff0c;这次攻击持续了30分钟至1小…

《随便测测》做UI测试

目录 前排提示 使用playwright录制ui操作 创建UI模板 运行用例 查看报告 再次编辑代码 再次查看报告 selenoid服务搭建 配置selenoid服务地址 总结 前排提示 1.使用playwright[selenoid]&#xff0c;可选的远程浏览器执行用例 2.没有采用 PageObjectModule&#xff0…

展示与处理复杂JSON数据——gradio库的JSON模块详解

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

从小白到大神之路之学习运维第54天--------ELK技术堆栈---

第三阶段基础 时 间&#xff1a;2023年7月6日 地 点&#xff1a;2304教室 授课人&#xff1a;李凤海 参加人&#xff1a;全班人员 内 容&#xff1a; ELK技术堆栈 目录 服务器设置&#xff1a; 部署elasticsearch集群&#xff1a; 配置elasticsearch集群&#xff…

Vue2中使用ElementUI组件Form组件的校验validate

先准备一些el-form元素 这里面el-form中:model(v-bind:model)是单项绑定的&#xff0c;如果你写成了v-model""可能会出现校验没有效果的情况。 这是校验过后的结果了 现在开始使用下吧&#xff01; 1.在el-form中绑定一个ref&#xff0c;名字自拟,后续触发检验结果…

【数据分析 - 基础入门之NumPy②】Jupyter Notebook安装及使用

知识目录 前言一、Jupyter Notebook安装使用1.1 Jupyter Notebook的三种打开方式1、点击Anaconda Prompt打开2、点击Jupyter Notebook打开3、使用Powershell打开 1.2 Jupyter Notebook的两种键盘输入模式1、编辑模式2、命令模式 二、Jupyter Notebook魔法命令2.1 查看帮助文档2…

2023-07-06:RabbitMQ中的AMQP是什么?

2023-07-06&#xff1a;RabbitMQ中的AMQP是什么&#xff1f; 答案2023-07-06&#xff1a; AMQP AMQP&#xff08;Advanced Message Queuing Protocol&#xff09;是一个应用层协议的开放标准&#xff0c;旨在设计面向消息的中间件。基于AMQP协议的客户端和消息中间件可以自由…

Mysql中IP地址如何在数据库中存储

用无符号的32位整数存储&#xff0c;不要用字符串存储ip 为什么呢&#xff1f; 在Mysql中&#xff0c;当存储ipv4地址的时候&#xff0c;应该使用32位的无符号&#xff08;int unsigned&#xff09;来存储ip地址&#xff0c;而不是使用字符串&#xff0c;用int unsigned类型存…