YUV420sp形式の画像のサイズを変更(縮小)しようとしています。 YUV420spピクセル配列を直接操作するので、RGBに変換することなくイメージのサイズ変更を行うことは可能ですか?どこでそのようなアルゴリズムを見つけることができますか?YUV420sp画像のサイズ変更(縮小)
おかげ
YUV420sp形式の画像のサイズを変更(縮小)しようとしています。 YUV420spピクセル配列を直接操作するので、RGBに変換することなくイメージのサイズ変更を行うことは可能ですか?どこでそのようなアルゴリズムを見つけることができますか?YUV420sp画像のサイズ変更(縮小)
おかげ
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:
これは、各彩度 - ピクセル値が4つのルミナンスピクセルで共有されることを意味します。
1つの方法は、対応するY-Cb-Cr関係が保持/再計算されていることを確認することです。
何かがNearest-neighbor interpolationに近いものの、逆のものです。 4:4:0サブサンプリング:2:
別のアプローチは、最初の4を変換することである4ここ
あなたは、輝度と色度データとの間の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を再度指定すると、それはどれくらい厳格にする必要があるかによって異なります。
ここでは、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;
}
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
4:4:4に戻って4:2:0に戻る必要はありません。その最後のステップは、画像を再サブサンプリングし、さらに品質を低下させる。 colourplanesを分割するだけです: http://stackoverflow.com/questions/17187193/resize-downsize-yuv420sp-image/30659193#30659193 –