Brak ścieżki pliku binarnego Pythona
Komunikat o błędzie:
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
zwykle oznacza, że Bazel nie może znaleźć lokalnego pliku binarnego Pythona. Aby rozwiązać ten problem, najpierw znajdź, gdzie znajduje się plik binarne Pythona, a następnie dodaj --action_env PYTHON_BIN_PATH=<path to python binary>
do polecenia Bazel. Możesz na przykład przełączyć się na domyślny binarny plik python3 za pomocą tego polecenia:
bazel build -c opt \
--define MEDIAPIPE_DISABLE_GPU=1 \
--action_env PYTHON_BIN_PATH=$(which python3) \
mediapipe/examples/desktop/hello_world
Brak wymaganych pakietów Pythona
Komunikat o błędzie:
ImportError: No module named numpy
Is numpy installed?
zwykle oznacza, że niektóre pakiety Pythona nie są zainstalowane. Aby zainstalować te pakiety, uruchom polecenie pip install
lub pip3 install
w zależności od wersji binarnej Pythona.
Nie udało się pobrać zdalnych repozytoriów zależności
Komunikat o błędzie:
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)
zwykle oznacza, że Bazel nie może pobrać niezbędnych repozytoriów zależności, których potrzebuje MediaPipe. MediaPipe ma kilka repozytoriów zależności hostowanych przez witryny Google. W niektórych regionach konieczne może być skonfigurowanie serwera proxy sieci lub użycie sieci VPN, aby uzyskać dostęp do tych zasobów. Może być też konieczne dodanie --host_jvm_args "-DsocksProxyHost=<ip address> -DsocksProxyPort=<port number>"
do polecenia Bazel. Więcej informacji znajdziesz w tym wątku na GitHub.
Jeśli uważasz, że problem nie dotyczy sieci, możliwe, że niektóre zasoby są tymczasowo niedostępne. Uruchom bazel clean --expunge
i spróbuj ponownie później. Jeśli problem nadal występuje, prześlij zgłoszenie na GitHub, dołączając szczegółowy komunikat o błędzie.
Nieprawidłowa konfiguracja MediaPipe OpenCV
Komunikat o błędzie:
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)'
zwykle oznacza, że OpenCV nie jest prawidłowo skonfigurowany pod kątem MediaPipe. Zapoznaj się z sekcjami „Instalowanie OpenCV i FFmpeg” w Instalacji, aby dowiedzieć się, jak zmodyfikować pliki WORKSPACE i linux_opencv/macos_opencv/windows_opencv.BUILD MediaPipe w przypadku lokalnych bibliotek opencv. Ten problem na GitHubie może Ci też pomóc.
Nie udało się zainstalować pakietu Python pip
Komunikat o błędzie:
ERROR: Could not find a version that satisfies the requirement mediapipe
ERROR: No matching distribution found for mediapipe
Po uruchomieniu pip install mediapipe
zwykle oznacza to, że w Twoim systemie nie ma kwalifikowanego pakietu MediaPipe Python. Pamiętaj, że MediaPipe Python PyPI oficjalnie obsługuje 64-bitową wersję Pythona 3.7–3.10 w następujących systemach operacyjnych:
- x86_64 Linux
- x86_64 macOS 10.15 lub nowszy
- amd64 Windows
Jeśli system operacyjny jest obecnie obsługiwany, a błąd nadal występuje, sprawdź, czy zarówno Python, jak i plik binarny pip są przeznaczone dla wersji Python 3.7–3.10. W przeciwnym razie rozważ skompilowanie pakietu MediaPipe na potrzeby Pythona lokalnie, postępując zgodnie z instrukcjami podanymi tutaj.
Nie udało się wczytać biblioteki DLL Pythona w systemie Windows
Komunikat o błędzie:
ImportError: DLL load failed: The specified module could not be found
zwykle oznacza, że w lokalnym systemie Windows brakuje pakietów do rozpowszechniania Visual C++ lub bibliotek DLL środowiska wykonawczego Visual C++. Aby rozwiązać ten problem, zainstaluj oficjalny pakiet vc_redist.x64.exe lub zainstaluj pakiet Pythona „msvc-runtime”, uruchamiając
$ python -m pip install msvc-runtime
Pamiętaj, że pakiet Python „msvc-runtime” nie jest wydawany ani obsługiwany przez firmę Microsoft.
Nie znaleziono metody natywnej
Komunikat o błędzie:
java.lang.UnsatisfiedLinkError: No implementation found for void com.google.wick.Wick.nativeWick
zwykle oznacza, że wymagana biblioteka natywna, np. /libwickjni.so
, nie została załadowana lub nie została uwzględniona w zależnościach aplikacji albo z jakiegoś powodu nie można jej znaleźć. Pamiętaj, że Java wymaga jawnego wczytania każdej natywnej biblioteki za pomocą funkcji System.loadLibrary
.
Nie znaleziono zarejestrowanego kalkulatora
Komunikat o błędzie:
No registered object with name: OurNewCalculator; Unable to find Calculator "OurNewCalculator"
zwykle oznacza, że OurNewCalculator
jest wywoływany z nazwy w CalculatorGraphConfig
, ale biblioteka docelowa OurNewCalculator nie została połączona z binarnym plikiem aplikacji. Gdy do grafu kalkulatora dodasz nowy kalkulator, musisz go też dodać jako zależność kompilacji aplikacji korzystających z tego grafu.
Ten błąd jest wykrywany w czasie wykonywania, ponieważ wykresy kalkulatora odwołują się do kalkulatorów po nazwie za pomocą pola CalculatorGraphConfig::Node:calculator
.
Gdy biblioteka kalkulatora jest połączona z binarnym plikiem aplikacji, kalkulator jest automatycznie rejestrowany według nazwy za pomocą makra REGISTER_CALCULATOR
, które korzysta z biblioteki registration.h
. Pamiętaj, że REGISTER_CALCULATOR
może zarejestrować kalkulator z prefiksem przestrzeni nazw identycznym z przestrzenią nazw C++. W takim przypadku graf kalkulatora musi też używać tego samego prefiksu przestrzeni nazw.
Błąd „brak pamięci”
Wyczerpywanie pamięci może być objawem zbyt dużej liczby pakietów gromadzących się w bieżącym grafie MediaPipe. Może się tak zdarzyć z kilku powodów, np.:
- Niektóre kalkulatory na wykresie po prostu nie nadążają za przybyciem pakietów z potoku danych wejściowych w czasie rzeczywistym, np. z kamery wideo.
- Niektóre kalkulatory czekają na pakiety, które nigdy nie dotrą.
W przypadku problemu 1 może być konieczne odrzucenie niektórych starszych pakietów w celu przetworzenia nowszych pakietów. Wskazówki:
How to process realtime input streams
.
W przypadku problemu (2) może się zdarzyć, że jeden strumień wejściowy z jakiegoś powodu nie zawiera pakietów. Urządzenie lub kalkulator mogą być źle skonfigurowane lub generować pakiety sporadycznie. Może to spowodować, że kalkulatory na dalszych etapach będą czekać na wiele pakietów, które nigdy nie dotrą do celu, co z kolei spowoduje gromadzenie się pakietów w niektórych strumieniach danych wejściowych. MediaPipe rozwiązuje tego typu problemy, używając „granic sygnatury czasowej”. Wskazówki:
How to process realtime input streams
Ustawienie MediaPipe CalculatorGraphConfig::max_queue_size
ogranicza liczbę pakietów ustawianych w kolejce w dowolnym strumieniu wejściowym, ograniczając w ten sposób dane wejściowe do grafu. W przypadku strumieni danych wejściowych w czasie rzeczywistym liczba pakietów oczekujących w kolejce strumienia wejściowego powinna prawie zawsze wynosić 0 lub 1. W przeciwnym razie może wyświetlić się taki komunikat:
Resolved a deadlock by increasing max_queue_size of input stream
Możesz też ustawić wartość parametru CalculatorGraphConfig::report_deadlock
, aby spowodować niepowodzenie wykonania wykresu i wyświetlenie blokady jako błędu, tak aby parametr max_queue_size działał jako limit wykorzystania pamięci.
Zawieszanie się wykresu
Wiele aplikacji wywołuje funkcję CalculatorGraph::CloseAllPacketSources
i CalculatorGraph::WaitUntilDone
, aby zakończyć lub zawiesić wykonywanie grafu MediaPipe. Celem jest umożliwienie ukończenia przetwarzania wszystkich oczekujących kalkulatorów lub pakietów, a następnie wyłączenie wykresu. Jeśli wszystko pójdzie zgodnie z planem, każdy przepływ na wykresie osiągnie wartość Timestamp::Done
, a każdy kalkulator osiągnie wartość CalculatorBase::Close
, a potem CalculatorGraph::WaitUntilDone
zostanie ukończony.
Jeśli niektóre kalkulatory lub strumienie nie mogą osiągnąć stanu Timestamp::Done
lub CalculatorBase::Close
, można wywołać metodę CalculatorGraph::Cancel
, aby zakończyć wykonywanie wykresu bez oczekiwania na zakończenie pracy wszystkich oczekujących kalkulatorów i pakietów.
Nierównomierne wygaszanie
Niektóre wykresy MediaPipe w czasie rzeczywistym generują serię klatek wideo, które można wyświetlić jako efekt wideo lub diagnostykę wideo. Czasami wykres MediaPipe wygeneruje te klatki w klastrach, na przykład gdy kilka klatek wyjściowych zostanie ekstrapolowanych z tego samego klastra klatek wejściowych. Jeśli wyniki są prezentowane w miarę ich generowania, niektóre ramki wyjściowe są natychmiast zastępowane późniejszymi ramkami w tym samym klastrze, co utrudnia ich wizualne sprawdzanie i ocenianie. W takich przypadkach wizualizację wyjściową można ulepszyć, prezentując klatki w równych odstępach w czasie rzeczywistym.
MediaPipe realizuje to zastosowanie, mapując sygnatury czasowe na punkty w czasie rzeczywistym.
Każda sygnatura czasowa wskazuje czas w mikrosekundach, a kalkulator, taki jak LiveClockSyncCalculator
, może opóźnić generowanie pakietów, aby pasowały one do ich sygnatur czasowych. Ten rodzaj kalkulatora dostosowuje czas generowania danych wyjściowych w taki sposób, aby:
- Czas między wyjściami odpowiada jak najbliżej czasowi między sygnaturami czasowymi.
- Dane wyjściowe są generowane z najmniejszym możliwym opóźnieniem.
CalculatorGraph nie nadąża za danymi wejściowymi
W przypadku wielu wykresów MediaPipe w czasie rzeczywistym celem jest krótkie opóźnienie. MediaPipe obsługuje równoległe przetwarzanie typu „pipeline”, aby jak najszybciej rozpocząć przetwarzanie każdego pakietu. Zwykle najniższa możliwa wartość opóźnienia to łączny czas potrzebny na wykonanie każdego z kalkulatorów na „ścieżce krytycznej” kolejnych kalkulatorów. Opóźnienie wykresu MediaPipe może być większe niż optymalne z powodu opóźnień wprowadzanych w ramkach wyświetlania w równych odstępach czasowych, jak opisano w sekcji Czas trwania wyjścia jest nierówny.
Jeśli niektóre z kalkulatorów na wykresie nie nadążają za strumieniami danych wejściowych w czasie rzeczywistym, opóźnienie będzie się zwiększać, a w konsekwencji konieczne będzie odrzucenie niektórych pakietów danych wejściowych. Zalecamy użycie kalkulatorów MediaPipe, które zostały zaprojektowane specjalnie do tego celu, np. FlowLimiterCalculator
, zgodnie z opisem w How to process realtime input streams
.
Monitorowanie danych wejściowych kalkulatora i rozliczeń z dodatkiem sygnatury czasowej
Debugowanie kalkulatorów MediaPipe często wymaga dogłębnego zrozumienia przepływu danych i synchronizacji sygnatur czasowych. Przychodzące pakiety do kalkulatorów są najpierw buforowane w kolejkach wejściowych na potrzeby poszczególnych strumieni, aby mogły zostać zsynchronizowane przez przypisany InputStreamHandler
. Zadaniem zadania InputStreamHandler
jest określenie zestawu pakietów wejściowych dla ustalonego sygnatury czasowej, co powoduje przejście kalkulatora w stan „gotowy”. Następnie kalkulator wywołuje funkcję Calculator::Process, podając jako argument określony zestaw pakietów.
Za pomocą polecenia DebugInputStreamHandler
możesz śledzić przychodzące pakiety i rozliczenia z nazwami w czasie rzeczywistym w wyjściu LOG(INFO) aplikacji. Można go przypisać do konkretnych kalkulatorów za pomocą pola input_stream_handler w kalkulatorze lub globalnie za pomocą pola input_stream_handler w elementach CalculatorGraphConfig
.
Podczas wykonywania grafu przychodzące pakiety generują komunikaty LOG, które zawierają sygnaturę czasową i typ pakietu, a także bieżący stan wszystkich kolejek wejściowych:
[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
Umożliwia też monitorowanie zdarzeń rozliczenia sygnatury czasowej (jeśli jest stosowana).DefaultInputStreamHandler
Może to pomóc w ujawnienia nieoczekiwanego zwiększenia limitu sygnatury czasowej w strumieniach danych wejściowych, co powoduje wywołanie Calculator::Process z niekompletnym zbiorem danych wejściowych, co z kolei powoduje puste pakiety w (potencjalnie wymaganych) strumieniach danych wejściowych.
Przykładowy scenariusz:
node {
calculator: "SomeCalculator"
input_stream: "INPUT_A:a"
input_stream: "INPUT_B:b"
...
}
Kalkulator z 2 wejściami otrzymuje pakiet przychodzący z oznaczeniem czasowym 1 w strumieniu A, a potem pakiet wejściowy z oznaczeniem czasowym 2 w strumieniu B.
Ograniczenie sygnatury czasowej zwiększone do 2 w strumieniu B z oczekującym pakietem danych wejściowych w strumieniu A w sygnaturze czasowej 1 powoduje wywołanie Calculator::Process z niepełnym zbiorem danych wejściowych dla sygnatury czasowej 1. W tym przypadku DefaultInputStreamHandler
zwraca:
[INFO] SomeCalculator: Filled input set at ts: 1 with MISSING packets in input streams: INPUT_B:0:input_b.
VLOG to Twój przyjaciel
MediaPipe używa funkcji VLOG
w wielu miejscach do rejestrowania ważnych zdarzeń na potrzeby debugowania, nie wpływając na wydajność, jeśli rejestrowanie nie jest włączone.
Dowiedz się więcej o VLOG
na stronie abseil VLOG
Pamiętaj, że VLOG
może generować spam, jeśli włączysz go globalnie (np. za pomocą flagi --v
). Rozwiązanie --vmodule
– flaga umożliwiająca ustawienie różnych poziomów dla różnych plików źródłowych.
W przypadku, gdy nie można użyć flagi --v
/ --vmodule
(np.podczas uruchamiania aplikacji na Androida), MediaPipe umożliwia ustawienie zastąpień flagi VLOG
--v
/ --vmodule
na potrzeby debugowania. Zastąpienia te są stosowane podczas tworzenia CalculatorGraph
.
Zastąpienia:
MEDIAPIPE_VLOG_V
: zdefiniuj i podaj wartość atrybutu--v
.MEDIAPIPE_VLOG_VMODULE
: zdefiniuj i podaj wartość, którą chcesz podać w polu--vmodule
.
Możesz ustawić zastąpienia, dodając:--copt=-DMEDIAPIPE_VLOG_VMODULE=\"*calculator*=5\"
z właściwymi wzorami modułów i poziomami VLOG
(więcej informacji o --vmodule
znajdziesz w abseil VLOG
) do polecenia kompilacji.
WAŻNE: dodanie tych opcji do polecenia kompilacji spowoduje odtworzenie całego binarnego pliku, w tym zależności. Ponieważ zastąpienia VLOG
istnieją tylko na potrzeby debugowania, szybciej jest po prostu zmodyfikować vlog_overrides.cc
, dodając MEDIAPIPE_VLOG_V/VMODULE
na samym szczycie.
Nieobsługiwane flagi podczas kompilacji
Jeśli używasz Clang 18 lub starszej wersji, konieczne może być wyłączenie niektórych optymalizacji kompilatora w naszym backendzie procesora.
Aby wyłączyć obsługę avxvnniint8
, dodaj do .bazelrc
te informacje:
build --define=xnn_enable_avxvnniint8=false