onPreviewFrame YUV灰度偏斜

时间:2013-05-24 14:47:15

标签: android image computer-vision yuv

我试图从运行相机视图的surfaceView获取图片,

我已经在onPreviewFrame上实现了,并且在调试显示我时正确调用了它。

我现在面临的问题,自从我在方法中收到的byte []数据以来,它是YUV空间颜色(NV21),我试图将其转换为灰度以生成位图,然后将其存储到文件中。

我跟随它的转换过程:

 public Bitmap convertYuvGrayScaleRGB(byte[] yuv, int width, int height) {

    int[] pixels = new int[width * height];

    for (int i = 0; i < height*width; i++) {
        int grey = yuv[i] & 0xff;
        pixels[i] = 0xFF000000 | (grey * 0x00010101);
    }

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

  }

将其存储到文件的导入程序,它是:

Bitmap bitmap = convertYuvGrayScaleRGB(data,widht,heigth);

    ByteArrayOutputStream bytes = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 50, bytes);

        File f = new File(Environment.getExternalStorageDirectory()
                                    + File.separator + "test.jpg");

    Log.d("Camera", "File: " + f.getAbsolutePath());
    try {
        f.createNewFile();
        FileOutputStream fo = new FileOutputStream(f);
        fo.write(bytes.toByteArray());
        fo.close();
        bitmap.recycle();
        bitmap = null;
         } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

尽管如此,我得到的结果如下:

Result

4 个答案:

答案 0 :(得分:0)

我在代码中找不到任何明显的错误,但我之前已经遇到过这种偏斜的图像。当这件事发生在我身上时,原因是:

  • 在代码中的某个位置,交换图像宽度和高度,
  • 或者您尝试转换的原始图片有填充,在这种情况下,除了宽度和高度之外,您还需要stride

希望这有帮助!

答案 1 :(得分:0)

您正在转换的图像的宽度可能不均匀。在这种情况下 它被填充在记忆中。

让我看看文档......

看起来比这更复杂。如果您希望代码按现在的样子运行,则必须具有宽度 16的倍数。

来自文档:

  

public static final int YV12

     

在API级别9 Android YUV格式中添加。

     

这种格式暴露给软件解码器和应用程序。

     

YV12是由WxH Y平面组成的4:2:0 YCrCb平面格式   接着是(W / 2)x(H / 2)Cr和Cb平面。

     

此格式假设

     

均匀宽度,偶数高度,水平跨度为16像素的倍数   垂直步幅等于高度y_size = stride * height   c_stride = ALIGN(stride / 2,16)c_size = c_stride * height / 2 size =   y_size + c_size * 2 cr_offset = y_size cb_offset = y_size + c_size

答案 2 :(得分:0)

我刚刚遇到S3这个问题。我的问题是我使用了错误的尺寸进行预览。我认为相机是16:9,实际上是4:3。

使用Camera.getParameters()。getPreviewSize()查看输出内容。

答案 3 :(得分:0)

我做到了:

int frameSize = width * height;
for (int i = 0; i < height; i++) {
    for (int j = 0; j < width; j++) {
        ret[frameSize + (i >> 1) * width + (j & ~1) + 1] = 127; //U
        ret[frameSize + (i >> 1) * width + (j & ~1) + 0] = 127; //V
    }
}

如此简单但它的效果非常好而且速度很快;)