首页 > 解决方案 > 如何在 ARCore [Android Studio] 中从 session.update() 获取位图

问题描述

我正在尝试使用 ARCore 从我的 ARSession 的当前帧中获取位图。但它始终等于 null。我已经在网上搜索了很长一段时间,但无法弄清楚我做错了什么。

try {
    capturedImage = mFrame.acquireCameraImage();

    ByteBuffer buffer = capturedImage.getPlanes()[0].getBuffer();

    byte[] bytes = new byte[buffer.capacity()];

    Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length,null);

    if (bitmap == null) 
        Log.e(TAG,"Bitmap was NOT initialized!");

} catch(Exception e){

}

我是mFrameonDrawFrameGLSurfaceView用来显示相机图像的。一切正常,除了我的位图等于空。

我使用的是 Button,因此只使用了一个 Frame,如下所示:

scanButton = (Button) findViewById(R.id.scanButton);
scanButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        checkbox = false;
        if (capturedImage!=null) capturedImage.close();
            BitmapMethod();
    }
});

capturedImage,buffer并且bytes全部不等于 null。

可能有什么问题mFrame.acquireCameraImage()吗?

非常感谢

标签: javaandroidbitmapbitmapfactoryarcore

解决方案


mFrame.acquireCameraImage() 可能有问题吗?

不,mFrame.acquireCameraImage()按预期工作。

但它总是等于 null

由于位图工厂不理解传递给它的图像数据,因此位图将始终等于 null。

该方法以 YUV 格式或 YCbCrmFrame.acquireCameraImage()类型的对象进行响应。Image这些类型的图像有 3 个平面,这里很好地解释了这些平面。这些平面中包含的内容可以由 CPU/GPU 在代码ByteArray中直接读取。无法读取此类数据。因此,您需要将此 YUV 图像转换为其他图像。nativeBitmapFactory

为此,您需要使用YuvImage类来创建 YUV 的实例,然后使用该compressToJpeg方法将其转换为 JPEG。一旦你得到了 byteArray,你就可以简单地做你在上面做的事情。用于BitmapFactory将其转换为位图并将其添加到您的ImageView.

注意:YUV 有 3 个平面。从所有平面创建一个字节数组,然后将其传递给 YUV 构造函数。虽然没有详细说明,但它应该看起来类似于:

//The camera image received is in YUV YCbCr Format. Get buffers for each of the planes and use them to create a new bytearray defined by the size of all three buffers combined
val cameraPlaneY = cameraImage.planes[0].buffer
val cameraPlaneU = cameraImage.planes[1].buffer
val cameraPlaneV = cameraImage.planes[2].buffer

//Use the buffers to create a new byteArray that 
val compositeByteArray = ByteArray(cameraPlaneY.capacity() + cameraPlaneU.capacity() + cameraPlaneV.capacity())

cameraPlaneY.get(compositeByteArray, 0, cameraPlaneY.capacity())
cameraPlaneU.get(compositeByteArray, cameraPlaneY.capacity(), cameraPlaneU.capacity())
cameraPlaneV.get(compositeByteArray, cameraPlaneY.capacity() + cameraPlaneU.capacity(), cameraPlaneV.capacity())

val baOutputStream = ByteArrayOutputStream()
val yuvImage: YuvImage = YuvImage(compositeByteArray, ImageFormat.NV21, cameraImage.width, cameraImage.height, null)
yuvImage.compressToJpeg(Rect(0, 0, cameraImage.width, cameraImage.height), 75, baOutputStream)
val byteForBitmap = baOutputStream.toByteArray()
val bitmap = BitmapFactory.decodeByteArray(byteForBitmap, 0, byteForBitmap.size)
imageView.setImageBitmap(bitmap)

这只是一个粗略的代码。它也许有改进的余地。另请参阅此处


推荐阅读