Smart Light Random Memory Sprays Retinex 传统图像增强 SLRMSR

文章目录

  • 前言
  • 1、Smart Light Random Memory Sprays Retinex概况
  • 2、Smart Light Random Memory Sprays Retinex的实现
    • 2.1、SLRMSR算法的伪代码
    • 2.2、初始化记忆喷雾(CreateInitialMemorySpray)
    • 2.3、更新记忆喷雾 (UpdateMemorySpray)
    • 2.4、计算颜色校正因子(ComputeColorCorrectionFactor)
    • 2.5、应用强度重映射(ApplyIntensityRemapping)
    • 2.6、应用引导滤波 (ApplyGuidedImageFiltering)
  • 3、Smart Light Random Memory Sprays Retinex效果


前言

  Smart Light Random Memory Sprays Retinex,即“智能光随机记忆喷雾Retinex”,简称SLRMSR。作为一种新的基于Retinex理论的图像增强算法,旨在解决图像亮度调整和颜色校正的问题。


1、Smart Light Random Memory Sprays Retinex概况

论文名称:
Smart light random memory sprays Retinex: a fast Retinex implementation for high-quality brightness adjustment and color correction
作者:
Nikola Banić,Sven Lončarić

  “智能光随机记忆喷雾Retinex”(Smart Light Random Memory Sprays Retinex,简称SLRMSR),该算法提出了记忆喷雾的概念,以减少每个像素操作的数量,从而实现了快速的Retinex基础的局部图像增强。同时提出了一种有效的图像强度重映射的方法,进一步显著地提高了图像的质量。最后通过使用引导滤波作为替代的光照处理方法,减少了原有LRSR算法的光晕效应。作为一种新的基于Retinex理论的图像增强算法,在解决图像亮度调整和颜色校正的问题上,具有显著优势。

2、Smart Light Random Memory Sprays Retinex的实现

2.1、SLRMSR算法的伪代码

在这里插入图片描述

2.2、初始化记忆喷雾(CreateInitialMemorySpray)

  图像第一个像素创建一个包含随机选择的邻近像素强度的记忆喷雾。
① 定义喷雾大小:
  确定记忆喷雾参数的大小n,作为预设值,决定了喷雾中包含像素的数量。
② 选择邻近像素:
  对于图像中每个像素,在其邻域定义一个包含n个随机选择的邻近像素区域。
③ 构建笛卡尔树:
  对于选定的每个邻近像素,收集其RGB强度值,进行笛卡尔树的构造,其每个节点包含子树的最大值。
④ 存储喷雾内容:
  构建好的笛卡尔树被作为存储记忆喷雾的数据结构,用于后续的像素处理。

2.3、更新记忆喷雾 (UpdateMemorySpray)

① 选择新像素:
  当处理新的像素时,算法会从当前像素的局部邻域中选择一个新的邻近像素。
② 更新笛卡尔树:
  新选定的像素强度值被添加到笛卡尔树中,同时,最旧的像素强度值被从树中移除。这种“先进先出”的更新机制确保了记忆喷雾始终反应最新的局部信息。
③ 计算最大值:
  通过笛卡尔树的根节点,可以快速获取当前记忆喷雾中所有像素强度的最大值。

//基于随机内存喷雾Retinex(Random Memory Sprays Retinex)算法对输入的彩色图像进行白平衡处理
void RandomMemorySpraysRetinexPerformWhiteBalance(Mat source, Mat& destination, int N, int n, double upperBound, int rowsStep, int colsStep, double rFactor) {int rows = source.rows;int cols = source.cols;int R = rFactor * sqrt((double)(rows * rows + cols * cols)) + 0.5;Mat normalized;source.convertTo(normalized, CV_64FC3);int outputRows = rows / rowsStep;int outputCols = cols / colsStep;destination = Mat(outputRows, outputCols, CV_64FC3);Vec3d* input = (Vec3d*)normalized.data;Vec3d* inputPoint = input;Vec3d* output = (Vec3d*)destination.data;Vec3d* outputPoint = output;RNG random;CartesianTree<double>** qhs;qhs = new CartesianTree<double>*[N];for (int i = 0; i < N; ++i) {qhs[i] = new CartesianTree<double>[3];}for (int outputRow = 0; outputRow < outputRows; ++outputRow) {for (int outputCol = 0; outputCol < outputCols; ++outputCol) {int row = outputRow * rowsStep;int col = outputCol * colsStep;inputPoint = input + row * cols + col;outputPoint = output + outputRow * outputCols + outputCol;Vec3d& currentPoint = *inputPoint;Vec3d& finalPoint = *outputPoint;finalPoint = Vec3d(0, 0, 0);for (int i = 0; i < N; ++i) {Vec3d max = Vec3d(0, 0, 0);while (qhs[i][0].Size() < n) {double angle = 2 * CV_PI * random.uniform(0.0, 1.0);double r = R * random.uniform(0.0, 1.0);int newRow = row + r * sin(angle);int newCol = col + r * cos(angle);if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols) {Vec3d& newPoint = input[newRow * cols + newCol];for (int k = 0; k < 3; ++k) {qhs[i][k].Push(newPoint[k]);}}}for (int k = 0; k < 3; ++k) {if (max[k] < qhs[i][k].Max()) {max[k] = qhs[i][k].Max();}qhs[i][k].Pop();}for (int k = 0; k < 3; ++k) {if (max[k] == 0) {max[k] = 1;}finalPoint[k] += currentPoint[k] / max[k];}}finalPoint /= N;for (int i = 0; i < 3; ++i) {if (finalPoint[i] > 1) {finalPoint[i] = 1;}}}}for (int i = 0; i < N; ++i) {delete[] qhs[i];}delete[] qhs;double scaleFactor = upperBound;if (rowsStep > 1 || colsStep > 1) {resize(destination, destination, source.size());}destination = destination * scaleFactor - 1;destination.convertTo(destination, source.type());}

2.4、计算颜色校正因子(ComputeColorCorrectionFactor)

  颜色校正因子是基于当前像素亮度值和记忆喷雾的最大强度计算得出。其主要用于调整像素的颜色,以便在不同的光照条件下保持颜色的一致性。

//光照校正算法的实现
void ApplyIllumination(Mat source, Mat illumination, Mat& destination, double upperBound) {vector<Mat> destinationChannels;split(source, destinationChannels);vector<Mat> illuminationChannels;split(illumination, illuminationChannels);for (int i = 0; i < destinationChannels.size(); ++i) {destinationChannels[i].convertTo(destinationChannels[i], CV_64FC1);divide(destinationChannels[i], illuminationChannels[i], destinationChannels[i]);}merge(destinationChannels, destination);double* check = (double*)destination.data;for (int i = 0; i < destination.rows * destination.cols * 3; ++i) {if (check[i] >= upperBound) {check[i] = upperBound - 1;}}destination.convertTo(destination, source.type());}

2.5、应用强度重映射(ApplyIntensityRemapping)

  强度重映射主要用于改善图像亮度调整和颜色校正的方法,特别是在处理高光细节处,以防止过度增强造成细节的丢失。即,在增强图像暗区域的同时,保持亮区域的高光细节,从而获得更为自然的视觉效果。
① 计算初始及LRSR的亮度:
  对于每个像素,首先计算其初始亮度Yi,及LRSR算法处理后的亮度Yo。
② 确定重映射的参数:
  引入重映射参数,用于调整亮度的增加强度。
③ 计算调整后的亮度:
  调整后的亮度是初始亮度Yi和处理后亮度Yo的凸组会。即:Yr = λi * Yi + (1 - λi) * Yo
  其中,λi 是一个介于0和1之间的权重因子,主要基于初始亮度Yi和一个调整参数a来计算。
④ 计算权重因子:
  权重因子λi,即:λi = (Yi / D) / (Yi / D + a)。
  其中,D是颜色通道的最大值(对于8bit颜色通道,D通常是255)。λi的值越大,表示保留的初始亮度越多,处理后亮度的影响越小。
⑤ 过滤处理:
  为了避免亮度增加的剧烈变化,对λi施以一个滤波器(例如使用5*5的均值核)进行平滑处理,得到平滑后的权重因子λ’i。
⑥ 计算最终亮度:
  最终的亮度值,即:OpIci = λ’i * Yo + (1 - λ’i) * Ici。
  其中OpIci是最终的输出亮度,Ici是原始图像中的像素亮度通道强度。

//基于随机内存喷雾Retinex算法对输入的彩色图像进行局部光照估计
void LightRandomMemorySpraysRetinexEstimateLocalIlumination(Mat source, Mat& destination, int N, int n, int inputKernelSize, int illuminantKernelSize, bool normalizeIlluminant = false, int rowsStep = 1, int colsStep = 1, double upperBound = 256.0, double rFactor = 1.0) {Mat retinex;RandomMemorySpraysRetinexPerformWhiteBalance(source, retinex, N, n, upperBound, rowsStep, colsStep, rFactor);Mat inputSource;Mat inputRetinex;source.convertTo(inputSource, CV_64FC3);retinex.convertTo(inputRetinex, CV_64FC3);Mat guidance;inputSource.copyTo(guidance);if (normalizeIlluminant) {Mat illuminant;divide(inputSource, inputRetinex, illuminant);vector<Mat> illuminantChannels;split(illuminant, illuminantChannels);Mat illuminantAverage = (illuminantChannels[0] + illuminantChannels[1] + illuminantChannels[2]) / 3;for (int i = 0; i < 3; ++i) {divide(illuminantChannels[i], illuminantAverage, illuminantChannels[i]);}merge(illuminantChannels, illuminant);inputSource = inputRetinex.mul(illuminant);}if (inputKernelSize > 1) {Mat averaging = Mat::ones(inputKernelSize, inputKernelSize, CV_64FC1) / (double)(inputKernelSize * inputKernelSize);boxFilter(inputSource, inputSource, -1, Size(inputKernelSize, inputKernelSize));boxFilter(inputRetinex, inputRetinex, -1, Size(inputKernelSize, inputKernelSize));}Mat illuminant;divide(inputSource, inputRetinex, illuminant);vector<Mat> illuminantChannels;if (illuminantKernelSize > 1) {Mat averaging = Mat::ones(illuminantKernelSize, illuminantKernelSize, CV_64FC1) / (double)(illuminantKernelSize * illuminantKernelSize);boxFilter(illuminant, illuminant, -1, Size(illuminantKernelSize, illuminantKernelSize));}illuminant.copyTo(destination);}

2.6、应用引导滤波 (ApplyGuidedImageFiltering)

  使用引导滤波来处理重映射后的像素强度,以减少光晕效果并保留图像边缘。
其中,对图像进一步灰度化作为引导图像,进而采用引导滤波进行处理,最后输出目标图像。

//图像引导滤波
//对输入的图像img进行引导滤波,输出结果保存在result中。
void GuidedImageFilterC1(Mat img, Mat guidance, Mat& result, int r, double epsilon) {Mat p;img.convertTo(p, CV_64F);Mat I;guidance.convertTo(I, CV_64F);Mat meanI;boxFilter(I, meanI, -1, Size(r, r));Mat meanP;boxFilter(p, meanP, -1, Size(r, r));Mat corrI;boxFilter(I.mul(I), corrI, -1, Size(r, r));Mat corrIp;boxFilter(I.mul(p), corrIp, -1, Size(r, r));Mat varI = corrI - meanI.mul(meanI);Mat covIp = corrIp - meanI.mul(meanP);Mat a;divide(covIp, varI + epsilon, a);Mat b = meanP - a.mul(meanI);Mat meanA;boxFilter(a, meanA, -1, Size(r, r));Mat meanB;boxFilter(b, meanB, -1, Size(r, r));Mat q = meanA.mul(I) + meanB;q.convertTo(result, img.type());
}//基于引导图像的彩色图像滤波方法
//基于引导图像guidance对输入的彩色图像img进行引导滤波,输出结果保存在result中。
void GuidedImageFilterC3(Mat img, Mat guidance, Mat& result, int r, double epsilon) {vector<Mat> imgChannels;vector<Mat> guidanceChannels;split(img, imgChannels);split(guidance, guidanceChannels);vector<Mat> resultChannels;for (int i = 0; i < imgChannels.size(); ++i) {Mat channelResult;GuidedImageFilterC1(imgChannels[i], guidanceChannels[i], channelResult, r, epsilon);resultChannels.push_back(channelResult);}merge(resultChannels, result);}//基于引导图像和随机内存喷雾Retinex算法的彩色图像局部光照估计方法
void GuidedLightRandomMemorySpraysRetinexEstimateLocalIlumination(Mat source, Mat& destination, int N, int n, int inputKernelSize, int illuminantKernelSize, bool normalizeIlluminant = false, int rowsStep = 1, int colsStep = 1, double upperBound = 256.0, double rFactor = 1.0) {Mat retinex;//白平衡化处理RandomMemorySpraysRetinexPerformWhiteBalance(source, retinex, N, n, upperBound, rowsStep, colsStep, rFactor);Mat inputSource;Mat inputRetinex;source.convertTo(inputSource, CV_64FC3);retinex.convertTo(inputRetinex, CV_64FC3);Mat guidance;inputSource.copyTo(guidance);//归一化处理if (normalizeIlluminant) {Mat illuminant;divide(inputSource, inputRetinex, illuminant);vector<Mat> illuminantChannels;split(illuminant, illuminantChannels);Mat illuminantAverage = (illuminantChannels[0] + illuminantChannels[1] + illuminantChannels[2]) / 3;for (int i = 0; i < 3; ++i) {divide(illuminantChannels[i], illuminantAverage, illuminantChannels[i]);}merge(illuminantChannels, illuminant);inputSource = inputRetinex.mul(illuminant);}double value = 40;double epsilon = value * value;if (inputKernelSize > 1) {//平滑图像GuidedImageFilterC3(inputSource, guidance, inputSource, inputKernelSize, epsilon);GuidedImageFilterC3(inputRetinex, guidance, inputRetinex, inputKernelSize, epsilon);}Mat illuminant;divide(inputSource, inputRetinex, illuminant);vector<Mat> illuminantChannels;if (illuminantKernelSize > 1) {GuidedImageFilterC3(illuminant, guidance, illuminant, illuminantKernelSize, epsilon);}illuminant.copyTo(destination);}

3、Smart Light Random Memory Sprays Retinex效果

在这里插入图片描述

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

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

相关文章

Android下的匀速贝塞尔

画世界pro里的画笔功能很炫酷 其画笔配置可以调节流量&#xff0c;密度&#xff0c;色相&#xff0c;饱和度&#xff0c;亮度等。 他的大部分画笔应该是通过一个笔头图片在触摸轨迹上匀速绘制的原理。 这里提供一个匀速贝塞尔的kotlin实现&#xff1a; class EvenBezier {p…

Tensorflow2.0 - 链式法则例子

本笔记简单记录链式法则的原理&#xff0c;关于链式法则&#xff0c;本身和高等数学中的链式求导法则是一样的&#xff0c;深度学习中相关资料可以参考这里&#xff1a; 【深度学习之美22】BP算法详解之链式法则 - 知乎10.5 什么是计算图&#xff1f;我们知道&#xff0c; 神经…

uniapp微信小程序随机生成canvas-id报错?

uniapp微信小程序随机生成canvas-id报错&#xff1f; 文章目录 uniapp微信小程序随机生成canvas-id报错&#xff1f;效果图遇到问题解决 场景&#xff1a; 子组件&#xff0c;在 mounted 绘制 canvas&#xff1b;App、H5端正常显示&#xff0c;微信小程序报错&#xff1b; 效…

内网穿透的应用-如何使用Docker安装DockerUI可视化管理工具无公网IP远程访问

文章目录 前言1. 安装部署DockerUI2. 安装cpolar内网穿透3. 配置DockerUI公网访问地址4. 公网远程访问DockerUI5. 固定DockerUI公网地址 前言 DockerUI是一个docker容器镜像的可视化图形化管理工具。DockerUI可以用来轻松构建、管理和维护docker环境。它是完全开源且免费的。基…

华为配置终端定位基本实验配置

配置终端定位基本示例 组网图形 图1 配置终端定位基本服务示例 组网需求数据准备配置思路配置注意事项操作步骤配置文件 组网需求 如图1所示&#xff0c;某公司网络中&#xff0c;中心AP直接与RU连接。 管理员希望通过RU收集Wi-Fi终端信息&#xff0c;并提供给定位服务器进行定…

Flutter-仿淘宝京东录音识别图标效果

效果 需求 弹起键盘&#xff0c;录制按钮紧挨着输入框收起键盘&#xff0c;录制按钮回到初始位置 实现 第一步&#xff1a;监听键盘弹起并获取键盘高度第二步&#xff1a;根据键盘高度&#xff0c;录制按钮高度计算偏移高度&#xff0c;并动画移动第三步&#xff1a;键盘收起…

C语言 02 安装

C 语言的编译器有很多&#xff0c;其中最常用的是 GCC&#xff0c;这里以安装 GCC 为例。 Windows 这里以 Windows 11 为例 官方下载地址&#xff1a;https://www.mingw-w64.org/ 选择 Downloads 选择 Windows 的 GCC 环境 MingW-W64-builds 选择 GitHub 根据操作系统位…

Qt5.14.2 深入理解Qt多线程编程,掌握线程池架构实现高效并发

在高并发的软件系统中&#xff0c;多线程编程是解决性能瓶颈和提高系统吞吐量的有效手段。作为跨平台的应用程序开发框架&#xff0c;Qt为我们提供了强大的多线程支持。本文将深入探讨Qt多线程编程的实现细节&#xff0c;并介绍线程池的设计思想&#xff0c;帮助读者彻底掌握Qt…

网盘聚合工具:统筹管理所有网盘资源 | 开源日报 No.203

alist-org/alist Stars: 35.6k License: AGPL-3.0 alist 是一个支持多存储的文件列表/WebDAV 程序&#xff0c;使用 Gin 和 Solidjs。 该项目的主要功能、关键特性、核心优势包括&#xff1a; 支持多种存储方式易于部署和开箱即用文件预览&#xff08;PDF、markdown、代码等&…

SpringBoot2.7集成Swagger3

Swagger2已经在17年停止维护了&#xff0c;取而代之的是 Swagger3&#xff08;基于openApi3&#xff09;&#xff0c;所以新项目要尽量使用Swagger3. Open API OpenApi是业界真正的 api 文档标准&#xff0c;其是由 Swagger 来维护的&#xff0c;并被linux列为api标准&#x…

Web基础06-AJAX,Axios,JSON数据

目录 一、AJAX 1.概述 2.主要作用 3.快速入门 4.AJAX的优缺点 &#xff08;1&#xff09;优点 &#xff08;2&#xff09;缺点 5.同源策略 二、Axios 1.概述 2.快速入门 3.请求方式别名 三、JSON 1.概述 2.主要作用 3.基础语法 4.JSON数据转换 &#xff08;1…

Windows11安装Msql8.0版本详细安装步骤!

文章目录 前言一、下载Mysql二、安装Mysql三、登录验证三、环境变量配置总结 前言 每次搭建新环境的时候&#xff0c;都需要网上搜寻安装的步骤教程&#xff01;为了以后方便查阅&#xff01;那么本次就记录一下Windows11安装Msql8.0的详细步骤&#xff01;也希望能帮助到有需…

抖音无水印视频关键词批量下载|视频下载工具

抖音无水印视频关键词批量下载操作说明 我们根据自己的需要开发了抖音视频批量下载工具&#xff0c;现在市面上的视频无水印工具只能通过单个视频链接进行提取&#xff0c;太不方便 所以我们延伸出了 不仅可以通过单个视频链接进行提取也可通过关键词进行视频搜索 进行批量和有…

Python基于深度学习的中文情感分析系统,附源码

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

计算机设计大赛 题目:基于深度学习的中文汉字识别 - 深度学习 卷积神经网络 机器视觉 OCR

文章目录 0 简介1 数据集合2 网络构建3 模型训练4 模型性能评估5 文字预测6 最后 0 简介 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的中文汉字识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &a…

【AAAI 2024】MuLTI:高效视频与语言理解

一、背景 1.1 多模态的发展 多模态理解模型具有广泛的应用&#xff0c;比如多标签分类&#xff08;Classification&#xff09;、视频问答&#xff08;videoQA&#xff09;和文本视频检索&#xff08;Retrieval&#xff09;等。现有的方法已经在视频和语言理解方面取得了重大…

unity发布安卓获取读取权限

一、Player Settings 设置 Player Settings>Player>Other Settings> Android > Write Permission > External (SDCard). 二、代码 using System.Collections; using System.Collections.Generic; using System.IO; using UnityEngine; using UnityEngine.Andr…

【c++】内联-引用-重载

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;c_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.【c】内联函数 1.1 背景 1.2 内联函数的概念 1.3 内联函数的特性 1.4 宏和内联的小知识 宏的优缺点&#xff1f; C有哪些技术替代…

mac npm install 很慢或报错

npm ERR! code CERT_HAS_EXPIRED npm ERR! errno CERT_HAS_EXPIRED npm ERR! request to https://registry.npm.taobao.org/pnpm failed, reason: certificate has expired 1、取消ssl验证&#xff1a; npm config set strict-ssl false 修改后一般就可以了&#xff0c;…

kingbase 服务器配置(参数修改)

引言&#xff1a; 人大金仓作为国产数据库的佼佼者(单机)&#xff0c;也是每位数据库从业者必须数据库之一 配置文件 kingbase 参数配置 主要由 kingbase.conf 和 kingbase.auto.conf 设置 kingbase.conf 该参数文件为主配置文件&#xff0c;一般情况下&#xff0c;需要 重启…