L'analisi delle immagini
nel caso d'uso fornisca alla tua app un'immagine accessibile alla CPU su cui
eseguire l'elaborazione di immagini, la visione artificiale
o l'inferenza del machine learning. La
un'applicazione implementa
analyze()
che viene eseguito su ogni frame.
Per scoprire come integrare ML Kit di Google con l'app CameraX, consulta Strumento di analisi ML Kit.
Modalità operative
Quando la pipeline di analisi dell'applicazione non riesce a stare al passo con il frame di CameraX di frequenza effettiva, CameraX può essere configurata in modo da rilasciare fotogrammi in uno dei seguenti modi:
non-coding (predefinito): in questa modalità, l'esecutore memorizza sempre nella cache l'ultima immagine nel buffer (simile a una coda con profondità di 1) mentre l'applicazione analizza l'immagine precedente. Se FotocameraX riceve una nuova immagine prima che l'applicazione termini l'elaborazione, la nuova immagine viene salvata nello stesso buffer, sovrascrivendo quella precedente. Tieni presente che
ImageAnalysis.Builder.setImageQueueDepth()
non ha alcun effetto in questo scenario e i contenuti del buffer vengono sempre sovrascritti. Puoi attivare questa modalità non di blocco chiamandosetBackpressureStrategy()
conSTRATEGY_KEEP_ONLY_LATEST
Per ulteriori informazioni sulle implicazioni per gli esecutori, consulta il riferimento documentazione diSTRATEGY_KEEP_ONLY_LATEST
block: in questa modalità, l'esecutore interno può aggiungere più immagini alla coda delle immagini interna e inizia a eliminare i frame solo quando la coda pieno. Il blocco si verifica nell'intero ambito del dispositivo videocamera: se fotocamera ha più casi d'uso correlati, bloccato durante l'elaborazione di queste immagini da parte di CameraX. Per ad esempio, quando a un dispositivo Fotocamera sono associate sia l'analisi dell'anteprima che l'analisi delle immagini, allora l'anteprima verrà bloccata anche durante l'elaborazione delle immagini da parte di CameraX. Puoi abilitare la modalità di blocco passando
STRATEGY_BLOCK_PRODUCER
asetBackpressureStrategy()
. Puoi anche configurare la profondità della coda di immagini utilizzando ImageAnalysis.Builder.setImageQueueDepth().
Con un analizzatore a bassa latenza e ad alte prestazioni, in cui il tempo totale analizzare un'immagine è inferiore alla durata di un fotogramma di CameraX (16 ms per 60 fps, ad esempio), entrambe le modalità operative offrono una fluidità complessiva un'esperienza senza intervento manuale. La modalità di blocco può comunque essere utile in alcuni scenari, ad esempio quando si ha a che fare con tremolio del sistema molto brevi.
Con uno strumento ad alta latenza e prestazioni elevate, la modalità di blocco una coda più lunga per compensare la latenza. Tieni presente, tuttavia, che un'applicazione può comunque elaborare tutti i frame.
Con un analizzatore a latenza elevata e che richiede molto tempo (l'analizzatore non è in grado di elaborare frame), una modalità non di blocco potrebbe essere una scelta più appropriata, in quanto i frame devono essere eliminati per il percorso di analisi, ma altri casi d'uso associati in contemporanea possono comunque vedere tutti i frame.
Implementazione
Per utilizzare l'analisi delle immagini nella tua applicazione, segui questi passaggi:
- Crea una
ImageAnalysis
caso d'uso. - Crea un
ImageAnalysis.Analyzer
- Imposta lo strumento di analisi su
ImageAnalysis
. - Vincolo
proprietario del ciclo di vita, selettore della fotocamera e caso d'uso
ImageAnalysis
al ciclo di vita.
Subito dopo il binding, CameraX invia le immagini all'analizzatore registrato.
Dopo aver completato l'analisi, chiama
ImageAnalysis.clearAnalyzer()
oppure slegare il caso d'uso ImageAnalysis
per interrompere l'analisi.
Caso d'uso di Build ImageAnalysis
ImageAnalysis
si connette
analizzatore (un consumatore di immagini) a CameraX, che produce immagini.
Le applicazioni possono utilizzare
ImageAnalysis.Builder
per creare un oggetto ImageAnalysis
. Con ImageAnalysis.Builder
,
può configurare quanto segue:
- Parametri di output dell'immagine:
- Formato: CameraX supporta
YUV_420_888
eRGBA_8888
asetOutputImageFormat(int)
. Il formato predefinito èYUV_420_888
. - Risoluzione e Proporzioni: Puoi impostare uno di questi parametri, ma tieni presente che non puoi impostarli entrambi contemporaneamente.
- Rotazione.
- Nome destinazione: Utilizza questo parametro per il debug.
- Formato: CameraX supporta
- Controlli del flusso delle immagini:
Le applicazioni possono impostare la risoluzione o il formato, ma non
entrambi. La risoluzione esatta dell'output dipende dalle dimensioni richieste dall'applicazione
(o proporzioni) e hardware e potrebbe differire dalle richieste
dimensioni o proporzioni. Per informazioni sull'algoritmo di corrispondenza della risoluzione, consulta
la documentazione
setTargetResolution()
Un'applicazione può configurare i pixel dell'immagine di output in modo che siano in YUV (impostazione predefinita)
con spazi colore RGBA. Quando imposti un formato di output RGBA, CameraX internamente
converte le immagini dallo spazio colore YUV allo spazio colore RGBA e pacchettizza i bit delle immagini nel
ByteBuffer
del primo piano di ImageProxy (gli altri due piani non vengono utilizzati) con
la seguente sequenza:
ImageProxy.getPlanes()[0].buffer[0]: alpha
ImageProxy.getPlanes()[0].buffer[1]: red
ImageProxy.getPlanes()[0].buffer[2]: green
ImageProxy.getPlanes()[0].buffer[3]: blue
...
Quando si esegue un'analisi complicata di immagini in cui il dispositivo non può memorizzare aumenta con la frequenza fotogrammi, puoi configurare CameraX in modo da rimuovere fotogrammi le strategie descritte nella sezione Modalità operative di questo argomento.
Crea il tuo analizzatore
Le applicazioni possono creare analizzatori implementando
ImageAnalysis.Analyzer
ed eseguire l'override
analyze(ImageProxy image)
.
In ogni analizzatore, le applicazioni ricevono
ImageProxy
, che è un wrapper
per Media.Image.
È possibile eseguire query sul formato dell'immagine
ImageProxy.getFormat()
Il formato è uno dei seguenti valori che l'applicazione
fornisce i seguenti vantaggi: ImageAnalysis.Builder
:
ImageFormat.RGBA_8888
se l'app ha richiestoOUTPUT_IMAGE_FORMAT_RGBA_8888
.ImageFormat.YUV_420_888
se l'app ha richiestoOUTPUT_IMAGE_FORMAT_YUV_420_888
.
Consulta il caso d'uso di Build ImageAnalysis per le configurazioni dello spazio colore e dove è possibile recuperare i byte pixel.
All'interno di uno strumento di analisi, l'applicazione deve fare quanto segue:
- Analizza un determinato frame il più rapidamente possibile, preferibilmente all'interno un determinato limite di tempo di frequenza frame (ad esempio, inferiore a 32 ms per il caso a 30 f/s). Se l'applicazione non è in grado di analizzare un frame abbastanza velocemente, prendi in considerazione uno dei meccanismi di interruzione del frame supportati.
- Rilascia
ImageProxy
per CameraX chiamandoImageProxy.close()
Tieni presente che non devi chiamare la funzione di chiusura di Media.Image sottoposta a wrapping (Media.Image.close()
)
Le applicazioni possono utilizzare l'oggetto Media.Image
aggregato direttamente all'interno di ImageProxy.
Non chiamare Media.Image.close()
sull'immagine aggregata perché si romperebbe
il meccanismo di condivisione delle immagini all'interno di CameraX; usa invece
ImageProxy.close()
per rilasciare Media.Image
sottostante a CameraX.
Configura il tuo analizzatore per ImageAnalysis
Dopo aver creato uno strumento di analisi, utilizza
ImageAnalysis.setAnalyzer()
registrarlo per iniziare l'analisi. Al termine dell'analisi, utilizza
ImageAnalysis.clearAnalyzer()
per rimuovere lo strumento di analisi registrato.
È possibile configurare un solo analizzatore attivo per l'analisi delle immagini. Chiamata in corso
ImageAnalysis.setAnalyzer()
sostituisce lo strumento di analisi registrato, se è già
esiste già. Le applicazioni possono impostare un nuovo analizzatore in qualsiasi momento, prima o dopo l'associazione
caso d'uso.
Associa l'analisi delle immagini a un ciclo di vita
Ti consigliamo vivamente di associare ImageAnalysis
a un account esistente
Ciclo di vita di AndroidX con
ProcessCameraProvider.bindToLifecycle()
personalizzata. Tieni presente che la funzione bindToLifecycle()
restituisce la selezione
Camera
, che può essere usato
per regolare con precisione le impostazioni avanzate come l'esposizione e altre. Consulta questa guida per ulteriori informazioni sul controllo dell'output della videocamera.
L'esempio seguente combina tutti i passaggi precedenti, associando
Casi d'uso di CameraX ImageAnalysis
e Preview
per un proprietario di lifeCycle
:
Kotlin
val imageAnalysis = ImageAnalysis.Builder() // enable the following line if RGBA output is needed. // .setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build() imageAnalysis.setAnalyzer(executor, ImageAnalysis.Analyzer { imageProxy -> val rotationDegrees = imageProxy.imageInfo.rotationDegrees // insert your code here. ... // after done, release the ImageProxy object imageProxy.close() }) cameraProvider.bindToLifecycle(this as LifecycleOwner, cameraSelector, imageAnalysis, preview)
Java
ImageAnalysis imageAnalysis = new ImageAnalysis.Builder() // enable the following line if RGBA output is needed. //.setOutputImageFormat(ImageAnalysis.OUTPUT_IMAGE_FORMAT_RGBA_8888) .setTargetResolution(new Size(1280, 720)) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST) .build(); imageAnalysis.setAnalyzer(executor, new ImageAnalysis.Analyzer() { @Override public void analyze(@NonNull ImageProxy imageProxy) { int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees(); // insert your code here. ... // after done, release the ImageProxy object imageProxy.close(); } }); cameraProvider.bindToLifecycle((LifecycleOwner) this, cameraSelector, imageAnalysis, preview);
Risorse aggiuntive
Per saperne di più su CameraX, consulta le risorse aggiuntive che seguono.
Codelab
Esempio di codice