demos - git android example
La vista previa de la devolución de llamada en Camera2 es significativamente más lenta que en Camera1 (2)
Esto es solo una observación, pero lo publicaré de todos modos.
Usted dice que está registrando un OnImageAvailableListener . Este oyente no entrega imágenes, sino una referencia al mismo ImageReader
que se suscribió. Y luego debe llamar a acquireLatestImage
o acquireNextImage
para obtener la imagen real.
Hay un párrafo en los documentos que puede ser útil para entender lo que está pasando:
Los datos de la imagen se encapsulan en los objetos de la
Image
, y se puede acceder a varios de estos objetos al mismo tiempo, hasta el número especificado por el parámetro constructormaxImages
. Las nuevas imágenes enviadas a unImageReader
través de su superficie seacquireLatestImage()
la cola hasta que se accede a través de laacquireLatestImage()
oacquireNextImage()
. Debido a los límites de memoria, una fuente de imagen eventualmente bloqueará o eliminará Imágenes al intentar renderizar en la Superficie si elImageReader
no obtiene y libera Imágenes a una tasa igual a la tasa de producción.
Así que algunas cosas que podrían ayudar:
- solicitar memoria grande en el manifiesto
- Pase un argumento lo suficientemente grande como
maxImages
al constructorImageReader
(IllegalStateException
si de todos modos agota la cola). - Prefiera
acquireLatestImage
sobreacquireNextImage
para el procesamiento en tiempo real. Este método libera automáticamente las imágenes más antiguas mientras que la otra no lo hace, y, por lo tanto, el uso deacquireNextImage
por error reducirá la velocidad de entrega de la imagen hasta que se quede sin memoria.
Es 2017 y finalmente estoy empezando a cambiar de Camera1 a Camera2. En Camera1 confiaba enormemente en setPreviewCallbackWithBuffer()
para realizar un procesamiento de cuadros en tiempo real, sin embargo, en Camera2 esto funciona mucho más lento hasta el punto en que se vuelve casi inutilizable.
Para comparar, en Moto G3, Camera1 puede producir fácilmente 30-40 FPS mientras que en Camera2 no pude obtener más de 10-15 FPS.
Así es como estoy creando 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()
);
La devolución de llamada en sí hace el trabajo mínimo posible:
Image image = reader.acquireNextImage();
image.close();
Ya verifiqué respuestas similares, como esta . Sin embargo, su problema es que están utilizando el formato de imagen JPEG
lugar de YUV_420_888
.
¿Cómo lograr un rendimiento similar al de Camera1?
Tuve los mismos problemas de rendimiento en una aplicación compatible con las API de Camera1 y Camera2. Cuando la versión de Android estaba por encima de Lollipop, solía cambiar a la API de Camera2, lo que me daba muy malos resultados (tenía dos objetivos a la vez: un ImageReader y un Surface).
Terminé usando la API de Camera2 solo cuando el teléfono tenía soporte completo de hardware. Puede verificar usando las Características de la Cámara.INFO_SUPPORTED_HARDWARE_LEVEL
Espero eso ayude