天天看點

OpenGL ES:YUV轉RGB

色彩的二次抽樣

在RGB顔色模式下,每個像素點由Red、Green、Blue三種顔色組合而成,YUV使用色彩通道UV和亮度通道Y,這種格式更适合圖像處理領域,圖檔的所有細節儲存在亮度通道中,如果沒有亮度,圖檔就是一張灰階圖檔,人的眼睛對亮度的敏感度要高于顔色,是以可以通過減少每個像素點的顔色值,達到效果比較好的壓縮,這個減少顔色資料的過程就是色彩的二次抽樣

YUV轉RGB繪制紋理

紋理映射隻能在RGBA方式下執行,攝像頭采集YUV,需要把YUV轉換成RGBA

  • 擷取到視訊幀的YUV資料
  • CoreVideo進行分離Y分量和UV分量
  • Fragment Shader對Y分量和UV分量進行采樣
  • Fragment Shader轉換YUV到RGB
  • 進行渲染

看一下BT.601的RGB到YUV的轉換算法

R' = 1.164*(Y’-16) + 1.596*(Cr'-128)

G' = 1.164*(Y’-16) - 0.392*(Cb'-128) - 0.813*(Cr'-128) 

B' = 1.164*(Y’-16) + 2.017*(Cb'-128)

// 其中括号裡面的是做伽馬矯正用的
           

是以我們的轉換矩陣可以這樣寫

mat3( 1.164,     1.164,     1.164,
          0.0,    -0.392,     2.017,
        1.596,    -0.813,       0.0,)
           

Fragment Shader中的轉換下面這樣寫

varying highp vec2 texCoordVarying;
precision mediump float;

uniform sampler2D SamplerY;
uniform sampler2D SamplerUV;
uniform mat3 colorConversionMatrix;

void main() {
    mediump vec3 yuv;
    lowp vec3 rgb;
    yuv.x = (texture2D(SamplerY, texCoordVarying).r);// - (16.0/255.0));
    yuv.yz = (texture2D(SamplerUV, texCoordVarying).ra - vec2(0.5, 0.5));
    
    rgb = colorConversionMatrix * yuv;
    gl_FragColor = vec4(rgb, 1);
}
           

繼續閱讀