G-channel 实现低光图像增强

G-channel

之前研究低光图像增强时,看到一篇博客,里面介绍了一种方法,没有说明出处,也没有说明方法的名字,这里暂时叫做 G-channel 算法。

博客地址:低照度图像增强(附步骤及源码)_低照度图像增强算法_grafx的博客-CSDN博客

算法过程

博客里面简单说明了算法的执行过程,这里重复如下:

  1. 将绿色通道反色后作为系数值,分别与各个通道相乘,得到新图层;
  2. 将新图层与原图做一次滤色混合,f(a,b)=1-(1-a)*(1-b);

为了了解算法原理,经过查找,找到了几篇博客:

  • 基于photoshop滤色混合模式的图片亮度改变_悍然的博客-CSDN博客
  • 正片叠底(Multiply)和滤色(Screen)是两种基本的混合模式_滤色和正片叠底_e财富800的博客-CSDN博客
  • Photoshop图层混合模式的计算公式_pizi0475的博客-CSDN博客

从这几篇博客里,可以将算法过程归纳为Photoshop的2个处理步骤:

  1. Multiply正片叠底:C=(A×B)/255,A为基色,B为混合色,会使得图像C整体亮度更暗
  2. Screen滤色:C=255-(A反相×B反相)/255,与上面相反,会使得图像C整体亮度更亮

算法实现

博客中给出了opencv的实现代码,下面使用matlab进行了仿真,代码如下所示:

close all;clear;clc;
src = imread('8.bmp');
im = double(src);
r = im(:,:,1);
g = im(:,:,2);
b = im(:,:,3);
g_alpha = 255 - g;
r1 = r .* g_alpha / 255;
g1 = g .* g_alpha / 255;
b1 = b .* g_alpha / 255;
r = 255 - (255 - r) .* (255 - r1) / 255;
g = 255 - (255 - g) .* (255 - g1) / 255;
b = 255 - (255 - b) .* (255 - b1) / 255;
dst = cat(3, r, g, b);
dst = uint8(round(dst));
imshow([src, dst])

由于找不到博客里测试图像的原图,这里换了另外一张测试图像,结果如下,这里执行2次算法,可以看到结果与博客里面的结果还是很相似的,说明仿真没有问题。
在这里插入图片描述

为了方便分析,这里对代码做了调整(原始代码,数据范围为[0,255],调整后的代码,数据范围归一化到[0,1]),如下所示,与原始结果是一致:

close all;clear;clc;
src = imread('8.bmp');
im = double(src)/255;
r = im(:,:,1);
g = im(:,:,2);
b = im(:,:,3);
g_alpha = 1 - g;
r1 = r .* g_alpha;
g1 = g .* g_alpha;
b1 = b .* g_alpha;
r = 1 - (1 - r) .* (1 - r1);
g = 1 - (1 - g) .* (1 - g1);
b = 1 - (1 - b) .* (1 - b1);
dst = cat(3, r, g, b);
dst = uint8(round(dst*255));
imshow([src, dst])

原理分析

下面就个人理解来对算法原理做个简单的分析。

步骤一:Multiply正片叠底

正片叠底公式为:C=(A×B)/255,数据范围都为[0,255],这里全部都归一化到[0,1],则公式变为:C=A×B。

任何一个数乘以一个小于1的数以后,都会变小,即C<A(C=A×B),因而图像整体会变暗。

这步里面的B为G通道取反,以G通道进行说明,处理后为:g1=g×(1-g)。原始图像中本来很亮的像素值gh,取反之后变为1-gh,变得很小,处理后会乘以一个很小的小数,使得很亮的像素值gh降低的很多;而原本很暗的像素值gl,取反之后1-gl,变得很大,处理后会乘以一个很大的小数,使得很暗的像素值gl降低的很少。最终的处理结果是图像中亮的像素变很暗,而暗的像素稍微变暗,因而图像会整体变暗

我们换一个方式来看,公式是一个二次函数,开口朝下,对称轴为0.5,超过0.5部分,单调递减,即原始亮度越亮,处理后亮度越暗,如下所示为其函数关系图:
在这里插入图片描述
下面是算法实际仿真结果,如下所示:

close all;clear;clc;
src = imread('8.bmp');
im = double(src)/255;
r = im(:,:,1);
g = im(:,:,2);
b = im(:,:,3);
g_alpha = 1 - g;
r1 = r .* g_alpha;
g1 = g .* g_alpha;
b1 = b .* g_alpha;
dst = cat(3, r1, g1, b1);
dst = uint8(round(dst*255));
imshow([src, dst])

在这里插入图片描述
可以看到,图像整体亮度变暗,且图中白色的杯盘变得很暗,与上面的分析很吻合。

步骤二:Screen滤色

同样,归一化到[0,1]后,Screen滤色公式为:C=1-(1-A)×(1-B)。如果用来做图像增强,则需要A和B有很强的相关性;如果是为了实现某种效果,则B跟这种效果密切相关(比如让某个区域更亮)。为了简化说明,这里让B=A,同样以G通道进行说明:g2=1-(1-g)×(1-g),这里先单独看Screen滤色。从第一步的分析可知,(1-g)可以使图像中亮的像素值降低的更多,然后取反,这样会使得图像中亮的像素增加的更多,暗的像素值增加的很少,图像整体亮度提升。

我们再来看看g2这个函数,它是一个二次函数,开口朝下,对称轴为1,[0,1]单调递增,如下所示:

在这里插入图片描述

close all;clear;clc;
src = imread('8.bmp');
im = double(src)/255;
r = im(:,:,1);
g = im(:,:,2);
b = im(:,:,3);
g_alpha = 1 - g;
r2 = 1 - (1- r) .* g_alpha;
g2 = 1 - (1- g) .* g_alpha;
b2 = 1 - (1- b) .* g_alpha;
dst = cat(3, r2, g2, b2);
dst = uint8(round(dst*255));
figure, imshow([src, dst])

在这里插入图片描述

可以看到,图像整体亮度变亮,且图中白色的杯盘变得更亮,与上面的分析很吻合。

这样就会出现一个问题,图像中原本比较亮的像素值处理后会更亮,容易出现饱和,为了避免出现这种问题,就需要结合步骤一里面的Multiply正片叠底,先对亮的像素值进行抑制再来提升亮度,从而可以减小出现饱和的风险

下面我们结合步骤一Multiply正片叠底一起看,对G通道,g3=1-(1-g)×(1-g1)=1-(1-g)×(1-g×(1-g)),它是一个3次函数,如下所示:
在这里插入图片描述
可以看到,最终的曲线g3,相比于Screen滤色g2,在亮的像素增强上进行了抑制。其最终增强效果如文章开头所示。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vue+element中如何设置单个el-date-picker开始时间和结束时间关联

功能&#xff1a;选了开始时间&#xff0c;则结束时间只能选择开始时间之后的&#xff1b;选了结束时间&#xff0c;则开始时间只能选择结束时间之前的 重点是picker-options属性 图示&#xff1a; 代码展示: // body 内部<el-form-item><el-date-pickerv-model&qu…

AI抠图使用指南:Stable Diffusion WebUI Rembg实用技巧

抠图是图像处理工具的一项必备能力&#xff0c;可以用在重绘、重组、更换背景等场景。最近我一直在探索 Stable Diffusion WebUI 的各项能力&#xff0c;那么 SD WebUI 的抠图能力表现如何呢&#xff1f;这篇文章就给大家分享一下。 安装插件 作为一个生成式AI&#xff0c;SD…

一文学透设计模式——抽象工厂模式

创建者模式 抽象工厂模式 概念 抽象工厂模式是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。 这是很多地方对于抽象工厂模式的描述&#xff0c;说实话感觉不是特别好懂。…

架构训练营学习笔记:5-2 负载均衡架构

多级负载架构 设计关键点 性能需求、维护复杂度之间做取舍。 一可以去掉F5、LVS &#xff1a; F5 是成本较高&#xff0c;LVS 是复杂&#xff0c;对于性能没那么高需求&#xff0c;可以去掉。 二 去掉ng: 服务网关服务 适应于初创公司快速验证&#xff0c;内部的 小系统…

Typescript+React入门

初识Typescript 出现背景 Typescript&#xff08;以下简称TS&#xff09;实际上就是JavaScriptType&#xff0c;用数据类型的方式来约束了JS的变量定义 在JS的基础上增加了类型支持 在JS中大多数错误都是因为数据类型造成的&#xff0c;所以TS为了规避这个问题加入了类型限制…

C语言案例 按序输出三个整数-02

题目&#xff1a;输入三个整数a,b,c,按从小到大的顺序输出 步骤一&#xff1a;定义程序的目标 编写一个C程序&#xff0c;随机输入三个整数&#xff0c;按照从小到大的顺序输出。 步骤二&#xff1a;程序设计 整个程序由三个模块组成&#xff0c;第一个为scanf输入函数模块&a…

OA会议管理系统之会议通知(送审成功可查看人员是否参与会议)

一、前言 1.导读 在上一次的博文中我们实现了会议审批&#xff0c;会议通过审批后&#xff0c;状态就会由原来的待审核变为待开&#xff0c;这时候我们就可以在我的会议下的反馈详情查看人员是否参与会议的反馈情况。这篇博客就是来了解&#xff0c;人员是怎么接收会议通知并反…

MyBatis 查询数据库之二(增、删、改、查操作)

目录 1. 配置打印 MyBatis 执行的SQL 2. 查询操作 2.1 通过用户 ID 查询用户信息、查询所有用户信息 (1) Mapper 接口 (2)UserMapper.xml 查询所有用户的具体实现 SQL (3)进行单元测试 3. 增加操作 3.1 在 mapper&#xff08;interface&#xff09;里面添加增加方法的声…

unity如何手动更改脚本执行顺序

在Unity中&#xff0c;脚本的执行顺序是由脚本的执行顺序属性决定的。默认情况下&#xff0c;Unity根据脚本在项目中的加载顺序来确定它们的执行顺序。然而&#xff0c;你可以手动更改脚本的执行顺序&#xff0c;以下是一种方法&#xff1a; 在Unity编辑器中&#xff0c;选择你…

剑指Offer05.替换空格

剑指Offer05.替换空格 目录 剑指Offer05.替换空格题目描述解法一&#xff1a;遍历添加解法二&#xff1a;原地修改 题目描述 请实现一个函数&#xff0c;把字符串s中的每个空格都替换成“%20”。 解法一&#xff1a;遍历添加 由于每次替换都要把一个空格字符变成三个字符&a…

【LeetCode】516. 最长回文子序列

文章目录 1. 思路讲解1.1 创建dp表1.2 状态转移方程1.3 不需考虑边界问题 2. 整体代码 1. 思路讲解 1.1 创建dp表 此题采用动态规划的方法&#xff0c;创建一个二维dp表&#xff0c;dp[i][j]表示s[i, j]中最大回文子序列的长度。且我们人为规定 i 是一定小于等于 j 的。 1.2…

OpenAI 已为 GPT-5 申请商标,GPT-4 发布不到半年,GPT-5 就要来了吗?

据美国专利商标局&#xff08;USPTO&#xff09;信息显示&#xff0c;OpenAI已经在7月18日申请注册了“GPT-5”商标。 在这份新商标申请中&#xff0c;OpenAI将“GPT-5”描述为一种“用于使用语言模型的可下载计算机软件”。 继GPT-4发布之后&#xff0c;它预计将成为OpenAI下一…

vue响应数据为二维码如何渲染到页面

在postman测试请求后发现响应数据为一个二维码图片,不是链接,如何解决? 然后如果在vue中使用请求还会报Uncaught (in promise) SyntaxError: Unexpected token o in JSON at position 1的错误。这个就是使用了JSON.parse导致的响应格式不对)&#xff0c;使用JSON.stringify解决…

骑砍二 ATC MOD 使用教程与应用案例解析

骑砍二 ATC MOD 使用教程与应用案例解析 作者&#xff1a;blibli-财不外漏 / NEXUSMODS-PuepleKarmen 案例MOD依赖&#xff1a;ATC - Adonnay’s Troop Changer & AEW - Adonnay’s Exotic Weaponry & New Armor 文本编辑工具&#xff1a;VS Code&#xff08;推荐使用&…

Typescript - 索引签名

目录 1&#xff0c;什么是索引签名1&#xff0c;js 中使用对象的属性2&#xff0c;ts 中的索引签名3&#xff0c;扩展索引签名定义的类型 2&#xff0c;与 Record 对比3&#xff0c;遇到的问题1&#xff0c;索引 key 的类型问题&#xff0c;keyof2&#xff0c;索引 key 的类型问…

Zebec APP:构建全面、广泛的流支付应用体系

目前&#xff0c;流支付协议 Zebec Protocol 基本明确了生态的整体轮廓&#xff0c;它包括由其社区推动的模块化 Layer3 构架的公链 Nautilus Chain、流支付应用 Zebec APP 以及 流支付薪酬工具 Zebec payroll 。其中&#xff0c;Zebec APP 是原有 Zebec Protocol 的主要部分&a…

无向图-已知根节点求高度

深搜板子题&#xff0c;无向图&#xff0c;加边加两个&#xff0c;dfs输入两个参数变量&#xff0c;一个是当前深搜节点&#xff0c;另一个是父节点&#xff08;避免重复搜索父节点&#xff09;&#xff0c;恢复现场 ///首先完成数组模拟邻接表#include<iostream> #incl…

re学习(27)攻防世界toddler_regs(字符串函数总结+交叉引用)

找不到main&#xff08;&#xff09;函数&#xff0c;查找字符串&#xff0c;发现特殊字符串 定位字符串出现的位置&#xff0c;反汇编出代码&#xff0c;进行分析“ flag{Xp0int_1s_n1c3_but_Xp0intJNU_is_we1rd} 总结 一.CP&#xff1a;shiftF12 展示所有的字符串; ctrlx查…

python高阶技巧

目录 设计模式 单例模式 具体用法 工厂模式 优点 闭包 案例 修改闭包外部变量 闭包优缺点 装饰器 装饰器原理 装饰器写法 递归 递归的调用过程 递归的优缺点 用递归计算阶乘 设计模式 含义&#xff1a;设计模式是一种编程套路&#xff0c;通过这种编程套路可…

Linux-centos花生壳实现内网穿透

Linux-centos花生壳实现内网穿透 官网教程 1.安装花生壳 下载网址 点击复制就可以复制下载命令了 wget "https://dl.oray.com/hsk/linux/phddns_5.2.0_amd64.rpm" -O phddns_5.2.0_amd64.rpm# 下载完成之后会多一个rpm文件 [rootlocalhost HuaSheng]# ls phddns_…