Беспорядок предварительного просмотра изображений Android camera2 при сохранении с помощью ImageReader

#java #android #android-camera2

#java #Android #android-camera2

Вопрос:

Я делаю серию снимков, используя Android Camera2 API для оценки позы в реальном времени и реконструкции окружающей среды (проблема SLAM). В настоящее время я просто сохраняю все эти снимки на своей SD-карте для автономной обработки.

Я настраиваю конвейер обработки в соответствии с тем, что Google 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();
                    }
                }
            }
        });
  

ImageReader Добавляется / удаляется при нажатии кнопки. ImageReader ‘s OnImageAvailableListener реализован следующим образом:

 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) для удаления старых кадров, а также проверил временную метку изображения, чтобы убедиться, что они монотонно увеличиваются.

Считыватель действительно получает изображения с приемлемой скоростью (около 25 кадров в секунду). Однако более пристальный взгляд на сохраненную последовательность изображений показывает, что они не всегда сохраняются в хронологическом порядке.

Следующие изображения взяты из длинной последовательности, снятой программой (извините, что не могу опубликовать изображения напрямую : ( ):

Изображение 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 размером буфера, поскольку при большем буфере происходит меньше «обратных вспышек». У кого-нибудь такая же проблема?

Ответ №1:

Я, наконец, обнаружил, что такой беспорядок исчезает при установке ImageReader формата YUV_420_888 в его конструкторе. Изначально я установил это поле как JPEG .

Использование JPEG формата приводит не только к большой задержке обработки, но и к беспорядку. Я предполагаю, что для преобразования данных датчика изображения в желаемый формат используется другое оборудование, такое как DSP или графический процессор, что не гарантирует хронологический порядок.

Ответ №2:

Используете ли вы TEMPLATE_STILL_CAPTURE для запросов на захват при включении ImageReader или просто TEMPLATE_PREVIEW? С какими устройствами вы видите проблемы?

Если вы используете STILL_CAPTURE, обязательно проверьте, поддерживает ли устройство флаг ENABLE_ZSL, и установите для него значение false. Когда для параметра установлено значение true (обычно по умолчанию на устройствах, которые его поддерживают, для шаблона STILL_CAPTURE), изображения могут быть возвращены не по порядку, поскольку на устройстве камеры установлена очередь с нулевой задержкой затвора.

Комментарии:

1. Спасибо за вашу заявку! Однако я использую TEMPLATE_PREVIEW и запускаю повторный сеанс захвата.