图像伽马校正_自适应伽马矫正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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于阿里DDNS的ipv6 for windows版软件

    基于阿里DDNS的ipv6 for windows版软件基于阿里DDNS的ipv6forwindows版软件会搜到这篇帖子的同学,应该和我一样,满世界为自己的虚拟主机找寻ipv6的动态ddns程序吧?下面我先说说我的折腾故事:因为买了群晖,然后发现需要公网ip,但公网ip现在电信要钱了,开口100元一个月,挺黑的。没办法尝试了各种内网穿透,这类帖子网上很多,就不细说了,总之是各种折腾,各种不爽,最终选择了零遁伴侣做内网穿透还算稳定,速度也不错。…

    2022年6月13日
    40
  • hashmap数组什么时候扩容_hashmap是数组还是链表

    hashmap数组什么时候扩容_hashmap是数组还是链表为什么需要扩容?因为HashMap为了节省创建出的对象的内存占用,一开始只默认分配:staticfinalintDEFAULT_INITIAL_CAPACITY=1<<4;也就是默认的数组大小是16个,而在HashMap的源码中可以发现HashMap扩容方法如下,就是说当HashMap里存储元素的个数大于threshold(capacity*loadFactor时,会进行扩容,…

    2025年12月11日
    1
  • 爬虫爬取妹子图片(入门篇)

    爬虫爬取妹子图片(入门篇)

    2021年11月11日
    51
  • 关系数据理论-数据库习题

    关系数据理论-数据库习题设有关系W(工号,姓名,工种,定额),将其规范化到第三范式正确的答案是()。A.W1(工号,姓名),W2(工种,定额)B.W1(工号,工种,定额),W2(工号,姓名)C.W1(工号,姓名,工种),w2(工种,定额)D.以上都不对正确答案:C3NF要求没有部分依赖和传递依赖,“定额”直接依赖“工种”,传递依赖“工号”。规范化的实质是概念的单一化,“一事一地”,一个关系只描述一个概念。规范化理论是关系数据库进行逻辑设计的理论依据。根据这个理论,关系数据库中的关系必须满

    2022年10月16日
    2
  • JWT单点登录(源码学习)

    JWT单点登录(源码学习)三、JWT源码学习//登录成功之后,需要生成tokenStringtoken=Jwts.builder().setSubject(“用户名/用户信息”)//主题,可以放用户的详细信息.setIssuedAt(newDate())//token创建时间.setExpiration(newDate(System.currentTimeMillis()+60000))//token过期时间.setId(“用户ID”)//用户ID

    2022年5月21日
    37
  • 第七讲:HTML5中的canvas两个小球全然弹性碰撞

    第七讲:HTML5中的canvas两个小球全然弹性碰撞

    2021年11月29日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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