代码之家  ›  专栏  ›  技术社区  ›  Soonts

将颜色从RGB转换为NV12

  •  1
  • Soonts  · 技术社区  · 7 年前

    crashes on Windows 7 通过VRAM中的RGB输入,说“0x8876086C D3DERR\u INVALIDCALL”,所以我实现了我自己的RGB->在GPU上进行NV12转换,节省超过60%的PCI express带宽。

    以下是我的媒体类型,包括输入(NV12)和输出(h264):

    mt->SetUINT32( MF_MT_VIDEO_CHROMA_SITING, MFVideoChromaSubsampling_MPEG2 ); // Specifies the chroma encoding scheme for MPEG-2 video. Chroma samples are aligned horizontally with the luma samples, but are not aligned vertically. The U and V planes are aligned vertically.
    mt->SetUINT32( MF_MT_YUV_MATRIX, MFVideoTransferMatrix_BT709 ); // ITU-R BT.709 transfer matrix.
    mt->SetUINT32( MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255 ); // The normalized range [0...1] maps to [0...255] for 8-bit samples or [0...1023] for 10-bit samples.
    mt->SetUINT32( MF_MT_TRANSFER_FUNCTION, MFVideoTransFunc_10 );  // Linear RGB (gamma = 1.0).
    

    到目前为止,我用这个公式得到的最好结果是:

    inline float3 yuvFromRgb(float3 rgba)
    {
        float3 res;
        res.x = dot( rgba, float3( 0.182585880, 0.614230573, 0.0620070584 ) );
        res.y = dot( rgba, float3( -0.121760942, -0.409611613, 0.531372547 ) );
        res.z = dot( rgba, float3( 0.531372547, -0.482648790, -0.0487237722 ) );
        res += float3( 0.0627451017, 0.500000000, 0.500000000 );
        return saturate( res );
    }
    

    让我担心的是,这个公式与我在互联网上读到的所有内容、代码示例和ITU官方规范相矛盾。

    规格说明我必须缩放U和V以从[0..255]映射到[16..240]。然而,我的眼睛告诉我它是不饱和的。为了获得正确的颜色,我必须缩放U&另一方面,从[0..255]变成类似[-8255+8]。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Soonts    7 年前

    问题是色度采样伪影。当我问这个问题时,我正在看彩色的控制台文本。

    今天我试着编码更好的图像,这个: enter image description here 有了这个图像,很明显正确的公式就是这些标准中规定的。

    下面是正确的系数:

    // Convert RGB color into ITU-R BT.709 YUV color
    inline float3 yuvFromRgb( float3 rgb )
    {
        float3 res;
        res.x = dot( rgb, float3( 0.18258588, 0.61423057, 0.06200706 ) );
        res.y = dot( rgb, float3( -0.10064373, -0.33857197, 0.43921569 ) );
        res.z = dot( rgb, float3( 0.43921569, -0.39894217, -0.04027352 ) );
        res += float3( 0.06274510, 0.50196081, 0.50196081 );
        return res;
    }
    

    他们仍然给我一个错误,但对于我的特殊问题,0.39%的错误是可以接受的。