2011-05-12 6 views
1

クロマチャンネルの幅および/または高さを半分にすると、サブアンブルにする正しい方法は何ですか? 2x2ルーマピクセルごとに1つのクロマピクセルを取得するには、フル解像度のクロマソースからサンプリングするとき、どのクロマピクセルを使用するか - 左上?すべての平均4?関係ない?PythonのYUVサブサンプリングクロマチャンネル

これは、YUV 4へ変換する正しい方法私の現在のコード

if field == 'top': 
    i = 0 
elif field == 'bottom': 
    i = 1 

U = fromstring(Udata, dtype='uint8', count=w/2*h).reshape(h,w/2) 

# halve chroma height (it's already half-width from UYVY source) by line skipping 
U = U[i::2] 

# scale chroma by a factor of 0.5 (2x2 pixels in -> 1 pixel out) 
U = (U[0::2, 0::2]>>2) + (U[0::2, 1::2]>>2) + (U[1::2, 0::2]>>2) + (U[1::2, 1::2]>>2) + \ 
    (((U[0::2, 0::2]%4) + (U[0::2, 1::2]%4) + (U[1::2, 0::2]%4) + (U[1::2, 1::2]%4)) >> 2) 
+2

すべてのコードを選択し、 '{}'ボタンを押してインデントします。 –

+0

これは数ヶ月後にもう一度見つけました。キーボードショートカットは 'Ctrl + k'です – wim

答えて

3

Idealy you woul dはデータを補間して最良の画像を生成しますが、あなたの質問はlumaとchromのサンプルがどこにあるかを簡単に概観することで最もよく答えられます。サブサンプリングには、輝度サンプルに再現する彩度の位置を選択するための複数の基準があります。 Cromaでoftain最も

は、「左上」輝度画素と同一位置のいずれか

XO X XO X 

X X X X 

XO X XO X 

X X X X 

であるか、または正方形の中心に位置し、

X X X X 
    O  O 
X X X X 

X X X X 
    O  O 
X X X X 

又は上に配置されています2つの左の輝度サンプルの間の正方形の左側。

X X X X 
O  O 
X X X X 

X X X X 
O  O 
X X X X 

全ての場合において、クロマ値は、少なくとも一部の輝度サンプルは、いくつかのクロマ値の組み合わせであろうと同じ場所に配置することを通知、これは一般的に別のフィルタをするためにお奨めされている理由FIRフィルタを用いて行われます(あなたは平均化でOKの結果を得ることができます)

1

:2:YUV 0~4:2 2 6タップFIRフィルタを使用することです。

/* vertical 1:2 interpolation filter */ 
static void conv420to422(unsigned char* src, unsigned char* dst) 
{ 
    int w, h, i, j, j2; 
    int jm6, jm5, jm4, jm3, jm2, jm1, jp1, jp2, jp3, jp4, jp5, jp6, jp7; 

    w = 352>>1; 
    h = 288>>1; 

    printf("hello \n"); 

    if (1) 
    { 
    /* intra frame */ 
    for (i=0; i<w; i++) 
    { 
     for (j=0; j<h; j++) 
     { 
    //printf("%d,%d\n", i, j); 
     j2 = j<<1; 
     jm3 = (j<3) ? 0 : j-3; 
     jm2 = (j<2) ? 0 : j-2; 
     jm1 = (j<1) ? 0 : j-1; 
     jp1 = (j<h-1) ? j+1 : h-1; 
     jp2 = (j<h-2) ? j+2 : h-1; 
     jp3 = (j<h-3) ? j+3 : h-1; 

     /* FIR filter coefficients (*256): 5 -21 70 228 -37 11 */ 
     /* New FIR filter coefficients (*256): 3 -16 67 227 -32 7 */ 
     dst[w*j2] =  Clip[(int)( 3*src[w*jm3] 
          -16*src[w*jm2] 
          +67*src[w*jm1] 
          +227*src[w*j] 
          -32*src[w*jp1] 
          +7*src[w*jp2]+128)>>8]; 

     dst[w*(j2+1)] = Clip[(int)( 3*src[w*jp3] 
          -16*src[w*jp2] 
          +67*src[w*jp1] 
          +227*src[w*j] 
          -32*src[w*jm1] 
          +7*src[w*jm2]+128)>>8]; 
     } 
     src++; 
     dst++; 
    } 
    } 
    else 
    { 
    /* intra field */ 
    for (i=0; i<w; i++) 
    { 
     for (j=0; j<h; j+=2) 
     { 
     j2 = j<<1; 

     /* top field */ 
     jm6 = (j<6) ? 0 : j-6; 
     jm4 = (j<4) ? 0 : j-4; 
     jm2 = (j<2) ? 0 : j-2; 
     jp2 = (j<h-2) ? j+2 : h-2; 
     jp4 = (j<h-4) ? j+4 : h-2; 
     jp6 = (j<h-6) ? j+6 : h-2; 

     /* Polyphase FIR filter coefficients (*256): 2 -10 35 242 -18 5 */ 
     /* New polyphase FIR filter coefficients (*256): 1 -7 30 248 -21 5 */ 
     dst[w*j2] = Clip[(int)( 1*src[w*jm6] 
         -7*src[w*jm4] 
         +30*src[w*jm2] 
         +248*src[w*j] 
         -21*src[w*jp2] 
          +5*src[w*jp4]+128)>>8]; 

     /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */ 
     /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */ 
     dst[w*(j2+2)] = Clip[(int)(7*src[w*jm4] 
          -35*src[w*jm2] 
          +194*src[w*j] 
          +110*src[w*jp2] 
          -24*src[w*jp4] 
           +4*src[w*jp6]+128)>>8]; 

     /* bottom field */ 
     jm5 = (j<5) ? 1 : j-5; 
     jm3 = (j<3) ? 1 : j-3; 
     jm1 = (j<1) ? 1 : j-1; 
     jp1 = (j<h-1) ? j+1 : h-1; 
     jp3 = (j<h-3) ? j+3 : h-1; 
     jp5 = (j<h-5) ? j+5 : h-1; 
     jp7 = (j<h-7) ? j+7 : h-1; 

     /* Polyphase FIR filter coefficients (*256): 11 -38 192 113 -30 8 */ 
     /* New polyphase FIR filter coefficients (*256):7 -35 194 110 -24 4 */ 
     dst[w*(j2+1)] = Clip[(int)(7*src[w*jp5] 
          -35*src[w*jp3] 
          +194*src[w*jp1] 
          +110*src[w*jm1] 
          -24*src[w*jm3] 
           +4*src[w*jm5]+128)>>8]; 

     dst[w*(j2+3)] = Clip[(int)( 1*src[w*jp7] 
          -7*src[w*jp5] 
          +30*src[w*jp3] 
          +248*src[w*jp1] 
          -21*src[w*jm1] 
           +5*src[w*jm3]+128)>>8]; 
     } 
     src++; 
     dst++; 
    } 
    } 
} 

と中:あなたは "mpegv12.zip" ファイルCで

実装のためにここにhttp://www.mpeg.org/MPEG/video/mssg-free-mpeg-software.html

ゴーを見つけることができ、このためのsrcはMPEG2のリファレンス実装から来

Python:

def conv420to422(src, dst): 
    """420 to 422 - vertical 1:2 interpolation filter """ 

    width = 352     # 352 
    height = 288     # 288 
    w = width >> 1    # 176 
    h = height >> 1    # 144 

    n = 0 
    k = 0 
    for i in range(0, w): 
     for j in range(0, h): 
      j2 = j<<1 
      jm3 = 0 if (j < 3) else j - 3 
      jm2 = 0 if (j < 2) else j - 2 
      jm1 = 0 if (j < 1) else j - 1 
      jp1 = j + 1 if (j < h - 1) else h - 1 
      jp2 = j + 2 if (j < h - 2) else h - 1 
      jp3 = j + 3 if (j < h - 3) else h - 1 

      a = (3*src[n+w*jm3]-16*src[n+w*jm2]+67*src[n+w*jm1]+227*src[n+w*j]-32*src[n+w*jp1]+7*src[n+w*jp2]+128)>>8 
      dst[k+w*j2] = clip(a) 
      b = (3*src[n+w*jp3]-16*src[n+w*jp2]+67*src[n+w*jp1]+227*src[n+w*j]-32*src[n+w*jm1]+7*src[n+w*jm2]+128)>>8 
      dst[k+w*(j2+1)] = clip(b) 
     n += 1 
     k += 1 
    return dst 
+0

ありがとうございましたが、補間ではなくサブサンプリングについて質問していました。つまり、444から420 – wim

関連する問題