Join FlipAndroid.COM Telegram Group: https://t.me/joinchat/F_aqThGkhwcLzmI49vKAiw


Extraiga la imagen en blanco y negro del formato NV21 de la cámara de Android

He hecho algunos google-ing alrededor y no podía encontrar suficiente información sobre este formato. Es el formato predeterminado para la vista previa de la cámara. ¿Puede alguien sugerir buenas fuentes de información sobre él y cómo extraer datos de una foto / vista previa de la imagen con ese formato? Para ser más específico, necesito la imagen en blanco y negro extraída.

EDIT: Parece que ese formato también se llama YCbCr 420 Semi Planar

  • Por qué el mismo color se ve diferente en diferentes dispositivos Android
  • Cómo obtener valores RGB de mapa de bits en android
  • Imágenes verdes al hacer una codificación JPEG desde YUV_420_888 utilizando la nueva cámara Android2 api
  • Convertir Bitmap en la memoria a Bitmap con Bitmap.Config.RGB_565
  • Cómo cargar los recursos de imagen como RGB 565
  • Valor RGB para el convertidor HSL
  • Cómo configurar el color rgb en Android?
  • Procesamiento de imágenes con Android Camera
  • 6 Solutions collect form web for “Extraiga la imagen en blanco y negro del formato NV21 de la cámara de Android”

    He desarrollado el siguiente código para convertir el NV21 a RGB, y está funcionando.

     /** * Converts YUV420 NV21 to RGB8888 * * @param data byte array on YUV420 NV21 format. * @param width pixels width * @param height pixels height * @return a RGB8888 pixels int array. Where each int is a pixels ARGB. */ public static int[] convertYUV420_NV21toRGB8888(byte [] data, int width, int height) { int size = width*height; int offset = size; int[] pixels = new int[size]; int u, v, y1, y2, y3, y4; // i percorre os Y and the final pixels // k percorre os pixles U e V for(int i=0, k=0; i < size; i+=2, k+=2) { y1 = data[i ]&0xff; y2 = data[i+1]&0xff; y3 = data[width+i ]&0xff; y4 = data[width+i+1]&0xff; u = data[offset+k ]&0xff; v = data[offset+k+1]&0xff; u = u-128; v = v-128; pixels[i ] = convertYUVtoRGB(y1, u, v); pixels[i+1] = convertYUVtoRGB(y2, u, v); pixels[width+i ] = convertYUVtoRGB(y3, u, v); pixels[width+i+1] = convertYUVtoRGB(y4, u, v); if (i!=0 && (i+2)%width==0) i+=width; } return pixels; } private static int convertYUVtoRGB(int y, int u, int v) { int r,g,b; r = y + (int)(1.402f*v); g = y - (int)(0.344f*u +0.714f*v); b = y + (int)(1.772f*u); r = r>255? 255 : r<0 ? 0 : r; g = g>255? 255 : g<0 ? 0 : g; b = b>255? 255 : b<0 ? 0 : b; return 0xff000000 | (b<<16) | (g<<8) | r; } 

    Esta imagen ayuda a entender. YUV420 NV21

    Si usted desea apenas la imagen del grayscale es easer. Puede descartar toda la información U y V, y tomar sólo la información Y. El código podría ser así:

     /** * Converts YUV420 NV21 to Y888 (RGB8888). The grayscale image still holds 3 bytes on the pixel. * * @param pixels output array with the converted array o grayscale pixels * @param data byte array on YUV420 NV21 format. * @param width pixels width * @param height pixels height */ public static void applyGrayScale(int [] pixels, byte [] data, int width, int height) { int p; int size = width*height; for(int i = 0; i < size; i++) { p = data[i] & 0xFF; pixels[i] = 0xff000000 | p<<16 | p<<8 | p; } } 

    Para crear su mapa de bits sólo:

     Bitmap bm = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888); 

    Donde píxeles es su matriz int [].

    NV21 es básicamente YUV420 pero en lugar de planar donde Y, U y V tienen planos independientes, NV21 tiene 1 plano para Luma y 2º plano para Chroma. El formato parece

    YYYYYYYYYYYYYYYYYYYYYYYYYYYYY YYYYYYYYYYYYYYYYYYYYYYYYY. . . .

    (Detalles) Información Del Diseñador Creado Por bridgemanart: . . . .

    También tuve muchos dolores de cabeza debido a este formato de vista previa.

    Lo mejor que pude encontrar son los siguientes:

    http://www.fourcc.org/yuv.php#NV21

    http://v4l2spec.bytesex.org/spec/r5470.htm

    Parece que el componente Y es el primer ancho * bytes de altura en la matriz que obtiene.

    Algunos enlaces más informativos:

    http://msdn.microsoft.com/en-us/library/ms867704.aspx#yuvformats_yuvsampling

    http://msdn.microsoft.com/en-us/library/ff538197(v=vs.85).aspx

    Espero que esto ayude.

    Los datos están en formato YUV420.
    Si solo está interesado en el canal monocromo, es decir, "blanco y negro", entonces este es el primer width x height bytes del búfer de datos que ya tiene.
    El canal Y es el primer plano de imagen. Es exactamente el canal de gris / intensidad / luminosidad etc.

    Aquí está el código para extraer los datos de la imagen en escala de grises:

     private int[] decodeGreyscale(byte[] nv21, int width, int height) { int pixelCount = width * height; int[] out = new int[pixelCount]; for (int i = 0; i < pixelCount; ++i) { int luminance = nv21[i] & 0xFF; out[i] = Color.argb(0xFF, luminance, luminance, luminance); } return out; } 

    Cuando sólo necesita una vista previa de la cámara en escala de grises, podría utilizar un rendering simple:

     # pragma version(1) # pragma rs java_package_name(com.example.name) # pragma rs_fp_relaxed rs_allocation gIn; // Allocation filled with camera preview data (byte[]) int previewwidth; // camera preview width (int) // the parallel executed kernel void root(uchar4 *v_out, uint32_t x,uint32_t y){ uchar c = rsGetElementAt_uchar(gIn,x+y*previewwidth); *v_out = (uchar4){c,c,c,255}; } 

    Nota: Esto no es más rápido que ScriptIntrinsicYuvToRGB (y una siguiente ScriptIntrinsicColorMatrix para hacer el RGBA-> gris), pero se ejecuta con API 11+ (donde el Intrinsics necesita Api 17+).

    FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.