首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >微光场景中捕获图像的ARKit色彩校正

微光场景中捕获图像的ARKit色彩校正
EN

Stack Overflow用户
提问于 2021-04-27 07:47:20
回答 1查看 239关注 0票数 1

我有一个ARKit应用程序,它做以下工作:

  • 将框架的捕获图像呈现为纹理。
  • 将此纹理应用于AR场景中的scenekit对象。

我用这个创建了一个虚拟对象,它完美地融入了AR场景。

我目前的方法非常适合光线充足的场景,但在黑暗场景中,虚拟物体上的纹理与当前场景背景有着微妙的不同。是什么原因造成的,有什么办法解决吗?

详细信息

我创建了演示项目的这个分支,它演示了这个问题。

该项目呈现一个面部模型,该模型使用框架的currentImage纹理。其结果应该是,即使人脸模型仍在呈现,它仍然有效地变得不可见。但是,在光线较低的情况下,您可以清楚地看到背景图像结束和人脸模型开始的位置。

以下是我用来捕捉纹理的着色器的概述

代码语言:javascript
复制
// Take in the current captured image. 
fragment float4 fragmentShader(TextureInOut in [[stage_in]],
                               texture2d<float, access::sample> capturedImageTextureY [[texture(0)]],
                               texture2d<float, access::sample> capturedImageTextureCbCr [[texture(1)]])
{
    
    // Sample from the captured image
    const float4 ycbcr = float4(capturedImageTextureY.sample(textureSampler, in.screenSpaceTexCoord).r,
                                capturedImageTextureCbCr.sample(textureSampler, in.screenSpaceTexCoord).rg, 1.0);
    
    
    // Convert to RGB
    const float3 color = (ycbcrToRGBTransform * ycbcr).rgb;
    
    // Gamma correction
    return float4(pow(color, float3(2.2)), 1);
}

此着色器获取框架的捕获图像并写出RGB纹理。我做了一些基本的伽马校正,这样得到的纹理看起来是正确的。

我将输出存储在金属纹理(.rgba8Unorm)中,然后有一个SceneKit对象,该对象将该纹理用于其弥漫性组件。

再一次,这一切都非常适合光线充足的场景。然而,在弱光场景中,捕捉到的纹理与背景图像明显不同。

下面的示例图像显示了这个问题。你可以看到一条清晰的线条(就在头发边缘附近),脸部模型结束,背景图像开始:

这在明亮的场景中是看不见的。

问题不是不对齐,在黑暗场景中,虚拟人脸纹理上的颜色看起来更饱和和/或噪音更小。

是什么导致了这一切,我该如何避免呢?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-04-29 13:04:41

您使用的是近似伽马校正,它不是RGB和sRGB之间的正确转换。您真正要做的是规避SceneKits默认像素格式(sRGB)。在片段着色器中,在您完成YCbCr到RGB转换之后,您有线性RGB,但是当您从片段着色器写入纹理时,来自着色器的值将被解释为sRGB,因此将发生RGB到sRGB的转换,即(实质上是pow 1/2.4,因此您为什么试图用近似的伽马校正来更正它),您需要做相反的事情来避免这一点,就好像您要从sRGB转换到线性。RGB-sRGB转换(反之亦然)可能令人困惑,因为有时在引擎盖下发生的事情您可能不知道。所以解决的方法是,而不是你的伽马校正,做这个:

代码语言:javascript
复制
float3 color2;
color2.x = ( color.r > 0.04045 ) ? pow((color.r + 0.055) / 1.055, 2.4) : color.r / 12.92;
color2.y = ( color.g > 0.04045 ) ? pow((color.g + 0.055) / 1.055, 2.4) : color.g / 12.92;
color2.z = ( color.b > 0.04045 ) ? pow((color.b + 0.055) / 1.055, 2.4) : color.b / 12.92;

return float4(color2, 1.0);

有关这方面的更多信息,请查看当前“金属阴影语言指南”(v2.3)的最后一页。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67278934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档