Risoluzione dei problemi

Percorso del file binario Python mancante

Il messaggio di errore:

ERROR: An error occurred during the fetch of repository 'local_execution_config_python':
  Traceback (most recent call last):
       File "/sandbox_path/external/org_tensorflow/third_party/py/python_configure.bzl", line 208
               get_python_bin(repository_ctx)
    ...
Repository command failed

di solito indica che Bazel non riesce a trovare il file binario Python locale. Per risolvere questo problema, individua innanzitutto la posizione del file binario di Python, quindi aggiungi --action_env PYTHON_BIN_PATH=<path to python binary> al comando Bazel. Ad esempio, puoi passare all'utilizzo del file binario python3 predefinito di sistema con il seguente comando:

bazel build -c opt \
  --define MEDIAPIPE_DISABLE_GPU=1 \
  --action_env PYTHON_BIN_PATH=$(which python3) \
  mediapipe/examples/desktop/hello_world

Pacchetti Python necessari mancanti

Il messaggio di errore:

ImportError: No module named numpy
Is numpy installed?

in genere indica che alcuni pacchetti Python non sono installati. Esegui pip install o pip3 install a seconda della versione binaria di Python per installare i pacchetti.

Impossibile recuperare i repository delle dipendenze remote

Il messaggio di errore:

ERROR: An error occurred during the fetch of repository 'org_tensorflow':
   java.io.IOException: Error downloading [https://mirror.bazel.build/github.com/tensorflow/tensorflow/archive/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz, https://github.com/tensorflow/tensorflow/archive/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz] to /sandbox_path/external/org_tensorflow/77e9ffb9b2bfb1a4f7056e62d84039626923e328.tar.gz: Tried to reconnect at offset 9,944,151 but server didn't support it

or

WARNING: Download from https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/rules_swift/releases/download/0.12.1/rules_swift.0.12.1.tar.gz failed: class java.net.ConnectException Connection timed out (Connection timed out)

in genere indica che Bazel non riesce a scaricare i repository delle dipendenze necessarie per MediaPipe. MediaPipe ha diversi repository di dipendenze ospitati da siti Google. In alcune regioni, potrebbe essere necessario configurare un proxy di rete o utilizzare una VPN per accedere a queste risorse. Potrebbe anche essere necessario aggiungere --host_jvm_args "-DsocksProxyHost=<ip address> -DsocksProxyPort=<port number>" al comando Bazel. Per maggiori dettagli, consulta questo problema GitHub.

Se ritieni che non si tratti di un problema di rete, un'altra possibilità è che alcune risorse potrebbero essere temporaneamente non disponibili. Esegui bazel clean --expunge e riprova più tardi. Se il problema persiste, segnala un problema su GitHub con il messaggio di errore dettagliato.

Configurazione errata di OpenCV di MediaPipe

Il messaggio di errore:

error: undefined reference to 'cv::String::deallocate()'
error: undefined reference to 'cv::String::allocate(unsigned long)'
error: undefined reference to 'cv::VideoCapture::VideoCapture(cv::String const&)'
...
error: undefined reference to 'cv::putText(cv::InputOutputArray const&, cv::String const&, cv::Point, int, double, cv::Scalar, int, int, bool)'

in genere indica che OpenCV non è configurato correttamente per MediaPipe. Consulta le sezioni "Installa OpenCV e FFmpeg" in Installazione per scoprire come modificare i file WORKSPACE e linux_opencv/macos_opencv/windows_opencv.BUILD di MediaPipe per le librerie opencv locali. Anche questa segnalazione di GitHub può esserti utile.

Errore di installazione di pip per Python

Il messaggio di errore:

ERROR: Could not find a version that satisfies the requirement mediapipe
ERROR: No matching distribution found for mediapipe

dopo l'esecuzione di pip install mediapipe in genere indica che non è presente MediaPipe Python qualificato per il tuo sistema. Tieni presente che MediaPipe Python PyPI supporta ufficialmente la versione a 64 bit di Python da 3.7 a 3.10 sui seguenti sistemi operativi:

  • Linux x86_64
  • x86_64 macOS 10.15 o versioni successive
  • Windows amd64

Se il sistema operativo è attualmente supportato e continui a visualizzare questo errore, assicurati che sia il codice Python sia il codice pip siano per Python 3.7-3.10. In caso contrario, prendi in considerazione la possibilità di compilare il pacchetto Python MediaPipe in locale seguendo le istruzioni riportate qui.

Errore di caricamento della DLL di Python su Windows

Il messaggio di errore:

ImportError: DLL load failed: The specified module could not be found

di solito indica che nel sistema Windows locale mancano i pacchetti di Visual C++ riedistribuibili e/o le DLL di runtime di Visual C++. Il problema può essere risolto installando il file ufficiale vc_redist.x64.exe o il pacchetto Python "msvc-runtime" eseguendo

$ python -m pip install msvc-runtime

Tieni presente che il pacchetto Python "msvc-runtime" non viene rilasciato o gestito da Microsoft.

Metodo nativo non trovato

Il messaggio di errore:

java.lang.UnsatisfiedLinkError: No implementation found for void com.google.wick.Wick.nativeWick

in genere indica che una libreria nativa necessaria, ad esempio /libwickjni.so, non è stata caricata o non è stata inclusa nelle dipendenze dell'app o non può essere trovata per qualche motivo. Tieni presente che Java richiede che ogni libreria nativa venga caricata esplicitamente utilizzando la funzione System.loadLibrary.

Nessun calcolatore registrato trovato

Il messaggio di errore:

No registered object with name: OurNewCalculator; Unable to find Calculator "OurNewCalculator"

in genere indica che a OurNewCalculator viene fatto riferimento per nome in un CalculatorGraphConfig, ma che la destinazione della libreria per OurNewCalculator non è stata collegata al file binario dell'applicazione. Quando si aggiunge una nuova calcolatrice al grafico, questa deve essere aggiunta anche come dipendenza della build delle applicazioni che utilizzano il grafico della calcolatrice.

Questo errore viene rilevato in fase di runtime perché i grafici del calcolatore fanno riferimento ai calcolatori per nome tramite il campo CalculatorGraphConfig::Node:calculator. Quando la libreria di una calcolatrice è collegata a un file binario dell'applicazione, la calcolatrice viene registrata automaticamente per nome tramite la macro REGISTER_CALCULATOR utilizzando la libreria registration.h. Tieni presente che REGISTER_CALCULATOR può registrare una calcolatrice con un prefisso dello spazio dei nomi, identico allo spazio dei nomi C++. In questo caso, anche il grafico del calcolatore deve utilizzare lo stesso prefisso dello spazio dei nomi.

Errore di memoria insufficiente

L'esaurimento della memoria può essere un sintomo di un numero eccessivo di pacchetti che si accumulano all'interno di un gráfo MediaPipe in esecuzione. Questo può accadere per diversi motivi, ad esempio:

  1. Alcuni calcolatori nel grafico non riescono semplicemente a tenere il passo con l'arrivo di pacchetti da uno stream di input in tempo reale, ad esempio una videocamera.
  2. Alcune calcolatrici sono in attesa di pacchetti che non arriveranno mai.

Per il problema (1), potrebbe essere necessario eliminare alcuni pacchetti meno recenti per elaborare quelli più recenti. Per alcuni suggerimenti, consulta: How to process realtime input streams.

Per il problema (2), è possibile che uno stream di input manchi di pacchetti per qualche motivo. Un dispositivo o una calcolatrice potrebbe essere configurato in modo errato o produrre pacchetti solo sporadicamente. Ciò può causare l'attesa di molti calcolatori a valle per molti pacchetti che non arriveranno mai, il che a sua volta causa l'accumulo di pacchetti su alcuni dei loro stream di input. MediaPipe risolve questo tipo di problema utilizzando "limiti di timestamp". Per alcuni suggerimenti, consulta: How to process realtime input streams.

L'impostazione MediaPipe CalculatorGraphConfig::max_queue_size limita il numero di pacchetti in coda su qualsiasi stream di input regolando gli input al grafico. Per gli stream di input in tempo reale, il numero di pacchetti in coda in uno stream di input dovrebbe essere quasi sempre pari a zero o uno. In caso contrario, potresti visualizzare il seguente messaggio di avviso:

Resolved a deadlock by increasing max_queue_size of input stream

Inoltre, l'impostazione CalculatorGraphConfig::report_deadlock può essere impostata in modo da causare il fallimento dell'esecuzione del grafico e mostrare il deadlock come errore, in modo che max_queue_size agisca come limite di utilizzo della memoria.

Blocchi del grafico

Molte applicazioni chiameranno CalculatorGraph::CloseAllPacketSources e CalculatorGraph::WaitUntilDone per terminare o sospendere l'esecuzione di un grafo MediaPipe. L'obiettivo è consentire a eventuali calcolatori o pacchetti in attesa di completare l'elaborazione e poi di arrestare il grafico. Se tutto va bene, ogni stream nel grafico raggiungerà Timestamp::Done e ogni calcolatrice raggiungerà CalculatorBase::Close, quindi CalculatorGraph::WaitUntilDone verrà completato correttamente.

Se alcuni calcolatori o stream non riescono a raggiungere lo stato Timestamp::Done o CalculatorBase::Close, è possibile chiamare il metodo CalculatorGraph::Cancel per interrompere l'esecuzione del grafico senza attendere il completamento di tutti i calcolatori e i pacchetti in attesa.

La temporizzazione dell'output non è uniforme

Alcuni grafici MediaPipe in tempo reale producono una serie di frame video da visualizzare come effetto video o come diagnostica video. A volte, un grafo MediaPipe produce questi frame in cluster, ad esempio quando diversi frame di output vengono estrapolati dallo stesso cluster di frame di input. Se gli output vengono presentati man mano che vengono prodotti, alcuni frame di output vengono sostituiti immediatamente da quelli successivi nello stesso cluster, il che rende difficile vedere e valutare i risultati visivamente. In questi casi, la visualizzazione dell'output può essere migliorata presentando i frame a intervalli regolari in tempo reale.

MediaPipe risolve questo caso d'uso mappando i timestamp ai punti in tempo reale. Ogni timestamp indica un'ora in microsecondi e un calcolatore come LiveClockSyncCalculator può ritardare l'output dei pacchetti in modo che corrispondano ai relativi timestamp. Questo tipo di calcolatrice regola la temporizzazione delle uscite in modo che:

  1. Il tempo tra le uscite corrisponde al tempo tra i timestamp il più possibile.
  2. Le uscite vengono prodotte con il ritardo più breve possibile.

CalculatorGraph non segue gli input

Per molti grafici MediaPipe in tempo reale, la latenza ridotta è un obiettivo. MediaPipe supporta l'elaborazione parallela in stile "pipeline" per iniziare l'elaborazione di ogni pacchetto il prima possibile. In genere, la latenza più bassa possibile è il tempo totale richiesto da ogni calcolatore lungo un "percorso critico" di calcolatori successivi. La latenza di un grafico MediaPipe potrebbe essere peggiore di quella ideale a causa dei ritardi introdotti per visualizzare i frame a intervalli regolari come descritto in La temporizzazione dell'output non è uniforme.

Se alcuni dei calcolatori nel grafico non riescono a tenere il passo con gli stream di input in tempo reale, la latenza continuerà ad aumentare e sarà necessario eliminare alcuni pacchetti di input. La tecnica consigliata è utilizzare i calcolatori MediaPipe progettati appositamente per questo scopo, come FlowLimiterCalculator, come descritto in How to process realtime input streams.

Monitora gli input del calcolatore e i calcoli dei timestamp

Il debug dei calcolatori MediaPipe spesso richiede una conoscenza approfondita del flusso di dati e della sincronizzazione dei timestamp. I pacchetti in arrivo ai calcolatori vengono prima memorizzati nella coda di input per ogni stream in modo da essere sincronizzati dal InputStreamHandler assegnato. Il compito del job InputStreamHandler è determinare il set di pacchetti di input per un timestamp stabilito, che mette la calcolatrice in stato "pronta", seguito dall'attivazione di una chiamata Calculator::Process con il set di pacchetti determinato come input.

DebugInputStreamHandler può essere utilizzato per monitorare i pacchetti in entrata e i calcoli dei timestamp in tempo reale nell'output LOG(INFO) dell'applicazione. Può essere assegnata a calcolatori specifici tramite input_stream_handler del calcolatore o al grafico a livello globale tramite il campo input_stream_handler di CalculatorGraphConfig.

Durante l'esecuzione del grafico, i pacchetti in arrivo generano messaggi LOG che rivelano il timestamp e il tipo di pacchetto, seguito dallo stato corrente di tutte le code di input:

[INFO] SomeCalculator: Adding packet (ts:2, type:int) to stream INPUT_B:0:input_b
[INFO] SomeCalculator: INPUT_A:0:input_a num_packets: 0 min_ts: 2
[INFO] SomeCalculator: INPUT_B:0:input_b num_packets: 1 min_ts: 2

Inoltre, consente il monitoraggio degli eventi di regolamento del timestamp (se viene applicato DefaultInputStreamHandler). In questo modo è possibile rilevare un aumento inaspettato del limite di timestamp negli stream di input che genera una chiamata Calculator::Process con un insieme di input incompleto che genera pacchetti vuoti negli stream di input (potenzialmente richiesti).

Scenario di esempio:

node {
  calculator: "SomeCalculator"
  input_stream: "INPUT_A:a"
  input_stream: "INPUT_B:b"
  ...
}

Dato un calcolatore con due input, riceve un pacchetto in entrata con timestamp 1 sullo stream A seguito da un pacchetto di input con timestamp 2 sullo stream B. L'aumento del limite del timestamp a 2 nello stream B con un pacchetto di input in attesa nello stream A al timestamp 1 attiva la chiamata Calculator::Process con un insieme di input incompleto per il timestamp 1. In questo caso, DefaultInputStreamHandler restituisce:

[INFO] SomeCalculator: Filled input set at ts: 1 with MISSING packets in input streams: INPUT_B:0:input_b.

I vlog sono tuoi amici

MediaPipe utilizza VLOG in molti punti per registrare eventi importanti a scopo di debugging, senza influire sulle prestazioni se la registrazione non è attivata.

Scopri di più su VLOG su abseil VLOG

Tieni presente che VLOG può essere considerato spam se lo attivi a livello globale, ad esempio utilizzando il flag --v. Il flag --vmodule della soluzione che consente di impostare livelli diversi per diversi file di origine.

Nei casi in cui non è possibile utilizzare --v / --vmodule (ad es. quando viene eseguita un'app per Android), MediaPipe consente di impostare sostituzioni di flag VLOG --v / --vmodule per scopi di debug, che vengono applicate quando viene creato CalculatorGraph.

Sostituzioni:

  • MEDIAPIPE_VLOG_V: definisci e fornisci il valore che offri per --v
  • MEDIAPIPE_VLOG_VMODULE: definisci e offri il valore che offri per --vmodule

Puoi impostare le sostituzioni aggiungendo: --copt=-DMEDIAPIPE_VLOG_VMODULE=\"*calculator*=5\"

con i pattern dei moduli e i livelli VLOG che preferisci (vedi maggiori dettagli su VLOG in abseil VLOG) al comando di compilazione.--vmodule

IMPORTANTE: tieni presente che l'aggiunta del codice precedente al comando di compilazione attiverà la ricostruzione dell'intero file binario, incluse le dipendenze. Pertanto, poiché le sostituzioni VLOG esistono solo per scopi di debug, è più veloce modificare semplicemente vlog_overrides.cc aggiungendo MEDIAPIPE_VLOG_V/VMODULE in alto.

Flag non supportati durante la compilazione

Se utilizzi Clang 18 o versioni precedenti, potresti dover disattivare alcune ottimizzazioni del compilatore nel nostro backend della CPU.

Per disattivare il supporto di avxvnniint8, aggiungi quanto segue a .bazelrc:

build --define=xnn_enable_avxvnniint8=false