从Android相机的NV21格式中提取黑白图像

Eth*_*han 31 rgb android format-conversion android-camera

我做了一些google-ing,但找不到有关此格式的足够信息.它是相机预览的默认格式.任何人都可以建议有关它的良好信息来源以及如何从该格式的照片/预览图像中提取数据?更具体地说,我需要提取黑白图像.

编辑:似乎这种格式也称为YCbCr 420 Semi Planar

Der*_*rzu 81

我开发了以下代码将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;
}
Run Code Online (Sandbox Code Playgroud)

这张图片有助于理解. 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

要创建您的位图:

Bitmap bm = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888);
Run Code Online (Sandbox Code Playgroud)

像素是int []数组的位置.

  • 图形中有错误.显示的字节布局是NV12,而不是NV21.唯一的区别是UV字节被翻转.NV12:YYYYUV NV21:YYYYVU (6认同)
  • @Derzu你只是摇滚!! \米/ (2认同)
  • 我认为上述答案是错误的.http://www.fourcc.org/pixel-format/yuv-nv21/列出NV21具有V/U平面而不是U/V,如上所述是NV12.请参阅http://stackoverflow.com/questions/12469730/confusion-on-yuv-nv21-conversion-to-rgb另一个参考:https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/pixfmt -nv12.html?突显= NV21 (2认同)

小智 12

NV21基本上是YUV420,但是在Y,U和V具有独立平面的平面格式中,NV21具有1个用于Luma的平面和用于色度的第2平面.格式看起来像

每年年度,年度,年度,情况友好,非常友好,非常友好....

VUVUVUVUVUVUVUVUVUVUVUVUVUVUVU VUVUVUVUVUVUVUVUVUVUVUVUVUVUVU.....


Max*_*Max 7

由于这种预览格式,我也很头疼.

我能找到的最好的是这些:

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

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

似乎Y组件是您获得的数组中的第一个宽度*高度字节.

一些更多的信息链接:

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

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

希望这可以帮助.