2011-06-23 5 views
6

Desidero creare un'applicazione Android che utilizzi la fotocamera e applichi i filtri di elaborazione delle immagini sui fotogrammi di anteprima.Android, manupulate i fotogrammi di anteprima della fotocamera

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);   
    } 
} 

Tuttavia, non vedo cambiamenti nella emulatore, non importa quello che faccio nel metodo onPreviewFrame.

+1

+1, mi chiedo anche se sia possibile manipolare direttamente i frame di anteprima. –

risposta

1

Beh, questo perché i buffer di anteprima che si ottengono nel callback sono solo una copia dei buffer di anteprima, quindi tutte le modifiche apportate non verranno visualizzate poiché il buffer che si ottiene è la copia. Menzionato nel SDK di Android here

io non sono sicuro di come fare questo, ma vi ho dato qualche pensiero su come andare su questo e qui è quello che penso dovrebbe essere fatto -

  • Registrati i buffer di anteprima
  • disattivare la visualizzazione di default anteprima
    • Se non si imposta la visualizzazione di anteprima per una superficie allora non dovrebbe ottenere qualsiasi display (ma non sono sicuro se funzionerà - aveva letto in qualche forum non in grado di richiamare la fonte)
    • Se quanto sopra non funziona, allora dovremo nascondere la vista (lo so difficilmente efficiente, ma non riuscivo a pensare ad altro ..)
  • Ridurre il framerate del anteprima, in modo da non sarà travolto dai buffer
  • Ora per visualizzare i nostri buffer, possiamo usare la funzionalità di default della bitmap o usare opengl per visualizzare i buffer. Ma fino ad ora non ho usato né così nemmeno so se è fattibile, qualche pensiero sullo stesso?

UPDATE
Rivisitare la documentazione SDK ho trovato questa API - setPreviewTexture questa API ci permette di - "cattura fotogrammi da un flusso di immagini come una texture OpenGL ES". Una volta che hai le immagini con la texture applicata puoi usare OpenGL per visualizzare i tuoi frame. (Dai un'occhiata alla risposta pubblicata da @Stephan su come farlo.)

NOTA - setPreviewTexture disponibile dal livello API 11 in poi!

+0

Penso di poter vedere dove stai andando. C'è un modo per usare un 'SurfaceHolder' senza usare un' SurfaceView'? Se usassimo quello per ottenere i dati di anteprima e un 'GLSurfaceView' ottimizzato per disegnare i frame elaborati, forse potremmo ottenere un frame rate ragionevole. –

+2

Penso che potrei averlo rotto - stavo passando attraverso la fotocamera doc ancora una volta e ho trovato questo 'setPreviewTexture' questo ci permette di" catturare fotogrammi da un flusso di immagini come una trama OpenGL ES ", penso che le trame OpenGL ES siano il modo andare. Ancora una volta possiamo usare l'opengl per visualizzare i frame una volta che abbiamo finito con esso. [SurfaceTexture] (http://developer.android.com/reference/android/graphics/SurfaceTexture.html) – bluefalcon

+0

Bello! Quella roba è dal livello API 11, quindi non l'ho visto nella documentazione. Sto cercando qualcosa che funzioni con l'API di livello 8, ma ancora, per favore includilo nella tua risposta, perché ti assegnerò la taglia se non c'è un'alternativa. –

2

Vedere this link, penso che sia simile a ciò che si desidera ottenere.

+0

Immagino che risponda alla mia domanda sulla visualizzazione dei buffer usando opengl. Grazie! +1 – bluefalcon

+0

se inizialmente non funziona, fai attenzione a questa riga di codice: 'this.setEGLConfigChooser (8, 8, 8, 8, 16, 0);' – Stephan

4

Un'altra opzione è quella di utilizzare il framework OpenCV, che dispone di una porta Android:

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

Si tratta di una porta NDK del progetto Open Computer Vision open source, e ci vorrà fotogrammi di anteprima prime e consentire l'elaborazione con OpenCV prima di visualizzarli su SurfaceView. Poiché manipola i fotogrammi, non viene eseguito con lo stesso framerate di un'anteprima dell'hardware ottimizzata direttamente, ma poiché gran parte di esso è nativo, svolge un ottimo lavoro.

C'è un'app OpenCV_Sample in quella versione collegata sopra che è stata compilata in un'app demo che può fare molto di quello che stai cercando. Ha opzioni di menu per abilitare l'inverso, sfocare l'immagine o eseguire il rilevamento dei bordi nell'area di anteprima. Anche se non è esattamente quello che vuoi, ci sono alcuni grandi esempi nel codice sorgente da cui imparare.

+0

Il collegamento è interrotto! – acrespo