2015-05-07 10 views
14

Sto utilizzando Android4OpenCV per eseguire l'elaborazione di immagini dal vivo e mi piacerebbe utilizzare la più piccola risoluzione che la fotocamera possa offrire. La risoluzione predefinita è la più grande che la fotocamera possa offrire.Android4OpenCV: risoluzione dell'impostazione all'avvio

Sto guardando il 3rd example, che consente all'utente di modificare le risoluzioni tramite un menu. Mi piacerebbe modificare quell'esempio per cambiare la risoluzione all'avvio invece di richiedere all'utente di passare attraverso il menu. Per fare questo, ho semplicemente aggiungere due righe alla funzione altrimenti vuoto onCameraViewStarted():

public void onCameraViewStarted(int width, int height) { 
    android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1); 
    mOpenCvCameraView.setResolution(res); 
} 

E la cosa è, questo funziona perfettamente bene sul mio Galaxy Nexus, sistema operativo Android 4.2.2. L'app si avvia e la risoluzione è impostata correttamente.

Tuttavia, quando eseguo la stessa identica app su un tablet Nexus 7, con Android 5.1, l'app si blocca sulla chiamata a setResolution(). In realtà funziona una volta sola, ma poi si blocca la seconda volta che provi a eseguirlo, anche se esci completamente dall'app, rimuovila dalle app in esecuzione o riavvia il dispositivo. Anche altri utenti riportano lo stesso errore, quindi non è solo il dispositivo Nexus 7, infatti il ​​mio Galaxy Nexus sembra essere l'unico dispositivo in cui funziona.

In particolare, l'applicazione va in funzione setResolution(), che poi chiama org.opencv.android.JavaCameraView.disconnectCamera(), che assomiglia a questo:

(Nota: questo codice è interno alla biblioteca OpenCV4Android, questo non è il mio codice)

protected void disconnectCamera() { 
    /* 1. We need to stop thread which updating the frames 
    * 2. Stop camera and release it 
    */ 
    Log.d(TAG, "Disconnecting from camera"); 
    try { 
     mStopThread = true; 
     Log.d(TAG, "Notify thread"); 
     synchronized (this) { 
      this.notify(); 
     } 
     Log.d(TAG, "Wating for thread"); 
     if (mThread != null) 
      mThread.join(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } finally { 
     mThread = null; 
    } 

    /* Now release camera */ 
    releaseCamera(); 
} 

Guardando i registri, vedo che il filo si blocca sulla linea synchronized(this). L'unica altra cosa che consente di sincronizzare su tale oggetto è l'interno JavaCameraView.CameraWorker classe, che è la variabile mThread nel codice di cui sopra, ha iniziato dalla classe JavaCameraView:

(Nota: questo codice è interno alla biblioteca OpenCV4Android, questo è non il mio codice)

private class CameraWorker implements Runnable { 

    public void run() { 
     do { 
      synchronized (JavaCameraView.this) { 
       try { 
        JavaCameraView.this.wait(); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 

      if (!mStopThread) { 
       if (!mFrameChain[mChainIdx].empty()) 
        deliverAndDrawFrame(mCameraFrame[mChainIdx]); 
       mChainIdx = 1 - mChainIdx; 
      } 
     } while (!mStopThread); 
     Log.d(TAG, "Finish processing thread"); 
    } 
} 

ho provato futzing con quel codice, cambiando il notify() per notifyAll(), e il mantenimento di un elenco di fili CameraWorker e unirsi ciascuno. Ma non importa quale, l'app si blocca ancora alla chiamata disconnectCamera().

Le mie domande sono:

  • Come posso modificare il terzo esempio OpenCV4Android in modo che la sua risoluzione è impostata all'avvio?

  • Che cosa sta causando l'interruzione dell'app?

  • Perché funziona su alcuni dispositivi ma non su altri?

Edit: non ho ricevuto commenti o risposte, così ho crosspost al forum OpenCV here.

Edit 2: Come da suggerimento di Cyriel, ho provato a impostare la risoluzione dopo alcuni fotogrammi sono passati:

int frames = 0; 
public Mat onCameraFrame(CvCameraViewFrame inputFrame) { 

    frames++; 

    if(frames == 6){ 
     android.hardware.Camera.Size res = mOpenCvCameraView.getResolutionList().get(mOpenCvCameraView.getResolutionList().size()-1); 
     mOpenCvCameraView.setResolution(res); 

    } 

    return inputFrame.rgba(); 
} 

Tuttavia, ora questo rimane incastrato nello stesso luogo esatto, anche sul mio Galaxy Nexus, che funziona se si imposta la risoluzione nella funzione onCameraViewStarted(). Ho provato ad aumentare il numero di fotogrammi a 7 e anche a 100, ma mi blocco sempre nello stesso posto.

risposta

5

La domanda più importante nella tua situazione è se funziona se non modifichi affatto il codice - sei in grado di modificare la risoluzione (tramite menu) senza arrestare l'app?
Se la risposta è più probabile è semplice - è lo stesso bug in OpenCV come nella versione di Windows: prima di cambiare la risoluzione della fotocamera o i fps (e molto probabilmente qualsiasi proprietà) è necessario afferrarne almeno uno (usare 3-5 per essere sicuro) frame prima di cambiare questa proprietà.
Se non molto probabilmente non c'è nulla che tu possa fare da solo: riempi la segnalazione di bug e attendi i commenti. L'unica alternativa è usare un'altra libreria per afferrare fotogrammi dalla fotocamera e convertirla in oggetto OpenCV.

+0

Funziona davvero se non lo modifichi affatto. Ho anche provato a cambiare la risoluzione sul primo fotogramma e il risultato è lo stesso. –

+0

Quindi molto probabilmente è lo stesso bug di Windows. Prova a cambiare la risoluzione dopo 5 fotogrammi - gli utenti probabilmente non se ne accorgeranno nemmeno. So che non è una soluzione perfetta, ma molto probabilmente è la soluzione migliore. – cyriel

+0

Ho modificato la mia domanda per mostrare cosa succede quando provo questo, ma questo non sembra risolvere il problema. –