图像伽马校正_自适应伽马矫正matlab

图像伽马校正_自适应伽马矫正matlabGamma矫正颜色空间(具体内容在之前的文章有讲)sRGB

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

百人计划学习视频连接:【技术美术百人计划】图形 2.6 伽马校正


颜色空间

具体内容在之前的文章有讲:色彩空间介绍

  • sRGB:微软在1996年发布的通用颜色标准
  • DCI-P3:数字电影播放的颜色标准
  • Rec-709、PAL:电视行业的颜色标准
    在这里插入图片描述
    图中可以看出sRGB和Rec-709表示的颜色范围很接近,三原色的位置也是相同的

    那他们的区别在哪里呢?

    答案是 他们的传递函数的不同

什么是传递函数

当我们已经知道了颜色空间下三原色的值,但是我们需要将它显示到电子设备上,那就需要把它转换成一个视频信号。
这里就需要用到一个转换函数,也叫传递函数
在这里插入图片描述
一个传递函数包含2个部分:

  • OEFT 把光转换为电子信号(例如:拍摄视频的时候,将场景中的光保存成信号)
  • EOFT 把电子信号转换成光信号(例如:播放视频的时候,将视频中的信号转换成光强度)

而传递函数就是Gamma校正所使用的一个函数

Gamma校正

什么是Gamma校正?
就是指对线性三色值和非线性视频信号之间进行编码和解码的操作

也可以简单的定义为:在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
那为什么不直接用线性方式存储颜色信号呢?

首先我们知道了图像的来龙去脉:自然界捕获的图像 -> 图像存储和处理->显示器输出

而两头的颜色数量都是非常丰富的,但是中间的存储和处理出于存储容量和渲染时带宽的限制,24位色图片每个通道只有28个色阶,总共只能显示224种颜色。

如过是32位通道的图片,确实可以直接存储物理光强,因为存储空间足够;但是目前主流使用还是8位通道的图片

因此,我们得出结论

  • 主要是为了优化存储空间和带宽,传递函数能更好的帮我们利用编码空间
  • 人眼对暗部的变化更加敏感,为了充分的利用带宽,那么就需要使用更多位置存储暗部值。也就是说暗部使用更高精度保存,而亮部使用更低精度保存

韦伯定律

在这里插入图片描述
正常人会觉得是上面更均匀,但是实际下面才是均匀变化的。

将自然界线性增长的亮度和心理上感受到的亮度进行一个映射得到下面的曲线,就是Gamma编码的曲线
在这里插入图片描述
这种情况也符合一个定律,就是韦伯定律
在这里插入图片描述

小结

  1. 人眼对暗部的变化比亮部更加敏感
  2. 我们目前所使用的RGBA32,每个颜色通道只有8位用于记录信息,为了合理使用带宽和存储空间,需要进行非线性转换
  3. 目前我们所普遍使用的sRGB颜色空间标准,他的传递函数gamma值为2.2

CRT

早期的人们是如何修正人眼的视觉感受和物理亮度的差异
在这里插入图片描述
CRT与转换函数
在这里插入图片描述

中灰值

中灰值是什么?
在这里插入图片描述
在这里插入图片描述
中灰值并非是一个固定的具体数值,而是取决于视觉感受

线性工作流

在这里插入图片描述
为了保证我们在着色器中拿到的颜色值是线性空间下的颜色值

如果不在线性空间下进行渲染工作,会产生什么问题
在这里插入图片描述
在这里插入图片描述

Unity中的颜色空间

在这里插入图片描述

  • 选择Gamma Space时,Unity不会做任何处理
  • 当选择Linear Space时,引擎的渲染流程在线性空间计算,理想情况下项目使用线性空间的贴图颜色,不需要勾选sRGB,如果勾选了sRGB的贴图,会通过硬件特性采样时进行线性转换。

在这里插入图片描述
Unity目前主要通过以下两个硬件特性来支持
在这里插入图片描述

资源导出问题

在这里插入图片描述

当Substance的贴图导出时,线性的颜色值经过伽马变换,颜色被提亮了,所以需要在Unity中勾选sRGB选项,让它在采样时能还原回线性值。
在这里插入图片描述
如果使用线性空间,一般来说Photoshop可以什么都不改,导出的贴图只要勾上sRGB就可以了。如果调整PhotoShop的伽玛值为1,导出的贴图在Unity中也不需要勾选sRGB了。

关于Color profile

在这里插入图片描述

半透明效果不一致在这里插入图片描述

Unity中的混合是线性混合,Photoshop的图层和图层之间做混合的时候,每个上层图层都经过了伽马变换,然后才做了混合。在设置中更改,选择“用灰度系数混合RGB颜色”,参数设置为1,这样图层才是直接混合的结果。

作业

手动尝试几种伽马校正的方法

1. 直接修改Unity3d的设置为Linear空间进行gamma校正

写了一个简单的带纹理的blin-phong模型

fixed4 frag (v2f i) : SV_Target
{ 
   

	fixed3 MainTex = tex2D(_MainTex, i.uv) * _DiffuseColor.rgb;
	float3 normalDir = normalize(i.worldNormal);
	float3 lightDir = normalize(UnityWorldSpaceLightDir(_WorldSpaceLightPos0.xyz)) ;
	float3 Diffuse =  _LightColor0.rgb * MainTex.rgb *  saturate(dot(lightDir, normalDir));
	float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
    float3 halfDir = normalize(lightDir + viewDir);
	float3 Specular = _LightColor0.rgb * pow(saturate(dot(halfDir, normalDir)), _Gloss);

	float3 Ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * MainTex.rgb;
	float4 col = fixed4(Diffuse + Specular, 1);
	return col;
}

Gamma空间:
在这里插入图片描述

Linear空间:
在这里插入图片描述

2. 在shader中手动进行gamma校正

fixed4 frag (v2f i) : SV_Target
{ 
   

		fixed3 MainTex = tex2D(_MainTex, i.uv) * _DiffuseColor.rgb;//先将Gamma空间的颜色值进行一次转换,转换到Linear空间。
		MainTex.rgb = GammaToLinearSpace(MainTex.rgb);
		float3 normalDir = normalize(i.worldNormal);
		float3 lightDir = normalize(UnityWorldSpaceLightDir(_WorldSpaceLightPos0.xyz)) ;
		float3 Diffuse =  _LightColor0.rgb * MainTex.rgb *  saturate(dot(lightDir, normalDir));
		float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos.xyz);
       	float3 halfDir = normalize(lightDir + viewDir);
		float3 Specular = _LightColor0.rgb * pow(saturate(dot(halfDir, normalDir)), _Gloss);

		float3 Ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * MainTex.rgb;
		float4 col = fixed4(Diffuse + Specular, 1);
		//输出的时候,再进行一次逆转换,从Linear空间转换回Gamma空间。
		col.rgb = LinearToGammaSpace(col.rgb * unity_ColorSpaceDouble);
		return col;
}

注:最后转换回Gamma Space的时候,我在Color上乘了一个Unity_ColorSpaceDouble。Unity_ColorSpaceDouble是一个Unity提供的与色彩空间相关的值,这个值在Gamma颜色空间时为2,在Linear Color Space时为4.594(2的2.2次方)。
对于这个值可以这样来理解。一般在Gamma颜色空间中将两个Color值相乘后,为了避免颜色变得很暗,会在后面乘以2。
也就是说,为了避免颜色变暗,应该扩大两倍,但是这个值在不同空间下不一样,所以要使用Unity_ColorSpaceDouble。

原效果:
在这里插入图片描述
加上gamma校正后的效果
在这里插入图片描述


参考学习:
《Unity+Shader入门精要》——冯乐乐著
https://blog.csdn.net/candycat1992/article/details/46228771

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/189830.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • sublime text3 2021激活码【在线注册码/序列号/破解码】

    sublime text3 2021激活码【在线注册码/序列号/破解码】,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • WerFault.exe 占用CPU 100%的问题处理[通俗易懂]

    WerFault.exe 占用CPU 100%的问题处理[通俗易懂]转载自:https://technet.microsoft.com/en-us/library/cc754364(v=ws.11).aspx关于禁用WerFault.exe进程的操作方法,网络上的其它设置都不生效,通过官方给出的操作,完美的禁用了此进程,适用于win2008。AppliesTo:WindowsServer2008R2WindowsErrorRe…

  • OpenCV 人脸识别LBPH算法分析

    OpenCV 人脸识别LBPH算法分析一、背景及理论基础人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻的功能。从OpenCV2.4开始,加入了新的类FaceRecognizer,该类用于人脸识别,使用它可以方便地进行相关识别实验。原始的LBP算子定义为在3*3的窗口内,以窗口中心像素为阈值,将相邻的8…

  • matlab分段函数的表达_MATLAB|分段函数的构造方法

    matlab分段函数的表达_MATLAB|分段函数的构造方法1.问题描述以如下的典型分段函数为例:2.技术背景MATLAB。3.解决方案以上的分段函数分别由两个函数构成:f1(x)=0.5*x,当x<100;f2(x)=-0.5*x+100,当x>=100;故整体的分段函数可以表示为:f(x)=f1(x)(当x<100)+f2(x)(当x>=100)如此,可以用一个统一的表达式表达,方便…

  • idea2022最新激活码 csdn【中文破解版】

    (idea2022最新激活码 csdn)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.cn/100143.htmlLGWSVFD4PZ-eyJsaWNlbnNlSW…

  • 单例模式 java 三种写法_单例模式基本类图

    单例模式 java 三种写法_单例模式基本类图本文为joshua317原创文章,转载请注明:转载自joshua317博客Java单例模式推荐写法-双重检测机制实现单例模式-joshua317的博客Java单例模式推荐写法–双重检测机制实现单例双重检测机制不仅可以既线程安全问题,又解决懒加载问题,同时保证了效率。packagecom.joshua317.pattern;/***推荐使用:双重检测机制实现单例模式*既解决线程安全问题,又解决懒加载问题,同时保证了效率。*/publicclassSinglet.

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号