2017-11-14 86 views
6

enter image description here
  HLSL konusunda yeni. BGRA'dan DXGI Masaüstü Çoğaltma API'sini kullanarak yakalanan bir görüntünün renk uzayını doku hedef olarak doku kullanarak YUV444'e dönüştürmeye çalışıyorum.
  Gerekli dönüşümü gerçekleştirmek için piksel gölgelendiricimi ayarladı. Ve 4: 2: 0 alt örneklemeli YUV, hedef doku oluşturup ffmpeg kullanarak H264 olarak kodlayarak, görüntüyü görebilirim.
  Sorun şu ki: greenish.
  Gölgelendirici için giriş rengi bilgileri, float veri türündedir, ancak RGB'den YUV'ye dönüştürme için kullanılabilen katsayı matrisi, tamsayı renk bilgisi alır.
  Kıskaç işlevini kullanır ve tamsayıları giriş renginden çıkarırsam, doğruluğunu kaybediyorum.
  Her türlü öneri ve yol tarifi kabul edilir. Başka bilgi yardımcı olursa lütfen bana bildirin.
  Yazdığım Pixel shader'dan şüpheleniyorum, İlk defa çalışıyorum. İşte piksel gölgelendiricisi. Oluşturma hedefiDirectX11 piksel gölgelendiriciyi kullanarak YRAV444 dönüştürme için BGRA ile yeşilimsi görüntü

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

  işlemci tarafından okunabilir bir doku eşlenir ve 3 bayt dizileri içine YUV444 verileri kopyalama ve tedarik kodlayıcı libx264 ffmpeg için. Kodlayıcı, kodlanmış paketleri bir video dosyasına yazar.
  Burada her bir 2X2 piksel matrisini bir U (Cb) ve bir V (Cr) ve 4 Y değeri için alıyorum.
  I dokudan YUV420 veri almak edilmiştir:

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: 45 200 170 ve değerler: CPU hesaplandığında YUV değerini:

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: Karışım durum azalan ekleme kayan nokta hesaplamaları içeren piksel gölgelendiriciden sonra: 86 141 104. İlgili RGB: 48 45 45. Fark yaratan ne olabilir?

+0

da aynı sorunla karşı karşıyayım –

+0

Neden V için 0,5 olan bir offset var, ama U?Bu asimetrik – harold

+0

@ harold, Denenmiş (0, 0,5, 0,5) gibi görünüyor ama sorun aynı kalıyor. Yeşilimsi etki başka bir renk etkisine dönüştü. –

cevap

1

Matrisinizin aktarıldığı anlaşılıyor. [6.4] ITU.BT-601 Y'CbCr altında www.martinreddy.net/gfx/faqs/colorconv.faq: göre

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' 

You numpy.dot davranışını yanlış kopyaladığınız kaynak. > YUV444 (BT.601) Eğer bu fonksiyonu kullanmalısınız -

Ayrıca, @harold doğru olduğu gibi, RGB dönüştürmek için, bu Wikipedia article dayanarak U ve V

0

hem mahsup edilmelidir görünüyor :

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

Ayrıca, gölgelendiricinize yüklediğiniz dokunun biçimi nedir? float4 rgba, yuva;'u kullandığınız düşünülürse, önce BGRA -> RGBA dönüştürdünüz mü?

+0

'dan bahsettiğim ek bilgilere bir göz atın. g, b) hlsl renk semantiklerini kullanarak tuple (rgba.r, rgba.g, rgba.b). BGRA -> RGBA dönüşümü gerekli değil –

+0

Doku formatınız ** BGRA ** ise, 'rgba.r' ** R ** kanalını döndürmez, ** B ** kanalı döndürür. Bu konuda okuyabilirsiniz [https://msdn.microsoft.com/en-us/library/windows/desktop/bb509634 (v = vs.85) .aspx). Yani ** RGBA ** sizden ** BGRA ** doku elde etmek için aşağıdaki dönüşümü yapmanız gerekir: float4 color = float4 (rgba.b, rgba.g, rgba.r, rgba.a); '. – Shaman

İlgili konular