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.
- Rotar una matriz de bytes YUV en Android
- La manera más rápida de dibujar un marco de vídeo decodificado con MediaCodec a la pantalla?
- Camera.PreviewCallback equivalente en Camera2 API
- Convertir el marco de vista previa en un mapa de bits
- Decodificación de YUV a RGB en C / C ++ con NDK
Como podemos ver diferencia entre N21 y yuv420 no grande e intento convertir datos a N21
YUV420:
Y N21:
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:
¿¿Qué me perdí??
- Rotación de la imagen YUV420 / NV21 en android
- Cómo convertir RGB565 a YUV420SP más rápido en Android?
- Convierta la matriz de bytes NV21 en formato legible de mapa de bits
- Android cámara2 jpeg framerate
- Convertir de YUV a RGB en c + + (android-ndk)
- Cómo convertir el formato de imagen NV21 en mapa de bits?
- Convertir android.media.Image (YUV_420_888) en mapa de bits
- Problemas al escalar una imagen YUV utilizando la biblioteca libyuv
Hay dos problemas principales en su intento de conversión:
- 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 . - 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(); }
- ¿Cómo desactivo la captura de pantalla de una aplicación Android?
- Por qué no puedo usar "correr Android lint" desde el menú "Window" en Eclipse en la barra de herramientas Puedo ejecutar, ¿está bien?