31

私はいくつかのグーグル検索を行ってきましたが、この形式に関する十分な情報を見つけることができませんでした. これは、カメラ プレビューの既定の形式です。それに関する良い情報源と、その形式で写真/プレビュー画像からデータを抽出する方法を誰かが提案できますか? 具体的には、白黒画像を抽出する必要があります。

編集:そのフォーマットはYCbCr 420 Semi Planarとも呼ばれているようです

4

6 に答える 6

83

NV21 を RGB に変換する次のコードを開発しましたが、動作しています。

/**
 * Converts YUV420 NV21 to RGB8888
 * 
 * @param data byte array on YUV420 NV21 format.
 * @param width pixels width
 * @param height pixels height
 * @return a RGB8888 pixels int array. Where each int is a pixels ARGB. 
 */
public static int[] convertYUV420_NV21toRGB8888(byte [] data, int width, int height) {
    int size = width*height;
    int offset = size;
    int[] pixels = new int[size];
    int u, v, y1, y2, y3, y4;

    // i percorre os Y and the final pixels
    // k percorre os pixles U e V
    for(int i=0, k=0; i < size; i+=2, k+=2) {
        y1 = data[i  ]&0xff;
        y2 = data[i+1]&0xff;
        y3 = data[width+i  ]&0xff;
        y4 = data[width+i+1]&0xff;

        u = data[offset+k  ]&0xff;
        v = data[offset+k+1]&0xff;
        u = u-128;
        v = v-128;

        pixels[i  ] = convertYUVtoRGB(y1, u, v);
        pixels[i+1] = convertYUVtoRGB(y2, u, v);
        pixels[width+i  ] = convertYUVtoRGB(y3, u, v);
        pixels[width+i+1] = convertYUVtoRGB(y4, u, v);

        if (i!=0 && (i+2)%width==0)
            i+=width;
    }

    return pixels;
}

private static int convertYUVtoRGB(int y, int u, int v) {
    int r,g,b;

    r = y + (int)(1.402f*v);
    g = y - (int)(0.344f*u +0.714f*v);
    b = y + (int)(1.772f*u);
    r = r>255? 255 : r<0 ? 0 : r;
    g = g>255? 255 : g<0 ? 0 : g;
    b = b>255? 255 : b<0 ? 0 : b;
    return 0xff000000 | (b<<16) | (g<<8) | r;
}

このイメージは理解に役立ちます。 YUV420 NV21

グレースケール画像だけを使いたい場合は簡単です。U 情報と V 情報をすべて破棄して、Y 情報だけを取得できます。コードは次のようになります。

/**
 * Converts YUV420 NV21 to Y888 (RGB8888). The grayscale image still holds 3 bytes on the pixel.
 * 
 * @param pixels output array with the converted array o grayscale pixels
 * @param data byte array on YUV420 NV21 format.
 * @param width pixels width
 * @param height pixels height
 */
public static void applyGrayScale(int [] pixels, byte [] data, int width, int height) {
    int p;
    int size = width*height;
    for(int i = 0; i < size; i++) {
        p = data[i] & 0xFF;
        pixels[i] = 0xff000000 | p<<16 | p<<8 | p;
    }
}

ビットマップを作成するには:

Bitmap bm = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);

ピクセルは int [] 配列です。

于 2012-10-03T06:18:17.900 に答える
12

NV21 は基本的に YUV420 ですが、Y、U、V が独立したプレーンを持つ平面フォーマットの代わりに、NV21 には輝度用の 1 つのプレーンとクロマ用の 2 番目のプレーンがあります。フォーマットは次のようになります

YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY . . . .

VUVUVUVUVUVUVUVUVUVUVUVUVUVUVU VUVUVUVUVUVUVUVUVUVUVUVUVUVUVU . . . . .

于 2012-06-20T18:53:40.187 に答える
7

また、このプレビュー形式のせいで頭が痛くなりました。

私が見つけることができる最高のものはこれらです:

http://www.fourcc.org/yuv.php#NV21

http://v4l2spec.bytesex.org/spec/r5470.htm

Y コンポーネントは、取得した配列の最初の width*height バイトのようです。

その他の情報リンク:

http://msdn.microsoft.com/en-us/library/ms867704.aspx#yuvformats_yuvsampling

http://msdn.microsoft.com/en-us/library/ff538197(v=vs.85).aspx

お役に立てれば。

于 2011-04-27T10:52:33.893 に答える
4

データは YUV420 形式です。
モノクロ チャネル、つまり「白黒」のみに関心がある場合は、これwidth x heightが既に持っているデータ バッファーの最初のバイトです。チャネルは最初の
イメージプレーンです。まさにグレー/強度/輝度などのチャネルです。Y

于 2012-05-01T09:46:05.657 に答える