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

2024-03-19 09:36

本文主要是介绍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效果

在这里插入图片描述

这篇关于Smart Light Random Memory Sprays Retinex 传统图像增强 SLRMSR的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/825538

相关文章

2024/9/8 c++ smart

1.通过自己编写的class来实现unique_ptr指针的功能 #include <iostream> using namespace std; template<class T> class unique_ptr { public:         //无参构造函数         unique_ptr();         //有参构造函数         unique_ptr(

深入探讨生成对抗网络(GANs):颠覆传统的AI创作方式

在人工智能的快速发展中,生成对抗网络(Generative Adversarial Networks, GANs)无疑是一个引人注目的技术。自2014年由Ian Goodfellow等人首次提出以来,GANs已经在图像生成、文本生成、视频生成等多个领域展现出了惊人的能力。本文将详细解析GANs的原理、结构以及应用场景,帮助读者全面理解这一颠覆性的技术。 一、GANs的基本原理 生成对抗网络(G

Numpy random.random()函数补充

np.random.random() np.random.random()的作用是生成指定形状的均匀分布的值为[0,1)的随机数 参数为size,也就是用于指定的形状大小 import numpy as npprint(np.random.random(size=(2, 2)))# [[0.19671797 0.85492315]# [0.99609539 0.66437246]]

Midjourney 随机风格 (Style Random),开启奇幻视觉之旅

作者:老余捞鱼 原创不易,转载请标明出处及原作者。 写在前面的话:       Midjourney 最近推出了 "Style Random"(随机风格),这项功能可以让我们使用独特的随机 sref 代码创建图像,从而每次都能获得不同的美感。通过对这些功能的探索和尝试,我发现了一些很棒的风格,我很高兴能与大家分享,这样可以节省大家的时间,不用自己动手测试。在本文中,我将展示十个M

Learning Memory-guided Normality for Anomaly Detection——学习记忆引导的常态异常检测

又是一篇在自编码器框架中研究使用记忆模块的论文,可以看做19年的iccv的论文的衍生,在我的博客中对19年iccv这篇论文也做了简单介绍。韩国人写的,应该是吧,这名字听起来就像。 摘要abstract 我们解决异常检测的问题,即检测视频序列中的异常事件。基于卷积神经网络的异常检测方法通常利用代理任务(如重建输入视频帧)来学习描述正常情况的模型,而在训练时看不到异常样本,并在测试时使用重建误

关于No resource found that matches the given name 'Theme.AppCompat.Light' No resource found that ma

关于No resource found that matches the given name  'Theme.AppCompat.Light' No resource found that matches the given name   'android:Widget.Material.ActionButton.CloseMode'. 我的上一遍文章 http://blog.csdn.net

【论文分享】GPU Memory Exploitation for Fun and Profit 24‘USENIX

目录 AbstractIntroductionResponsible disclosure BackgroundGPU BasicsGPU architectureGPU virtual memory management GPU Programming and ExecutionGPU programming modelGPU kernelDevice function NVIDIA

飞利浦的精益转型之路:从传统制造到智能制造的华丽蜕变

飞利浦作为一家拥有百年历史的全球知名品牌,其在精益转型方面的经验值得我们深入研究和借鉴。本文将从飞利浦的转型背景、转型过程、转型成效以及给我们的启示等方面,探讨飞利浦如何成功实现精益转型,从而在新的市场竞争中脱颖而出。 一、转型背景 随着科技的飞速发展和市场竞争的日益激烈,传统制造业面临着巨大的挑战。飞利浦作为一家以家电和医疗设备为主的制造企业,同样面临着产品同质化、成本上升、利润下滑等问

【HDU】 4067 Random Maze 费用流

Random Maze Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1114    Accepted Submission(s): 387 Problem Description In the game “A C

模拟实现string类及体验传统深拷贝

目录 strcpy 构造函数 优化 拷贝构造/深拷贝 operator= size/operator[] operator<<  c_str() 模拟string::iterator 插入 push_back() append() operator+= reserve npos strcpy strcpy是将'/0'拷贝完成后才会停止。 构造函数