低光场景下捕获图像的 ARKit 颜色校正

ARKit color correction of captured image in low light scenes

我有一个 ARKit 应用可以执行以下操作:

我用它来创建一个完美融入 AR 场景的虚拟对象。

我目前的方法适用于光线充足的场景,但在黑暗场景中,虚拟对象的纹理与当前场景背景略有不同。是什么原因造成的,有什么办法可以解决吗?

详情

我创建了 this branch on a demo project 来演示这个问题。

该项目渲染了一个面部模型,该模型使用框架的 currentImage 进行了纹理处理。结果应该是面部模型实际上变得不可见,即使它仍在渲染中。但是在光线较暗的情况下,您可以清楚地看到背景图像结束和面部模型开始的位置。

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

// 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);
}

此着色器获取帧的 captured image 并写出 RGB 纹理。我做了一些基本的伽马校正,使生成的纹理看起来正确。

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

同样,这一切都适用于光线充足的场景。然而,在低光场景中,捕获的纹理与背景图像明显不同。

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

这在光线充足的场景中是看不到的。

问题不是错位,在黑暗场景中,虚拟面部纹理上的颜色看起来更饱和 and/or 噪点更少。

可能是什么原因造成的,我该如何避免?

您使用的是近似伽马校正,不是 RGB 和 sRGB 之间的正确转换。您真正想做的是规避 SceneKits 默认像素格式 (sRGB)。在进行 YCbCr 到 RGB 转换后的片段着色器中,您拥有线性 RGB,但是当您从片段着色器写入纹理时,来自着色器的该值将被解释为 sRGB,因此将发生 RGB 到 sRGB 的转换,即(本质上pow 1/2.4,因此你为什么要尝试用近似伽马校正来校正它),你需要做相反的事情来规避这个问题,就好像你要从 sRGB 到线性。 RGB-sRGB 转换(反之亦然)可能会令人困惑,因为有时您可能没有意识到在引擎盖下发生的事情。所以修复是,而不是你的伽马校正这样做:

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);

有关这方面的更多信息,请查看当前 Metal 着色语言指南 (v 2.3) 的最后一页。