2011-07-28 21 views
12

Quiero hacer algunos procesamientos de imágenes a los píxeles obtenidos de la cámara.píxeles de la cámara girados

El problema es que los píxeles de la cámara se giran 90 grados.

Im que consigue los píxeles dentro del método onPreviewFrame(byte[] data, Camera camera)

me trató camera.setDisplayOrientation(90); y se muestra el vídeo en la orientación correcta, pero todavía estoy recibiendo los píxeles rotados como se indica en la documentación:

Esto hace no afecta el orden de la matriz de bytes pasada en Android.Hardware.Camera.IPreviewCallback.OnPreviewFrame (Byte [], Android.Hardware.Camera), imágenes JPEG o videos grabados.

También probé:

parameters.setRotation(90); 
camera.setParameters(parameters); 

pero que no funcionó.

estoy usando androide 2,2

enter image description here

imagen superior muestra el SurfaceView utilizando camera.setDisplayOrientation(90);

La segunda imagen se incorpora dentro de onPreviewFrame(byte[] data, Camera camera) de la matriz data. Como puede ver, la matriz data se gira.

Respuesta

5

Tal vez pueda realizar el procesamiento de imágenes en el marco lateral, y solo se preocupe por la rotación cuando lo muestre (lo que ya ha hecho). Si no es así, debe girar el marco de la manera antigua. He encontrado algo de código en algún lugar (con una pequeña modificación) que podría ayudar:

// load the origial bitmap 
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), 
     R.drawable.android); 

int width = bitmap.width(); 
int height = bitmap.height(); 

// create a matrix for the manipulation 
Matrix matrix = new Matrix(); 
// rotate the Bitmap 90 degrees (counterclockwise) 
matrix.postRotate(90); 

// recreate the new Bitmap, swap width and height and apply transform 
Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap, 0, 0, 
        width, height, matrix, true); 

Esto es fácil porque el método CreateBitmap soporta una transformación de matriz: http://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(android.graphics.Bitmap, int, int, int, int, android.graphics.Matrix, boolean)

2

Puede rotar los datos en bruto de la siguiente manera:

// Rotate the data for Portait Mode 
byte[] rotatedData = new byte[data.length]; 
for (int y = 0; y < height; y++) { 
    for (int x = 0; x < width; x++) 
     rotatedData[x * height + height - y - 1] = data[x + y * width]; 
} 

Donde 'ancho' y 'altura' son los tamaños preestablecidos para su imagen de vista previa usando:

Camera.Parameters parameters = camera.getParameters(); 
parameters.setPreviewSize(width, height); 
camera.setParameters(parameters); 

A continuación, puede utilizar los datos girados en consecuencia.

Solo he usado este método para escanear códigos QR y parece funcionar perfectamente. No estoy seguro de cómo podría afectar otras aplicaciones.

+0

Esto no funcionó, dio una ArrayIndexOutOFBoundsException. –

+0

Siempre que la imagen de vista previa que reciba coincida con los valores de ancho y alto, entonces no debería recibir una excepción fuera de límite. Este es el código exacto que estoy usando en este momento y funciona muy bien. – Scott

+0

Los datos brutos se rotan bien, pero la calidad de la imagen baja, después de usar su código no puedo obtener la calidad de imagen adecuada, ¿puede explicar algunos puntos más sobre la pieza giratoria o me puede dar algún enlace útil? por lo mismo. Tu ayuda será altamente apreciada. –

4

Si recibe una matriz de bytes YUV420, el siguiente método puede girar esto en 90 grados.

private byte[] rotateYUV420Degree90(byte[] data, int imageWidth, int imageHeight) 
{ 
    byte [] yuv = new byte[imageWidth*imageHeight*3/2]; 
    // Rotate the Y luma 
    int i = 0; 
    for(int x = 0;x < imageWidth;x++) 
    { 
     for(int y = imageHeight-1;y >= 0;y--)        
     { 
      yuv[i] = data[y*imageWidth+x]; 
      i++; 
     } 
    } 
    // Rotate the U and V color components 
    i = imageWidth*imageHeight*3/2-1; 
    for(int x = imageWidth-1;x > 0;x=x-2) 
    { 
     for(int y = 0;y < imageHeight/2;y++)         
     { 
      yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+x]; 
      i--; 
      yuv[i] = data[(imageWidth*imageHeight)+(y*imageWidth)+(x-1)]; 
      i--; 
     } 
    } 
    return yuv; 
} 

(Tenga en cuenta que esto sólo podría funcionar si el ancho y la altura es un factor de 4)

+1

no funciona! Por favor, ayúdenme con esto dio una ArrayIndexOutOFBoundsException – therealprashant

6

Aunque estoy un poco tarde a la fiesta, aquí está un método escribí que otros podrían serle de utilidad para girar una imagen YUV420sp (NV21).Ninguno de los otros métodos que vi en SO parecía realmente hacerlo.

public static byte[] rotateNV21(final byte[] yuv, 
           final int width, 
           final int height, 
           final int rotation) 
{ 
    if (rotation == 0) return yuv; 
    if (rotation % 90 != 0 || rotation < 0 || rotation > 270) { 
    throw new IllegalArgumentException("0 <= rotation < 360, rotation % 90 == 0"); 
    } 

    final byte[] output = new byte[yuv.length]; 
    final int  frameSize = width * height; 
    final boolean swap  = rotation % 180 != 0; 
    final boolean xflip  = rotation % 270 != 0; 
    final boolean yflip  = rotation >= 180; 

    for (int j = 0; j < height; j++) { 
    for (int i = 0; i < width; i++) { 
     final int yIn = j * width + i; 
     final int uIn = frameSize + (j >> 1) * width + (i & ~1); 
     final int vIn = uIn  + 1; 

     final int wOut  = swap ? height    : width; 
     final int hOut  = swap ? width    : height; 
     final int iSwapped = swap ? j     : i; 
     final int jSwapped = swap ? i     : j; 
     final int iOut  = xflip ? wOut - iSwapped - 1 : iSwapped; 
     final int jOut  = yflip ? hOut - jSwapped - 1 : jSwapped; 

     final int yOut = jOut * wOut + iOut; 
     final int uOut = frameSize + (jOut >> 1) * wOut + (iOut & ~1); 
     final int vOut = uOut + 1; 

     output[yOut] = (byte)(0xff & yuv[yIn]); 
     output[uOut] = (byte)(0xff & yuv[uIn]); 
     output[vOut] = (byte)(0xff & yuv[vIn]); 
    } 
    } 
    return output; 
} 
+0

precaución: Esto parece provenir de https://github.com/SMSSecure/SMSSecure/blob/master/src/org/smssecure/smssecure/util/BitmapUtil.java y el proyecto es etiquetado GPLv3. Las herramientas que buscan infracciones GPL pueden marcar su programa si usa esto. – laalto

+0

se originó en https://github.com/WhisperSystems/Signal-Android/blob/master/src/org/thoughtcrime/securesms/util/BitmapUtil.java fuente: lo escribí y lo puse allí. – jake

+0

Gracias, parece que el primer proyecto exitoso es una bifurcación de su proyecto. De todos modos, hay GPLv3 y las herramientas que buscan infracciones de GPL pueden marcar el código con este fragmento. (Para mí: estaba revisando un fragmento de código propietario donde se destacaba este fragmento y comencé a buscar en Google de dónde viene. Ahora se ha eliminado del espacio de código propietario). – laalto

Cuestiones relacionadas