2017-11-14 11 views
6

enter image description here
  HLSLを初めて使用しています。 DXGI Desktop Duplication APIを使用してキャプチャした画像の色空間をBGRAからYUV444にレンダリングターゲットとしてテクスチャを使用して変換しようとしています。
 ピクセルシェーダで必要な変換を実行するように設定しました。そして、4:2:0サブサンプリングされたYUVをターゲットテクスチャからレンダリングし、ffmpegを使用してH264としてエンコードすると、イメージが表示されます。
 問題は - greenishです。
 シェーダの入力カラー情報は浮動小数点データ型ですが、RGBからYUVへの変換に使用できる係数行列は整数の色情報を前提としています。
 クランプ機能を使用して整数を入力色から取り除くと、精度が失われます。
 ご意見やご指摘をお待ちしております。他の情報が役立つかどうかお知らせください。
 私は最初にそれを使って作業しているように、私が書いたピクセルシェーダーを疑う。ここにピクセルシェーダがあります。DirectX11ピクセルシェーダを使用したBGRAからYUV444への緑色のイメージ

float3 rgb_to_yuv(float3 RGB) 
{ 
    float y = dot(RGB, float3(0.29900f, -0.16874f, 0.50000f)); 
    float u = dot(RGB, float3(0.58700f, -0.33126f, -0.41869f)); 
    float v = dot(RGB, float3(0.11400f, 0.50000f, -0.08131f)); 
    return float3(y, u, v); 
} 
float4 PS(PS_INPUT input) : SV_Target 
{ 
    float4 rgba, yuva; 
    rgba = tx.Sample(samLinear, input.Tex); 
    float3 ctr = float3(0, 0, .5f); 
    return float4(rgb_to_yuv(rgba.rgb) + ctr, rgba.a); 
} 

 ターゲットはCPUで読み取り可能なテクスチャにマッピングされ、3つのバイト配列にYUV444データをコピーし、エンコーダlibx264 ffmpegのために供給されるレンダリング。 エンコーダは、エンコードされたパケットをビデオファイルに書き込みます。
 ここでは、ピクセルの2×2行列ごとに1つのU(Cb)と1つのV(Cr)と4つのY値を取っています。
 私はテクスチャからYUV420データを取得する:

for (size_t h = 0, uvH = 0; h < desc.Height; ++h) 
{ 
    for (size_t w = 0, uvW = 0; w < desc.Width; ++w) 
    { 
     dist = resource1.RowPitch *h + w * 4; 
     distance = resource.RowPitch *h + w * 4; 
     distance2 = inframe->linesize[0] * h + w; 
     data = sptr[distance + 2 ]; 
     pY[distance2] = data; 
     if (w % 2 == 0 && h % 2 == 0) 
     { 
      data1 = sptr[distance + 1]; 
      distance2 = inframe->linesize[1] * uvH + uvW++; 
      pU[distance2] = data1; 
      data1 = sptr[distance ]; 
      pV[distance2] = data1; 
     } 
    } 
    if (h % 2) 
     uvH++; 
} 

EDIT1:ブレンド状態DESCを追加する:

D3D11_BLEND_DESC BlendStateDesc; 
    BlendStateDesc.AlphaToCoverageEnable = FALSE; 
    BlendStateDesc.IndependentBlendEnable = FALSE; 
    BlendStateDesc.RenderTarget[0].BlendEnable = TRUE; 
    BlendStateDesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 
    BlendStateDesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 
    BlendStateDesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 
    BlendStateDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; 
    BlendStateDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; 
    BlendStateDesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 
    BlendStateDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 
    hr = m_Device->CreateBlendState(&BlendStateDesc, &m_BlendState); 
FLOAT blendFactor[4] = {0.f, 0.f, 0.f, 0.f}; 
    m_DeviceContext->OMSetBlendState(nullptr, blendFactor, 0xffffffff); 
    m_DeviceContext->OMSetRenderTargets(1, &m_RTV, nullptr); 
    m_DeviceContext->VSSetShader(m_VertexShader, nullptr, 0); 
    m_DeviceContext->PSSetShader(m_PixelShader, nullptr, 0); 
    m_DeviceContext->PSSetShaderResources(0, 1, &ShaderResource); 
    m_DeviceContext->PSSetSamplers(0, 1, &m_SamplerLinear); 
    m_DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 

EDIT2:CPUで計算YUVの値:45 200 170および値浮動小数点計算を伴うピクセルシェーダーの後:86 141 104. 対応するRGB:48 45 45。違いを生むものは何ですか?

+0

同じ問題に直面しています –

+0

なぜVのオフセットは0.5ですが、Uはありませんか?それは非対称だと思われる – harold

+0

@harold、(0、0.5、0.5)で試してみましたが問題は同じです。緑の効果が他の色効果に変わりました。 –

答えて

1

あなたの行列が転置されているようです。 [6.4] ITU.BT-601 Y'CbCr下www.martinreddy.net/gfx/faqs/colorconv.faq:によると

Y'= 0.299*R' + 0.587*G' + 0.114*B' 
Cb=-0.169*R' - 0.331*G' + 0.500*B' 
Cr= 0.500*R' - 0.419*G' - 0.081*B' 

はあなたにはnumpy.dotの行動を誤解しましたあなたがコピーしたソース。 > YUV444(BT.601)あなたはこの機能を使用する必要があります -

また、それは@haroldが正しいことのように、あなたはRGB を変換するには、このWikipedia articleに基づいて、UおよびV

0

の両方を相殺する必要があります見えます:

float3 RGBtoYUV(float3 c) 
{ 
     float3 yuv; 
     yuv.x = dot(c, float3(0.299, 0.587, 0.114)); 
     yuv.y = dot(c, float3(-0.14713, -0.28886, 0.436)); 
     yuv.z = dot(c, float3(0.615, -0.51499, -0.10001)); 
     return yuv; 
} 

また、シェーダーに読み込むテクスチャの形式は何ですか? float4 rgba, yuva;を使用していることを考慮して、BGRA - > RGBAを先に変換しましたか?

+0

私は(r、 g、b)hlslカラーセマンティクス(rgba.r、rgba.g、rgba.b)を使ったタプル。 BGRA→RGBA変換は必要ありません –

+0

テクスチャ形式が** BGRA **の場合、 'rgba.r'は** R **チャンネルを返しません。** B **チャンネルを返します。これについて[ここ](https://msdn.microsoft.com/en-us/library/windows/desktop/bb509634(v = vs.85).aspx)を読むことができます。だから、** BGRA **テクスチャから** RGBA **を得るためには、次の変換をしなければなりません: 'float4 color = float4(rgba.b、rgba.g、rgba.r、rgba.a); '。 – Shaman

関連する問題