2017-11-14 55 views
6

enter image description here
  저는 HLSL을 처음 사용했습니다. DXGI Desktop Duplication API를 사용하여 BGRA에서 YUV444로 캡처 한 이미지의 색상 공간을 렌더링 대상으로 텍스처를 사용하여 변환하려고합니다.
  필요한 변형을 수행하기 위해 픽셀 쉐이더를 설정했습니다. 그리고 4 : 2 : 0 서브 샘플링 된 YUV를 렌더링 대상 텍스처에서 가져와 ffmpeg를 사용하여 H264로 인코딩하면 이미지를 볼 수 있습니다.
  문제는 - greenish입니다.
  쉐이더의 입력 색상 정보는 float 데이터 유형이지만 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하기. 인코더는 인코딩 된 패킷을 비디오 파일에 기록합니다.
  여기에서 픽셀의 각 2X2 행렬에 대해 U (Cb)와 V (Cr) 및 4Y 값을 취합니다.
 는 I 텍스처에서 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 : 45 200 (170) 및 값 : CPU 계산 때 YUV 값 :

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 : 블렌드 상태 DESC 추가 부동 소수점 계산이 포함 된 픽셀 쉐이더 이후 : 86 141 104. 해당 RGB : 48 45 45. 차이를 만들 수있는 것은 무엇입니까?

+0

또한 동일한 문제가 발생합니다. –

+0

V가 아닌 0.5의 오프셋이있는 이유는 무엇입니까?비대칭 인 것 같습니다 – 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)에서 볼 수 있습니다. 그래서 ** RGBA **를 얻으려면 다음과 같은 변환을해야합니다 :'float4 color = float4 (rgba.b, rgba.g, rgba.r, rgba.a); '. – Shaman