如何在ARCore中从session.update()获取Bitmap [A​​ndroid Studio]

高博衍*_*高博衍 3 java android bitmap bitmapfactory arcore

我正在尝试使用 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){

}
Run Code Online (Sandbox Code Playgroud)

我正在mFrameonDrawFrameGLSurfaceView用来显示相机图像的地方获取信息。一切工作正常,除了我的位图等于空。

我使用的是按钮,因此只使用了一个框架,如下所示:

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();
    }
});
Run Code Online (Sandbox Code Playgroud)

capturedImagebuffer并且bytes全部不等于 null。

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

多谢

Cli*_*nkz 6

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

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

但它总是等于 null

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

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

为此,您需要使用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)
Run Code Online (Sandbox Code Playgroud)

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