2011-06-23 20 views
6

Quiero hacer una aplicación de Android que use la cámara y aplique filtros de procesamiento de imagen en los marcos de vista previa.Android, manupulate camera preview frames

package alex.filter; 

import java.io.IOException; 

import android.content.Context; 
import android.graphics.Canvas; 
import android.hardware.Camera; 
import android.hardware.Camera.PreviewCallback; 
import android.view.SurfaceHolder; 
import android.view.SurfaceView; 

class Preview extends SurfaceView implements SurfaceHolder.Callback { 

    SurfaceHolder mHolder; 
    public Camera camera; 

    Preview(Context context) { 
     super(context); 
     mHolder = getHolder(); 
     mHolder.addCallback(this); 
     mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); 
    } 

    public void surfaceCreated(SurfaceHolder holder) {   
     camera = Camera.open();   

     try { 
      camera.setPreviewDisplay(holder); 

      camera.setPreviewCallback(new PreviewCallback() { 
       public void onPreviewFrame(byte[] data, Camera arg1) {      
        for(int i = 0 ; i < data.length ; i ++){ 
         data[ i] = 0; // or some sirius filter 
        }                
        Preview.this.invalidate(); 
       } 
      }); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     } 

    public void surfaceDestroyed(SurfaceHolder holder) {   
     camera.stopPreview();   
     camera = null; 
    } 

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {   
     Camera.Parameters parameters = camera.getParameters(); 
     parameters.setPreviewSize(w, h); 
     camera.setParameters(parameters); 
     camera.startPreview(); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     super.draw(canvas);   
    } 
} 

Sin embargo, no veo cambios en el emulador no importa lo que hago en el método onPreviewFrame.

+1

+1, también me pregunto si es posible manipular directamente los marcos de vista previa. –

Respuesta

1

Bueno, eso se debe a que los búferes de vista previa que recibe en la devolución de llamada son solo una copia de los búferes de vista previa, por lo tanto, no se mostrarán las modificaciones que haga ya que el búfer que obtiene es su copia. Mencionado en el SDK de Android here

no estoy seguro de cómo hacer esto, pero me han estado dando un poco de pensamiento sobre cómo hacer esto y esto es lo que creo que se debe hacer -

  • Inscríbase las memorias intermedias de vista previa
  • desactivar la pantalla de vista previa por defecto
    • Si no ajusta la pantalla de vista previa a una superficie, entonces no debería tener ninguna pantalla (pero no estoy seguro de si va a trabajar - lo había leído en alguna foro no puede recordar la fuente)
    • Si lo anterior no funciona, entonces vamos a tener que ocultar la vista (lo sé casi eficiente, pero no podía pensar en otra cosa ..)
  • Reducir la tasa de fotogramas de la vista previa, por lo que no se verá abrumado con los almacenamientos intermedios
  • Ahora, para mostrar nuestros almacenamientos intermedios, podemos usar la funcionalidad predeterminada de dibujar mapas de bits o usar abrir para visualizar los almacenamientos intermedios. Pero hasta ahora no he usado ninguno, así que ni siquiera sé si es factible, ¿alguna idea sobre lo mismo?

ACTUALIZACIÓN
Revisando la documentación del SDK encontré esta API - setPreviewTexture esta API nos permite - "captura fotogramas de una secuencia de imágenes como una textura de OpenGL ES". Una vez que tenga las imágenes con la textura aplicada, puede usar OpenGL para mostrar sus marcos. (Eche un vistazo a la respuesta publicada por @Stephan sobre cómo hacer esto.)

NOTA - setPreviewTexture está disponible desde el nivel 11 de la API en adelante. SDK Link

+0

Creo que puedo ver a dónde vas. ¿Hay alguna manera de usar un 'SurfaceHolder' sin usar' SurfaceView'? Si usáramos eso para obtener datos de vista previa y un 'GLSurfaceView' optimizado para dibujar los cuadros procesados, tal vez podríamos lograr una velocidad de cuadros razonable. –

+2

Creo que podría haber resuelto esto - estaba revisando el documento de la cámara una vez más y encontré esto 'setPreviewTexture' esto nos permite" capturar cuadros de una secuencia de imágenes como una textura OpenGL ES ", creo que estas texturas OpenGL ES son la manera ir. De nuevo, podemos utilizar OpenGL para mostrar los marcos una vez que hayamos terminado con él. [SurfaceTexture] (http://developer.android.com/reference/android/graphics/SurfaceTexture.html) – bluefalcon

+0

¡Agradable! Eso es del nivel API 11, así que no lo vi en la documentación. Estoy buscando algo que funcione con el nivel 8 de la API, pero igual, por favor inclúyalo en tu respuesta, porque te otorgaré la recompensa si no hay otra alternativa. –

2

Ver this link, creo que es similar a lo que desea lograr.

+0

Supongo que eso responde mi pregunta sobre la visualización de almacenamientos intermedios usando opengl. ¡Gracias! +1 – bluefalcon

+0

si no funciona al principio, tenga cuidado con esta línea de código: 'this.setEGLConfigChooser (8, 8, 8, 8, 16, 0);' – Stephan

4

Otra opción es utilizar el marco OpenCV, que tiene un puerto de Android:

http://opencv.willowgarage.com/wiki/Android2.3.0

Es un puerto NDK del proyecto de código abierto abierto Computer Vision, y que va a tomar cuadros de vista preliminar primas y permita procesarlos con OpenCV antes de mostrarlos en un SurfaceView. Debido a que manipula los fotogramas, no se ejecuta a la misma velocidad de cuadro que la que se enganchó directamente en la vista previa optimizada por hardware, pero como gran parte es nativa, hace un trabajo bastante bueno.

Hay una aplicación OpenCV_Sample en esa versión vinculada anteriormente que se compiló en una aplicación de demostración que puede hacer mucho de lo que está buscando. Tiene opciones de menú para habilitar el inverso, desenfocar la imagen o hacer detección de bordes en el área de vista previa. Incluso si no es exactamente lo que quieres, hay algunas muestras geniales en el código fuente para aprender.

+0

¡El enlace está roto! – acrespo