Подтвердить что ты не робот

Предварительный обратный вызов в Camera2 значительно медленнее, чем в Camera1

Это 2017 год, и я, наконец, начинаю переключение с Camera1 на Camera2. В Camera1 я очень полагался на setPreviewCallbackWithBuffer() для выполнения обработки в реальном времени, однако в Camera2 это работает намного медленнее до такой степени, что становится почти непригодным.

Для сравнения, на Moto G3 Camera1 можно легко производить 30-40 FPS, а на Camera2 я не мог получить более 10-15 FPS.

Вот как я создаю ImageReader

imageReader = ImageReader
  .newInstance(
    previewSize.width,        // size is around 1280x720
    previewSize.height,
    ImageFormat.YUV_420_888,  // note, it is not JPEG
    2 // max number of images, does not really affect performance
  );

imageReader.setOnImageAvailableListener(
  callback,
  CameraThread.getInstance().createHandler()
);

Сам обратный вызов выполняет минимально возможное задание:

Image image = reader.acquireNextImage();
image.close();

Я уже проверил аналогичные ответы, например этот. Однако их проблема заключается в том, что они используют JPEG формат изображения вместо YUV_420_888.

Как добиться производительности, аналогичной Camera1?

4b9b3361

Ответ 1

Это просто наблюдение, но я все равно отправлю его.

Вы говорите, что регистрируете OnImageAvailableListener. Этот слушатель не доставляет изображения, а ссылку на тот же ImageReader, на который вы подписаны. И тогда вы должны позвонить либо acquireLatestImage, либо acquireNextImage, чтобы получить фактическое изображение.

В docs есть абзац, который может быть полезен для понимания того, что происходит:

Данные изображения инкапсулируются в объекты Image, и к ним можно одновременно обращаться к нескольким таким объектам, вплоть до числа, указанного параметром конструктора maxImages. Новые изображения, отправленные на ImageReader через его поверхность, помещаются в очередь до тех пор, пока не будут доступны через вызов acquireLatestImage() или acquireNextImage(). Из-за ограничений памяти источник изображения в конечном итоге сдерживает или удаляет изображения при попытке визуализации на поверхность, если ImageReader не получает и не отпускает изображения со скоростью, равной скорости производства.

Итак, некоторые вещи, которые могут помочь:

  • запрос большой памяти в манифесте
  • Передайте достаточно большой аргумент maxImages конструктору ImageReader (вы получите IllegalStateException, если вы все равно исчерпаете очередь).
  • Предпочитает acquireLatestImage более acquireNextImage для обработки в реальном времени. Этот метод автоматически удаляет старые изображения, а другой - нет, и, следовательно, использование acquireNextImage по ошибке будет все более замедлять доставку изображений до тех пор, пока вы не исчерпаете память.

Ответ 2

У меня были те же проблемы с производительностью в приложении, поддерживающем как Camera1, так и Camera2 API. Когда версия Android была выше Lollipop, я использовал для переключения на Camera2 API, что приводило к очень плохим результатам (у меня было две цели: ImageReader и Surface).

Я закончил использовать Camera2 API только тогда, когда по телефону была полная аппаратная поддержка. Вы можете проверить, используя CameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL

Надеюсь, что это поможет