2013-06-19 52 views
7

YUV420sp形式の画像のサイズを変更(縮小)しようとしています。 YUV420spピクセル配列を直接操作するので、RGBに変換することなくイメージのサイズ変更を行うことは可能ですか?どこでそのようなアルゴリズムを見つけることができますか?YUV420sp画像のサイズ変更(縮小)

おかげ

答えて

13

YUV 4:2:0の平面は、次のようになります。

---------------------- 
|  Y  | Cb|Cr | 
---------------------- 

場所:

Y = width x height pixels 
Cb = Y/4 pixels 
Cr = Y/4 pixels 

Total num pixels (bytes) = width * height * 3/2 

そして、このように使用subsamling:

420

これは、各彩度 - ピクセル値が4つのルミナンスピクセルで共有されることを意味します。

1つの方法は、対応するY-Cb-Cr関係が保持/再計算されていることを確認することです。

何かがNearest-neighbor interpolationに近いものの、逆のものです。 4:4:0サブサンプリング:2:

別のアプローチは、最初の4を変換することである4ここ

444

あなたは、輝度と色度データとの間の1対1のマッピングを持っています。

これは、4:2:0と4:2:2の間でクロマを補間する正しい方法です(ルーマはすでに正しい解像度になっています)。 c-ditoのhtml-linkに従ってください。 コードは非常にpythonicではなく、Cバージョンの直接の翻訳です。

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

    Bit-exact with 
    http://www.mpeg.org/MPEG/video/mssg-free-mpeg-software.html 
    """ 
    w = self.width >> 1 
    h = self.height >> 1 

    for i in xrange(w): 
     for j in xrange(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 

      pel = (3*src[i+w*jm3] 
       -16*src[i+w*jm2] 
       +67*src[i+w*jm1] 
       +227*src[i+w*j] 
       -32*src[i+w*jp1] 
        +7*src[i+w*jp2]+128)>>8 

      dst[i+w*j2] = pel if pel > 0 else 0 
      dst[i+w*j2] = pel if pel < 255 else 255 

      pel = (3*src[i+w*jp3] 
       -16*src[i+w*jp2] 
       +67*src[i+w*jp1] 
       +227*src[i+w*j] 
       -32*src[i+w*jm1] 
       +7*src[i+w*jm2]+128)>>8 

      dst[i+w*(j2+1)] = pel if pel > 0 else 0 
      dst[i+w*(j2+1)] = pel if pel < 255 else 255 
    return dst 

これを2回実行して4:4:4にします。 次に、行と列を削除するだけです。

4:2:0から4:4:4へのクロマピクセルを4倍にし、行と列を削除して平均4Cb/Cr値を1にして4:2: 0を再度指定すると、それはどれくらい厳格にする必要があるかによって異なります。

+0

4:4:4に戻って4:2:0に戻る必要はありません。その最後のステップは、画像を再サブサンプリングし、さらに品質を低下させる。 colourplanesを分割するだけです: http://stackoverflow.com/questions/17187193/resize-downsize-yuv420sp-image/30659193#30659193 –

7

ここでは、YUV 420(またはNV21)を2倍にスケールダウンするJava関数を示します。

この関数は、元の画像の幅と高さとともに画像をバイト配列で取り込み、元の幅と高さの両方の半分に等しい幅と高さを持つバイト配列で画像を返します。私はこれを使用自分のコードのための基礎として

Rotate an YUV byte array on Android

public static byte[] halveYUV420(byte[] data, int imageWidth, int imageHeight) { 
    byte[] yuv = new byte[imageWidth/2 * imageHeight/2 * 3/2]; 
    // halve yuma 
    int i = 0; 
    for (int y = 0; y < imageHeight; y+=2) { 
     for (int x = 0; x < imageWidth; x+=2) { 
      yuv[i] = data[y * imageWidth + x]; 
      i++; 
     } 
    } 
    // halve U and V color components 
    for (int y = 0; y < imageHeight/2; y+=2) { 
     for (int x = 0; x < imageWidth; x += 4) { 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + x]; 
      i++; 
      yuv[i] = data[(imageWidth * imageHeight) + (y * imageWidth) + (x + 1)]; 
      i++; 
     } 
    } 
    return yuv; 
} 
1

YUV420sp一面と他にU & VにYを有しています。 U & Vを別々のプレーンに分割すると、最初に4:2:0→4:4:4から移動することなく、3つのプレーンのそれぞれに対して同じスケーリング操作を順番に実行できます。

libyuvのソースコードを見てください。 https://code.google.com/p/libyuv/source/browse/trunk/source/scale.cc

関連する問題