【问题标题】:Camera2 api Imageformat.yuv_420_888 results on rotated imageCamera2 api Imageformat.yuv_420_888 旋转图像的结果
【发布时间】:2017-11-22 23:37:11
【问题描述】:

关于camera2 api和RAW图像格式已经提出了很多问题,但是在网上搜索我仍然没有找到答案(这就是为什么我在这里顺便说一句)。

我正在尝试使用ImageReader 对摄像头捕获的帧进行一些实时图像处理,并使用前置摄像头设置重复请求。正如之前一些帖子中所建议的,我正在获取 RAW 格式的图像(特别是 Imageformat.yuv_420_888),以便获得大约 30fps 的帧速率:

  imageReader = ImageReader.newInstance(width, height, ImageFormat.YUV_420_888, 2); 

我的图像处理算法需要一个 RGB 图像作为输入,所以我需要将 YUV 转换为 RGB。为此,我使用ScriptIntrinsicYuvToRGB

  private static Bitmap YUV_420_888_toRGBIntrinsics(Image image) {

    if (image == null) return null;

    int W = image.getWidth();
    int H = image.getHeight();

    Image.Plane Y = image.getPlanes()[0];
    Image.Plane U = image.getPlanes()[1];
    Image.Plane V = image.getPlanes()[2];

    int Yb = Y.getBuffer().remaining();
    int Ub = U.getBuffer().remaining();
    int Vb = V.getBuffer().remaining();

    byte[] data = new byte[Yb + Ub + Vb];


    Y.getBuffer().get(data, 0, Yb);
    V.getBuffer().get(data, Yb, Vb);
    U.getBuffer().get(data, Yb + Vb, Ub);



    rs = RenderScript.create(context);
    ScriptIntrinsicYuvToRGB yuvToRgbIntrinsic = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

    Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
    Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

    Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(W).setY(H);
    Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);


    final Bitmap bmpout = Bitmap.createBitmap(W, H, Bitmap.Config.ARGB_8888); 

    in.copyFromUnchecked(data);

    yuvToRgbIntrinsic.setInput(in);
    yuvToRgbIntrinsic.forEach(out);
    out.copyTo(bmpout);
    image.close();
    return bmpout ;
}

这种方法非常快,因为我可以在不到 20 毫秒的时间内转换 1080p 图像。唯一的问题是图像结果旋转了 270 度(即照片是在横向模式下拍摄的)。即使我在相机生成器设置中设置了 JPEG_ORIENTATION,captureRequestBuilder.set(CaptureRequest.JPEG_ORIENTATION, characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)); 结果还是一样。

这是我的问题:

  • 有没有办法通过 renderscript 内部函数取回旋转的图像?
  • 是否有不分配内存的“旋转”函数?
  • 是否有 YUV 类型的图像旋转设置? 我尝试过的其他解决方案——矩阵旋转、YUV 数组旋转——非常慢。此外,我认为将图像旋转 90/180/270 是一项简单的任务,如果在拍摄后完成,只需要保存行而不是列(以某种方式)。

【问题讨论】:

  • 您好,您的问题解决了吗?如果可以,您可以发布结果代码吗?谢谢。

标签: android image-processing renderscript yuv android-camera2


【解决方案1】:

不,YUV 输出没有内置旋转。为了最大限度地减少开销,它始终由图像传感器按原样生成。您可以读取 SENSOR_ORIENTATION 字段以确定图像传感器在设备上的放置方式;通常,图像传感器的长边与 Android 设备的长边对齐,但这仍然会留下两个有效的旋转。

此外,如果您的目标是让图像“直立”,那么您还需要从加速度计读取设备的方向,并将其添加到旋转中。

您正在复制已经将图像中的帧放入分配中,因此进行 90/180/270 度旋转相对简单,尽管内存带宽密集。

您还可以查看 Google 的示例应用程序之一,HdrViewfinderDemo,该应用程序将相机数据传输到 RenderScript 中,而无需您执行中间副本,然后转换为 RGB 以绘制到 SurfaceView。它现在没有旋转,但您可以调整通过 rsGetElementAtYuv_uchar_* 完成的查找以执行 90 增量。

【讨论】:

  • 你好,“它现在没有旋转,但你可以调整通过 rsGetElementAtYuv_uchar_* 完成的查找以执行 90 增量”是什么意思。我尝试采用 HdrViewfinderDemo 方法使用 Renderscript 处理相机数据,但我不知道如何在纵向模式下进行输出。输出始终处于横向模式。
  • YUV 输出总是相同的方向。如果您要求 WxH 大小,无论您如何握住手机或 UI 朝向如何,您都会得到一个 WxH YUV 缓冲区。如果需要旋转缓冲区以在纵向 ImageView 或类似方式中显示,则需要自己完成。
  • @EddyTalvala:如何旋转缓冲区?
  • @EddyTalvala:你能看看stackoverflow.com/questions/57724927/…,你能帮我解决这个问题吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-16
  • 2015-12-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多