使用ImageReader保存时,Android camera2预览图像无序

问题描述 投票:0回答:2

我正在使用Android Camera2 API拍摄一系列照片,用于实时姿势估计和环境重建(SLAM问题)。目前我只是将所有这些图片保存在我的SD卡中进行离线处理。

我根据谷歌的Camera2Basic使用TextureView以及ImageReader设置处理管道,它们都被设置为重复预览请求的目标表面。

mButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(mIsShooting){
                    try {
                        mCaptureSession.stopRepeating();
                        mPreviewRequestBuilder.removeTarget(mImageReader.getSurface());
                        mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
                        mIsShooting = false;
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
                else{
                    try {
                        mCaptureSession.stopRepeating();
                        mPreviewRequestBuilder.addTarget(mImageReader.getSurface());
                        mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler);
                        mIsShooting = true;
                    } catch (CameraAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

按下按钮时添加/删除ImageReaderImageReaderOnImageAvailableListener实施如下:

private ImageReader.OnImageAvailableListener mOnImageAvailableListener = new ImageReader.OnImageAvailableListener() {
        @Override
        public void onImageAvailable(ImageReader reader) {
            Image img = reader.acquireLatestImage();
            if(null == img){
                return;
            }
            if(img.getTimestamp() <= mLatestFrameTime){
                Log.i(Tag, "disorder detected!");
                return;
            }
            mLatestFrameTime = img.getTimestamp();
            ImageSaver saver = new ImageSaver(img, img.getTimestamp());
            saver.run();
        }
    };

我使用acquireLatestImage(缓冲区大小设置为2)来丢弃旧帧,并检查图像的时间戳以确保它们单调增加。

读者确实以可接受的速率(约25fps)接收图像。但仔细观察保存的图像序列表明它们并不总是按时间顺序保存。

以下图片来自程序拍摄的长序列(抱歉无法直接发布图片:():

图1:

https://github.com/thuliangjz/openfile/blob/master/pic01218.jpg

图2:

https://github.com/thuliangjz/openfile/blob/master/pic01219.jpg

图3:

https://github.com/thuliangjz/openfile/blob/master/pic01218.jpg

这种病症不会经常发生,但它们可以随时发生,似乎不是初始化问题。我认为它与ImageReader的缓冲区大小有关,因为更大的缓冲区更少发生“闪回”。有没有人有同样的问题?

java android android-camera2
2个回答
0
投票

您是否在启用ImageReader时使用TEMPLATE_STILL_CAPTURE进行捕获请求,或者仅使用TEMPLATE_PREVIEW?您看到哪些设备存在问题?

如果您正在使用STILL_CAPTURE,请确保检查设备是否支持ENABLE_ZSL标志,并将其设置为false。当它设置为true时(通常是支持它的设备上的默认值,对于STILL_CAPTURE模板),图像可能无序返回,因为在相机设备中有一个零快门滞后队列。


0
投票

我终于发现,当ImageReader的格式在其构造函数中为YUV_420_888时,这种混乱就会消失。最初我把这个字段设为JPEG

使用JPEG格式不仅会导致大的处理延迟,还会导致无序。我想从图像传感器数据到所需格式的转换利用其他硬件,如DSP或GPU,不保证按时间顺序排列。

© www.soinside.com 2019 - 2024. All rights reserved.