Camera2 api convertir yuv420 a rgb verde hacia fuera

I intentar convertir la imagen de YUV_420_888 a rgb y tengo algunos problemas con la imagen de salida. En ImageReader consigo la imagen en el formato YUV_420_888 (usando la cámara 2 api para conseguir esta previsualización de la imagen).

imageReader = ImageReader.newInstance(1920,1080,ImageFormat.YUV_420_888,10); 

En android sdk para YuvImage escritura de clase, que YuvImage con sólo NV21, YUY2.

Como podemos ver diferencia entre N21 y yuv420 no grande e intento convertir datos a N21

YUV420: Introduzca aquí la descripción de la imagen

Y N21: Introduzca aquí la descripción de la imagen

In onImageAvailable consigo por separado cada Planes y los pongo en el lugar correcto (como en la imagen)

 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ByteBuffer bufferY = image.getPlanes()[0].getBuffer(); byte[] data0 = new byte[bufferY.remaining()]; bufferY.get(data0); ByteBuffer bufferU = image.getPlanes()[1].getBuffer(); byte[] data1 = new byte[bufferU.remaining()]; bufferU.get(data1); ByteBuffer bufferV = image.getPlanes()[2].getBuffer(); byte[] data2 = new byte[bufferV.remaining()]; bufferV.get(data2); ... outputStream.write(data0); for (int i=0;i<bufferV.remaining();i++) { outputStream.write(data1[i]); outputStream.write(data2[i]); } 

Después de crear YuvImage, convertir a mapa de bits, ver y guardar

 final YuvImage yuvImage = new YuvImage(outputStream.toByteArray(), ImageFormat.NV21, 1920,1080, null); ByteArrayOutputStream outBitmap = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(0, 0,1920, 1080), 95, outBitmap); byte[] imageBytes = outBitmap.toByteArray(); final Bitmap imageBitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); mImageView.setImageBitmap(imageBitmap); ... imageBitmap.compress(Bitmap.CompressFormat.JPEG, 95, out); 

Pero mi imagen guardada es verde y rosa: Captura de imagen Captura de imagen

¿¿Qué me perdí??

Hay dos problemas principales en su intento de conversión:

  1. No podemos suponer que los planos U y V están aislados, pueden contener datos entrelazados (por ejemplo, U-PLANE = {U1, V1, U2, V2, ...} ). De hecho, podría incluso ser un estilo NV21 entrelazado ya. La clave aquí es mirar la zancada de la fila del plano y la zancada del pixel y también comprobar qué podemos asumir sobre el formato de YUV_420_888 .
  2. El hecho de que hayas comentado que la mayoría de los datos de los aviones U an V son ceros indica que estás experimentando un error de Android en la generación de imágenes en YUV_420_888 . Esto significa que incluso si obtiene la conversión correcta, la imagen seguiría siendo verde si se ve afectado por el error, que sólo se corrigió en Android 5.1.1 y superior, por lo que vale la pena comprobar la versión que está utilizando además Fijando el código.

He implementado la lógica YUV_420 (exactamente como se muestra en el diagrama anterior) en RenderScript, vea el código completo aquí:

Conversión YUV_420 _888 a Bitmap, código completo

Produce bimaps perfectos para la API 22, pero para la API 21 muestra el "idilio verde". De esto puedo confirmar, los resultados que encontró. Como ya se mencionó anteriormente por Silvaren, la razón parece ser un error de Android en la API 21. Mirando mi código rs está claro, que si la información U y V falta (es decir, cero) el componente G (reen) ARGB se vuelve enorme durante la conversión.

Veo fotos verdes similares en mi Galaxy S5 (todavía API 21) – aquí incluso al revés ;-). Sospecho que la mayoría de los dispositivos de la API 21 todavía no usan Camera2 para sus aplicaciones de dispositivo-cámara. Hay una aplicación gratuita llamada "Manual Camera Compatibility" que permite probar esto. De esto veo que efectivamente el S5 / API21 aún no usa Camera2 … afortunadamente no …

bufferV.get(data2) aumenta la posición del ByteBuffer. Es por eso que el bucle for (int i=0;i<bufferV.remaining();i++) produce 0 iteraciones. Puede reescribirlo fácilmente como

 for (int i=0; i<data1.length; i++) { outputStream.write(data1[i]); outputStream.write(data2[i]); } 

Conseguí una imagen de ImageFormat.YUV_420_888 y tenía éxito para ahorrar al archivo del jpeg, y podría verlo correctamente en ventanas.
Estoy compartiendo aquí:

 private final Image mImage; private final File mFile; private final int mImageFormat; ByteArrayOutputStream outputbytes = new ByteArrayOutputStream(); ByteBuffer bufferY = mImage.getPlanes()[0].getBuffer(); byte[] data0 = new byte[bufferY.remaining()]; bufferY.get(data0); ByteBuffer bufferU = mImage.getPlanes()[1].getBuffer(); byte[] data1 = new byte[bufferU.remaining()]; bufferU.get(data1); ByteBuffer bufferV = mImage.getPlanes()[2].getBuffer(); byte[] data2 = new byte[bufferV.remaining()]; bufferV.get(data2); try { outputbytes.write(data0); outputbytes.write(data2); outputbytes.write(data1); final YuvImage yuvImage = new YuvImage(outputbytes.toByteArray(), ImageFormat.NV21, mImage.getWidth(),mImage.getHeight(), null); ByteArrayOutputStream outBitmap = new ByteArrayOutputStream(); yuvImage.compressToJpeg(new Rect(0, 0,mImage.getWidth(), mImage.getHeight()), 95, outBitmap); FileOutputStream outputfile = null; outputfile = new FileOutputStream(mFile); outputfile.write(outBitmap.toByteArray()); } catch (IOException e) { e.printStackTrace(); } finally { mImage.close(); } 
  • ¿Por qué el decodificador de MediaCodec no emite un formato YUV unificado (como YUV420P)?
  • Convertir YUV-> RGB (procesamiento de imágenes) -> YUV durante onPreviewFrame en android?
  • Cómo mostrar la imagen de YUV en Android
  • Convertir la cámara Android api YUV_420_888 a RGB
  • Cámara adecuada2 YUV_420_888 a conversión de JPEG
  • Fuera de memoria al usar compresstojpeg en varios YuvImage uno a la vez
  • OnPreviewFrame data image to imageView
  • Imágenes verdes al hacer una codificación JPEG desde YUV_420_888 utilizando la nueva cámara Android2 api
  • Convertir matriz de mapa de bits a YUV (YCbCr NV21)
  • El proceso de alojamiento del servicio de cámara ha muerto inesperadamente
  • YUV_420_888 interpretación en Samsung Galaxy S7 (Camera2)
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.