Edge AI w praktyce: jak uruchomić modele sztucznej inteligencji na Raspberry Pi krok po kroku

0
80
Rate this post

Z tego artykuły dowiesz się:

Po co w ogóle bawić się w Edge AI na Raspberry Pi

Edge AI a klasyczne AI w chmurze

Edge AI oznacza uruchamianie modeli sztucznej inteligencji bezpośrednio na urządzeniu „na krawędzi” sieci – w tym przypadku na Raspberry Pi – zamiast wysyłać dane do serwera w chmurze. Różnica wydaje się subtelna, ale w praktyce przekłada się na kilka kluczowych parametrów projektu.

Przy przetwarzaniu w chmurze każda klatka obrazu, każda próbka dźwięku czy każde zapytanie tekstowe musi dotrzeć do serwera, zostać tam przetworzona i wrócić z wynikiem. To kosztuje czas (latencja), transfer i pieniądze (abonamenty, usługi chmurowe), a do tego wymaga stabilnego połączenia internetowego. Przy Edge AI na Raspberry Pi większość tego procesu dzieje się lokalnie – dane często nie wychodzą poza dom czy biuro.

Daje to kilka istotnych korzyści:

  • niższa latencja – reakcja w milisekundach zamiast dziesiątek lub setek milisekund;
  • większa prywatność – obraz z kamery czy nagranie głosu nie muszą opuszczać sieci lokalnej;
  • praca offline – system działa nawet przy słabym lub zerowym internecie;
  • stałe koszty – brak niespodzianek z rachunkiem za chmurę czy transfer.

To dlatego Edge AI dobrze sprawdza się w monitoringu wideo, inteligentnych czujnikach czy prostych asystentach głosowych. Model jest „bliżej” danych, reaguje szybciej i nie wymaga stałego podłączenia do dużej infrastruktury.

Dlaczego Raspberry Pi to dobry start dla Edge AI

Raspberry Pi bywa niedoceniane, bo z wyglądu przypomina zabawkę lub typową „płytkę do nauki programowania”. W praktyce to pełnoprawny komputer z procesorem ARM, portami USB, HDMI i złączem kamery, który w wersjach 4 i 5 radzi sobie z lekkimi modelami AI całkiem sprawnie.

Najważniejsze powody, dla których Raspberry Pi jest świetnym poligonem dla Edge AI:

  • niska cena w porównaniu z klasycznym PC lub gotowymi bramkami IoT;
  • ogromna społeczność – tysiące tutoriali, repozytoriów, gotowych projektów;
  • duża liczba akcesoriów – kamery, mikrofony, moduły NPU, obudowy, HAT-y;
  • elastyczny system – można zainstalować Raspberry Pi OS, Ubuntu czy wyspecjalizowane dystrybucje;
  • skalowalność – od prostego proof-of-concept po małą flotę urządzeń w firmie.

Do prostych zadań, takich jak detekcja ruchu, klasyfikacja kilku klas obiektów czy prosty asystent głosowy offline, wystarczy jedna płytka i podstawowe akcesoria. Z czasem można dodać akcelerator TPU, dysk SSD lub dodatkowe moduły komunikacyjne, jeśli projekt tego wymaga.

Jeśli wcześniej pojawiało się myślenie w stylu „AI to tylko chmura i potężne GPU”, Raspberry Pi pomaga zmienić perspektywę: da się zrobić bardzo wiele na małym, tanim sprzęcie, o ile odpowiednio przygotuje się modele i oprogramowanie.

Typowe obawy: czy Pi nie jest za słabe i czy dam sobie radę

Dwie obawy padają niemal zawsze: „czy Raspberry Pi nie jest za słabe do AI?” oraz „czy to nie jest za trudne dla kogoś, kto nie jest programistą?”. Obie są zrozumiałe, ale w praktyce problemy są mniejsze, niż się wydaje.

Moc obliczeniowa Raspberry Pi jest ograniczona w porównaniu z laptopem z GPU, jednak nowoczesne modele pod edge – jak MobileNet, EfficientNet-Lite czy TinyYOLO – są projektowane właśnie z myślą o takim sprzęcie. Do tego dochodzi optymalizacja modeli pod edge: kwantyzacja, pruning, distillation. W wielu zastosowaniach wystarczy kilka–kilkanaście klatek na sekundę, a nie 60 FPS jak w grach.

Przykładowe zastosowania Edge AI na Raspberry Pi

Jednym z najprostszych, a jednocześnie bardzo użytecznych projektów jest domowy monitoring z detekcją ruchu lub rozpoznawaniem obiektów. Kamera podłączona do Raspberry Pi może analizować klatki, wykrywać człowieka, zwierzęta czy samochód i lokalnie podejmować decyzje, czy wysłać powiadomienie.

Inny zestaw przykładów:

  • klasyfikacja dźwięków – rozpoznawanie dzwonka do drzwi, alarmu, głośnego krzyku czy konkretnego słowa wybudzającego („hotword”);
  • asystent głosowy offline – proste komendy typu „włącz światło w kuchni”, „podnieś temperaturę” bez wysyłania nagrań do chmury;
  • liczenie obiektów – np. aut przejeżdżających przez określony punkt, ludzi wchodzących do sklepu, produktów na taśmie;
  • analiza prostych anomalii na podstawie danych z czujników (wibracje, temperatura, dźwięk) dla małego monitoringu maszyn.

Wiele z tych projektów można zaczynać od wersji „demo” i stopniowo rozbudowywać. Najważniejsze to mieć działający przepływ: dane → preprocessing → model → decyzja, a następnie dodawać kolejne klocki – web API, logowanie, integracje z innymi systemami.

Proof-of-concept kontra system „na lata”

Raspberry Pi znakomicie nadaje się do proof-of-concept – sprawdzenia, czy dana idea ma sens. W tej fazie wystarczy prosta instalacja, podstawowy zasilacz, otwarta płytka leżąca na biurku i skrypt Pythona. To sposób, aby przetestować różne modele, ustawić pipeline i „poczuć”, ile mocy faktycznie potrzebuje projekt.

Jeżeli jednak celem jest system, który ma działać miesiącami bez dotykania, trzeba zwrócić uwagę na dodatkowe aspekty:

  • stabilne zasilanie – dobry zasilacz, czasem UPS lub zasilanie z szafy elektrycznej;
  • chłodzenie i obudowa – radiatory, wentylator, obudowa odporna na kurz i temperaturę otoczenia;
  • nośnik danych – lepiej SSD niż karta SD, która w trybie 24/7 potrafi paść szybciej;
  • aktualizacje i monitoring – mechanizm aktualizacji oprogramowania, zbieranie logów, watchdog.

Różnica między prototypem a produktem nie polega jedynie na tym, czy model działa, ale także na tym, jak zachowuje się w dłuższym okresie: czy „wiesza” system, jak reaguje na brak internetu, przerwy w zasilaniu i nietypowe dane wejściowe.

Dobór Raspberry Pi i akcesoriów pod sztuczną inteligencję

Raspberry Pi 3, 4 i 5 – co je różni z punktu widzenia AI

Na rynku wciąż krąży sporo egzemplarzy Raspberry Pi 3, natomiast do zastosowań AI zdecydowanie lepiej wypadają modele 4 i 5. Różnią się liczbą rdzeni, taktowaniem, ilością RAM i wydajnością I/O, co bezpośrednio wpływa na to, jak szybko będzie działał model.

Jeśli chodzi o trudność techniczną, większość kroków da się powtórzyć „z terminala” na zasadzie kopiuj–wklej, a społeczność Raspberry Pi dostarczyła już wiele gotowych przykładów. Przydatne jest podstawowe obycie z Linuxem i Pythonem, ale nie jest wymagany dyplom informatyka. Dobrze sprawdzają się konkretne, ustrukturyzowane przewodniki, podobne do tych, które znajdziesz w serwisach oferujących praktyczne wskazówki: Informatyka – krok po kroku, bez zbędnego żargonu.

ModelCPURAM (typowe warianty)Przeznaczenie w kontekście AI
Raspberry Pi 34x ~1.2 GHz1 GBProste modele, pojedyncze procesy, demo
Raspberry Pi 44x ~1.5 GHz2–8 GBWiększość projektów edge AI, kilka usług równolegle
Raspberry Pi 54x ~2.4 GHz4–8 GBBardziej wymagające modele, wyższe FPS, akceleratory

Na Raspberry Pi 3 uruchomisz TensorFlow Lite i prostą detekcję lub klasyfikację obrazów, ale komfort pracy jest ograniczony. Raspberry Pi 4 to obecnie najbardziej opłacalny wybór: w wersji 4 GB RAM pozwala uruchomić kilka usług jednocześnie (model, API, prosty interfejs webowy). Raspberry Pi 5 daje wyraźnego „kopa” wydajnościowego, co przekłada się na większą liczbę klatek na sekundę przy użyciu tego samego modelu.

Co realnie da się zrobić na Pi 3, a gdzie zaczyna się Pi 4/5

Na Raspberry Pi 3 sensownie działa:

  • prosta klasyfikacja obrazów – np. rozpoznawanie kilku–kilkunastu klas obiektów;
  • detekcja ruchu z wykorzystaniem prostszych algorytmów lub lekkich modeli;
  • klasyfikacja dźwięków na małych spectrogramach;
  • niewielkie modele NLP dla krótkich komend.

Przy Raspberry Pi 4 zakres rozszerza się znacząco: można uruchomić lekkie wyszukiwarki wektorowe, systemy rozpoznawania twarzy (np. FaceNet w wersji zoptymalizowanej) czy bardziej zaawansowaną detekcję obiektów z kamery w czasie zbliżonym do rzeczywistego. Raspberry Pi 5 dodatkowo usprawnia zadania wymagające intensywnej pracy CPU i szybkiej komunikacji z akceleratorami.

Jeżeli startujesz od zera, masz ograniczony budżet i nie planujesz ciężkich modeli, Pi 4 jest złotym środkiem. Pi 3 warto rozważyć tylko wtedy, gdy już go masz i chcesz nauczyć się koncepcji, licząc się z ograniczeniami wydajności.

Akcesoria: zasilanie, chłodzenie, obudowa, pamięć

Dobrze przygotowane środowisko sprzętowe oszczędzi sporo nerwów. Najważniejsze elementy do AI na Raspberry Pi:

  • zasilacz – oryginalny lub sprawdzony odpowiednik, odpowiednio mocny (3A dla Pi 4, dla Pi 5 często więcej);
  • chłodzenie – radiatory + mały wentylator lub obudowa z aktywnym chłodzeniem; model podczas inferencji potrafi grzać procesor mocniej niż typowe zastosowania;
  • nośnik danych – karta microSD klasy A1/A2 jako minimum, najlepiej jednak dysk SSD na USB 3.0, szczególnie jeśli logujesz dużo danych lub instalujesz cięższe biblioteki;
  • obudowa – nie tylko ze względów estetycznych, ale także ochrony przed kurzem i przypadkowym zwarciem.

Do projektów z obrazem przyda się moduł kamery (oficjalny Raspberry Pi Camera Module lub kamera USB kompatybilna z UVC). Do analizy dźwięku – mikrofon USB lub HAT audio z wejściem mikrofonowym. Dostępność akcesoriów to jedna z największych zalet platformy.

Akceleratory sprzętowe: TPU, NPU i inne dodatki

Raspberry Pi samo w sobie poradzi sobie z lekkimi modelami, ale jeśli zależy na większej wydajności lub niższym zużyciu CPU, dobrym krokiem jest dołożenie akceleratora AI. Najpopularniejszym wyborem jest Google Coral USB Accelerator z układem Edge TPU.

Do tego dochodzą:

  • różne HAT-y z wbudowanymi NPU (np. moduły oparte na układach Movidius, Rockchip NPU);
  • moduły PCIe dla Raspberry Pi 5 (gdy potrzebny jest wyższy transfer danych);
  • akceleratory zgodne z ONNX Runtime lub OpenVINO.

Ich konfiguracja bywa bardziej wymagająca niż instalacja samego Raspberry Pi OS, ale różnica w wydajności jest znaczna. Na Edge TPU lekki model detekcji obiektów potrafi działać wielokrotnie szybciej, podczas gdy CPU pozostaje w dużej mierze wolny, co umożliwia obsługę dodatkowych zadań (logika, interfejs, komunikacja).

Przykładowe konfiguracje startowe

Dla początkujących dobrze sprawdzają się dwie konfiguracje:

  • Budżetowa: Raspberry Pi 4 (2 GB), karta microSD 32–64 GB, prosty radiator, kamera USB, mikrofon USB. Nadaje się do nauki i prostych dem.
  • „Komfortowa”: Raspberry Pi 4 lub 5 (4–8 GB), dysk SSD na USB 3.0, obudowa z wentylatorem, oficjalna kamera, dobry mikrofon USB, ewentualnie Coral USB Accelerator.

Pierwsza wersja wystarczy, żeby przejść pełny cykl: od instalacji systemu, przez przygotowanie modelu, po prototyp aplikacji. Druga zapewnia margines bezpieczeństwa pod kątem wydajności, liczby równoległych procesów i żywotności nośnika danych.

Przygotowanie systemu Raspberry Pi do projektów Edge AI

Wybór systemu: Raspberry Pi OS czy Ubuntu

Raspberry Pi OS – plusy, minusy i kiedy wystarczy

Do większości projektów Edge AI wystarczy domyślny Raspberry Pi OS (64-bit). Ma dobre wsparcie społeczności, gotowe pakiety i dokumentację dotyczącą pracy z kamerą, GPIO czy akcesoriami AI. Dla wielu osób to najprostsza droga: im mniej egzotyki w systemie, tym mniej zaskoczeń przy instalacji frameworków.

Dobrą praktyką jest wybranie wariantu „Lite”, jeśli Pi będzie pracowało jako „klocek” infrastruktury (bez środowiska graficznego), albo „with desktop”, jeśli planujesz lokalny podgląd z kamery, okna debugowe itp. Środowisko graficzne przydaje się na etapie prototypu, ale później często znika na rzecz wydajności i stabilności.

Pod kątem AI najczęściej działa następujący zestaw:

  • Raspberry Pi OS 64-bit (stable),
  • Python 3.11+ zainstalowany z repozytoriów,
  • podstawowe biblioteki: python3-venv, git, build-essential, cmake.

Taka konfiguracja wystarczy, aby ruszyć z TensorFlow Lite, ONNX Runtime czy OpenCV. Jeśli pojawią się niestandardowe potrzeby (np. konkretna wersja CUDA na innym SBC), dopiero wtedy ma sens rozważanie bardziej specjalistycznych dystrybucji.

Ubuntu Server na Raspberry Pi – kiedy ma przewagę

Na Raspberry Pi 4/5 można też użyć Ubuntu Server 64-bit. Wybierany bywa wtedy, gdy:

  • cała reszta infrastruktury działa na Ubuntu i chcesz mieć ten sam ekosystem narzędzi,
  • planujesz używać narzędzi do konteneryzacji (Docker, Kubernetes) w sposób zbliżony do środowiska serwerowego,
  • masz gotowe instrukcje lub skrypty pod Ubuntu i zależy ci na ich ponownym wykorzystaniu.

Drobna różnica, ale istotna: w Ubuntu część paczek AI (np. konkretne wersje ONNX Runtime, PyTorch dla ARM) bywa dostępna szybciej albo w bardziej aktualnej wersji niż w Raspberry Pi OS. Z drugiej strony, konfiguracja kamery czy akceleratorów bywa minimalnie trudniejsza, bo sporo tutoriali jest pisanych pod Raspberry Pi OS.

Podstawowa twarda konfiguracja systemu

Po pierwszym uruchomieniu dobrze od razu:

  • zmienić hasło użytkownika pi (lub utworzyć własnego użytkownika),
  • włączyć SSH, jeśli planujesz zdalne logowanie (sudo raspi-config → Interfacing Options → SSH),
  • ustawić strefę czasową i lokalizację, aby logi i cron miały sensowne daty,
  • zrobić pełną aktualizację pakietów:
    sudo apt update
    sudo apt full-upgrade -y
    sudo reboot

Przy projektach AI dobrze od razu zadbać o miejsce na dysku. Pojedynczy model, kilka bibliotek i logi potrafią szybko „zjeść” kartę 16 GB, zwłaszcza jeśli równolegle eksperymentujesz z kilkoma wersjami środowiska.

Wirtualne środowiska Pythona i podstawowe narzędzia

Z czasem na Pi ląduje wiele bibliotek. Bez izolacji łatwo wpaść w „dependency hell”. Proste wirtualne środowiska Pythona rozwiązują większość problemów:

sudo apt install -y python3-venv python3-pip git
mkdir -p ~/ai-projects && cd ~/ai-projects
python3 -m venv venv-ai
source venv-ai/bin/activate
pip install --upgrade pip

Na tym etapie można dodać podstawowy zestaw narzędzi, który przyda się niemal w każdym projekcie:

pip install numpy pillow opencv-python-headless 
            matplotlib jupyterlab

Zamiast instalować wszystko globalnie w systemie, wystarczy aktywować venv-ai przy pracy nad danym projektem. Jeśli pojawi się konflikt wersji, tworzysz osobne środowisko i nie wprowadzasz bałaganu w całym systemie.

Konfiguracja kamery i audio

W projektach Edge AI na Raspberry Pi bardzo często pojawia się kamera lub mikrofon. Dobrze je skonfigurować zanim zaczniesz walczyć z modelem – łatwiej wtedy diagnozować, czy problem leży po stronie danych, czy AI.

Dla oficjalnego modułu kamery w Raspberry Pi OS:

  • w Raspberry Pi > 4 używany jest podsystem libcamera,
  • włączenie interfejsu odbywa się przez sudo raspi-config → Interfacing Options → Camera (w nowszych systemach opcja dotyczy ogólnie interfejsów).

Prosty test kamery z linii komend:

libcamera-still -o test.jpg
libcamera-vid -t 5000 -o test.h264

Jeśli korzystasz z kamery USB zgodnej z UVC, możesz sprawdzić jej obecność:

ls /dev/video*
v4l2-ctl --all

Dla audio (mikrofon USB) przydatne są:

arecord -l      # lista urządzeń nagrywających
aplay -l        # lista urządzeń odtwarzających

Prosty test nagrania:

arecord -D plughw:1,0 -f cd -d 5 test.wav
aplay test.wav

Jeżeli na tym etapie masz działający obraz i dźwięk, przejście do frameworków AI jest dużo spokojniejsze – od razu widzisz, czy model dobrze reaguje na rzeczywiste wejście.

Frameworki i narzędzia AI sensowne na Raspberry Pi

TensorFlow Lite – klasyk na edge

Najczęściej wybieranym frameworkiem na Raspberry Pi jest TensorFlow Lite (TFLite). Jego główne zalety to:

  • lekka biblioteka dopasowana do urządzeń o ograniczonych zasobach,
  • dobre wsparcie dla quantization (int8, float16),
  • gotowe przykłady pod Raspberry Pi, w tym obsługa Coral Edge TPU.

Instalacja bazowej wersji (dla CPU) w środowisku wirtualnym zwykle sprowadza się do:

pip install --extra-index-url https://google-coral.github.io/py-repo/ 
    tflite-runtime

ewentualnie do oficjalnego tensorflow dla ARM, jeśli naprawdę go potrzebujesz. Jednak dla inferencji na edge znacznie częściej wystarczy tflite-runtime – mniejsze wymagania, mniej zależności.

ONNX Runtime – elastyczność modeli

Jeżeli modele powstają w różnych frameworkach (PyTorch, TensorFlow, scikit-learn), dobrą strategią jest eksport do ONNX i użycie ONNX Runtime na Raspberry Pi. Daje to kilka korzyści:

  • jeden mechanizm wykonawczy dla różnych źródeł modeli,
  • możliwość korzystania z różnych backendów (CPU, czasem NPU/TPU przez dodatkowe rozszerzenia),
  • łatwiejsze przenoszenie modeli między edge a serwerem.

Instalacja ONNX Runtime (wersji ARM) wygląda najczęściej tak:

pip install onnxruntime

lub, dla nowszych wersji i optymalizacji:

pip install onnxruntime==<konkretna_wersja>

Potem wystarczy wczytać model:

import onnxruntime as ort

session = ort.InferenceSession("model.onnx", providers=["CPUExecutionProvider"])
outputs = session.run(None, {"input": input_array})

To podejście dobrze sprawdza się, jeśli nie chcesz przywiązywać się do jednego ekosystemu. Model trenujesz tam, gdzie wygodniej, a na Pi masz stosunkowo prosty runtime.

Jeśli interesują Cię konkrety i przykłady, rzuć okiem na: Jak przenieść WordPress do chmury bez utraty SEO i downtime.

PyTorch na Raspberry Pi – kiedy ma sens

Pełny PyTorch na Raspberry Pi działa, ale jest ciężki i nie zawsze wart zachodu. Często sens ma tylko wtedy, gdy:

  • koniecznie potrzebujesz specyficznych warstw lub zachowania modelu w trybie „pełnym”,
  • chcesz delikatnie „dostroić” model na samym urządzeniu (np. few-shot learning, proste „douczenie” z nowych danych).

W większości scenariuszy trening i ciężka obróbka dzieją się na mocniejszej maszynie (laptop, serwer z GPU), a na Raspberry Pi ląduje już wersja zoptymalizowana (TFLite / ONNX). Jeśli dopiero startujesz z Edge AI, PyTorch na Pi może niepotrzebnie skomplikować początki.

OpenCV i biblioteki pomocnicze

Przy projektach z wizją komputerową OpenCV jest niemal obowiązkowe. Na Raspberry Pi można użyć:

  • opencv-python-headless – lżejsza wersja, bez zależności GUI, wystarcza na serwer/edge,
  • lub zbudować OpenCV ze źródeł, gdy potrzebne są konkretne moduły (np. GStreamer, CUDA na innych SBC).

Instalacja bazowa:

pip install opencv-python-headless

Dodatkowo często przydają się:

  • imutils – wygodne helpery do skalowania, rotacji, rysowania,
  • scikit-image – bardziej zaawansowane przekształcenia obrazów.

W prostych projektach (np. klasyfikacja z kamery) OpenCV odpowiada za przechwycenie i przygotowanie klatki, a model TFLite/ONNX daje predykcję. To typowy duet.

Obsługa akceleratorów: Coral Edge TPU i NPU

Gdy na Raspberry Pi 4/5 zaczyna brakować mocy, kolejny krok to akcelerator, np. Google Coral USB Accelerator. Instalacja sprowadza się zwykle do:

echo "deb https://packages.cloud.google.com/apt coral-edgetpu-stable main" | 
  sudo tee /etc/apt/sources.list.d/coral-edgetpu.list

curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | 
  sudo apt-key add -

sudo apt update
sudo apt install libedgetpu1-std
pip install --extra-index-url https://google-coral.github.io/py-repo/ 
    pycoral

Pod Edge TPU używa się modeli TFLite w wersji skompilowanej specjalnym kompilatorem (edgetpu_compiler). Przykład użycia:

from pycoral.utils.edgetpu import make_interpreter
from pycoral.adapters.common import input_size
from pycoral.adapters import classify

interpreter = make_interpreter("model_edgetpu.tflite")
interpreter.allocate_tensors()
w, h = input_size(interpreter)

Pozostałe NPU i akceleratory (np. HAT-y oparte na Rockchip czy Movidius) zwykle mają własne SDK. Zasada pozostaje jednak ta sama: model musi zostać do nich dostosowany, a z Raspberry Pi komunikuje się przez USB/PCIe/I2C/SPI lub dedykowany sterownik.

Zbliżenie płytki Raspberry Pi z układami scalonymi i komponentami
Źródło: Pexels | Autor: Alessandro Oliverio

Skąd wziąć model i jak go przygotować do pracy na brzegu sieci

Gotowe modele kontra własne trenowanie

Na starcie często pojawia się obawa: „nie mam czasu, żeby trenować modele od zera”. Do pierwszych projektów wcale nie jest to konieczne. Można skorzystać z:

  • gotowych modeli (zoo modeli TensorFlow, PyTorch, ONNX Model Zoo),
  • modeli pretrenowanych i delikatnie je „przestroić” pod swoje dane (fine-tuning),
  • prostego uczenia klasyfikatora na wyjściu z gotowych embeddingów (np. z modelu wizji).

Dla wielu zastosowań edge (np. rozróżnienie kilku typów obiektów w magazynie) wystarczy model pretrenowany na ImageNet z drobnym dostrojeniem ostatnich warstw. Cały „ciężki” trening robisz na laptopie lub maszynie z GPU, a na Raspberry Pi ląduje już tylko finalna, skompresowana wersja.

Eksport modelu do TFLite

Jeżeli model powstał w TensorFlow/Keras, popularne jest konwertowanie go do TFLite. Ogólna procedura (na mocniejszej maszynie) wygląda następująco:

import tensorflow as tf

model = tf.keras.models.load_model("model.h5")

converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]

tflite_model = converter.convert()
with open("model.tflite", "wb") as f:
    f.write(tflite_model)

Plik model.tflite kopiujesz na Raspberry Pi (np. przez scp lub Git) i używasz z tflite-runtime. To podstawowa wersja, ale już sama opcja Optimize.DEFAULT potrafi znacznie zmniejszyć rozmiar modelu i przyspieszyć inferencję.

Quantization – klucz do wydajności na edge

Na Raspberry Pi często największy zysk daje zastosowanie kwantyzacji – reprezentacji wag i aktywacji w mniejszej precyzji (np. int8 zamiast float32). Dla TFLite można dodać:

converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_types = [tf.float16]

albo przeprowadzić pełną kwantyzację int8 z zestawem kalibracyjnym. Z mojego doświadczenia: dla prostych modeli klasyfikacyjnych spadek jakości jest niewielki, a zysk na szybkości i rozmiarze – bardzo odczuwalny. Dla bardziej skomplikowanych sieci (np. z dużą ilością warstw konwolucyjnych) dobrze jest to zweryfikować na swoim zbiorze testowym.

Do kompletu polecam jeszcze: Transfer learning w CV: jak trenować szybciej na mniejszych zbiorach — znajdziesz tam dodatkowe wskazówki.

Konwersja do ONNX

Konwersja modeli z PyTorch do ONNX

Jeśli model powstał w PyTorch, rozsądną drogą jest eksport do ONNX, a dopiero potem uruchamianie go na Raspberry Pi z ONNX Runtime. Taki model będzie łatwiej przenosić pomiędzy różnymi platformami. Przykładowy schemat (na maszynie deweloperskiej) wygląda tak:

import torch

model = ...  # Twój model PyTorch
model.load_state_dict(torch.load("model.pth", map_location="cpu"))
model.eval()

dummy_input = torch.randn(1, 3, 224, 224)  # dopasuj do swojego modelu

torch.onnx.export(
    model,
    dummy_input,
    "model.onnx",
    input_names=["input"],
    output_names=["output"],
    dynamic_axes={"input": {0: "batch_size"}, "output": {0: "batch_size"}},
    opset_version=13,
)

Tak przygotowany plik model.onnx można bezpośrednio wczytać na Raspberry Pi przez onnxruntime. Jeżeli zależy ci na jeszcze większej szybkości, da się później użyć narzędzi optymalizujących (np. onnxruntime-tools, onnx-simplifier) już po eksporcie.

Uproszczenie i przycinanie modeli

Na małym urządzeniu sens ma minimalizacja nie tylko rozmiaru pliku, ale też całej logiki sieci. W praktyce często:

  • usuwa się zbędne gałęzie (np. dodatkowe wyjścia do debugowania),
  • zmniejsza liczbę kanałów w warstwach konwolucyjnych (np. z 64 do 32),
  • redukuje liczbę warstw fully-connected,
  • przyjmuje niższą rozdzielczość wejścia (np. 160×160 zamiast 224×224).

Wiele osób boi się, że każde przycięcie drastycznie pogorszy jakość, tymczasem przy dobrze dobranym zadaniu (np. klasyfikacja kilku prostych klas) model może działać niemal tak samo dobrze. Najprostsza metoda to iteracyjne testy: tniesz model o krok, sprawdzasz jakość, i tak aż do zaakceptowania kompromisu.

Optymalizacje specyficzne dla Raspberry Pi

Przy konwersji warto spojrzeć nie tylko na liczby parametrów, ale też na to, jak model „układa się” pod ARM. Kilka praktycznych wskazówek:

  • używaj standardowych operacji (Conv2D, ReLU, MaxPool, MatMul), unikaj egzotycznych warstw – lepiej się mapują na ARM i TFLite,
  • kiedy to możliwe, wybieraj depthwise separable convolutions (MobileNet, EfficientNet-lite) zamiast masywnych konwolucji 3D,
  • spłaszczaj nadmiarowe operacje: zamiast kilku kroków przetwarzania, spróbuj połączyć je w jedną prostszą transformację.

Jeżeli korzystasz z gotowych architektur, takie jak MobileNetV2, MobileNetV3, EfficientNet-lite czy SqueezeNet zwykle „czują się” na Raspberry Pi dużo lepiej niż klasyczne ResNety.

Pierwszy działający przykład: klasyfikacja obrazu z kamery na Raspberry Pi

Założenia przykładowego projektu

Dobrym pierwszym krokiem jest konfiguracja prostego systemu, który:

  1. przechwytuje obraz z kamery (USB lub dedykowana kamera Raspberry Pi),
  2. przepuszcza każdą klatkę przez model TFLite,
  3. wyświetla etykietę przewidywanej klasy i pewność predykcji,
  4. działa w czasie zbliżonym do rzeczywistego (np. od kilku do kilkunastu FPSów).

Nie trzeba od razu budować skomplikowanego systemu detekcji. Prosta klasyfikacja typu „kot/pies/pusty kadr” pozwala przećwiczyć cały łańcuch: kamera → preprocessing → model → postprocessing → akcja.

Przygotowanie środowiska na Raspberry Pi

Zakładamy, że system jest już zaktualizowany, a Python i pip działają. Najpierw instalacja podstawowych paczek do wizji i inferencji:

python -m venv edgeai-env
source edgeai-env/bin/activate

pip install --upgrade pip
pip install tflite-runtime opencv-python-headless numpy

Jeśli korzystasz z kamery CSI (oficjalna kamera Raspberry Pi), upewnij się, że jest włączona w narzędziach konfiguracyjnych (raspi-config lub odpowiednik w Raspberry Pi OS), a w nowszych wersjach systemu – że działa stack libcamera. Przy kamerach USB zwykle wystarcza, że system je widzi jako urządzenie /dev/video0.

Pobranie przykładowego modelu i etykiet

Aby uniknąć uczenia od zera, można użyć gotowego modelu ImageNet w wersji TFLite, dostosowanego do edge. Przykładowo:

mkdir ~/edge-ai-demo
cd ~/edge-ai-demo

wget https://storage.googleapis.com/download.tensorflow.org/models/tflite_11_05_08/mobilenet_v1_1.0_224_quant.tflite 
     -O model.tflite

wget https://storage.googleapis.com/download.tensorflow.org/data/imagenet_labels.txt 
     -O labels.txt

Ten konkretny model jest skwantyzowany (uint8), więc dobrze nadaje się na Raspberry Pi. Plik labels.txt zawiera listę klas w takiej kolejności, jaką zwraca model.

Skrypt do klasyfikacji pojedynczego obrazu

Zanim przejdzie się do strumienia wideo, wygodnie jest sprawdzić model na jednym pliku graficznym. W katalogu z modelem utwórz plik classify_image.py:

import argparse
import numpy as np
import cv2
import tflite_runtime.interpreter as tflite

def load_labels(path):
    with open(path, "r", encoding="utf-8") as f:
        return [line.strip() for line in f.readlines()]

def preprocess_image(image_path, input_shape):
    img = cv2.imread(image_path)
    if img is None:
        raise RuntimeError(f"Nie mogę odczytać obrazu: {image_path}")
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    h, w = input_shape[1], input_shape[2]
    img = cv2.resize(img, (w, h))
    return img

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--model", default="model.tflite")
    parser.add_argument("--labels", default="labels.txt")
    parser.add_argument("image", help="Ścieżka do obrazu wejściowego")
    args = parser.parse_args()

    interpreter = tflite.Interpreter(model_path=args.model)
    interpreter.allocate_tensors()

    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()

    input_shape = input_details[0]["shape"]
    labels = load_labels(args.labels)

    img = preprocess_image(args.image, input_shape)

    input_data = np.expand_dims(img, axis=0)

    # obsługa modeli uint8 (quantized) vs float
    if input_details[0]["dtype"] == np.uint8:
        scale, zero_point = input_details[0]["quantization"]
        input_data = input_data / 255.0
        input_data = input_data / scale + zero_point
        input_data = input_data.astype(np.uint8)
    else:
        input_data = input_data.astype(np.float32) / 255.0

    interpreter.set_tensor(input_details[0]["index"], input_data)
    interpreter.invoke()

    output_data = interpreter.get_tensor(output_details[0]["index"])[0]

    if output_details[0]["dtype"] == np.uint8:
        scale, zero_point = output_details[0]["quantization"]
        output_data = scale * (output_data.astype(np.int32) - zero_point)

    top_k = output_data.argsort()[-5:][::-1]
    for i in top_k:
        print(f"{labels[i]}: {float(output_data[i]):.4f}")

if __name__ == "__main__":
    main()

Test uruchomienia:

python classify_image.py test.jpg

Jeśli wyświetlą się sensowne klasy i prawdopodobieństwa, model działa poprawnie, można więc przejść do kamery.

Klasyfikacja wideo z kamery w czasie rzeczywistym

Kolejny krok to przechwytywanie obrazu z kamery i przetwarzanie każdej klatki. Utwórz plik classify_camera.py:

import time
import numpy as np
import cv2
import tflite_runtime.interpreter as tflite

MODEL_PATH = "model.tflite"
LABELS_PATH = "labels.txt"
CAMERA_INDEX = 0  # /dev/video0

def load_labels(path):
    with open(path, "r", encoding="utf-8") as f:
        return [line.strip() for line in f.readlines()]

def main():
    labels = load_labels(LABELS_PATH)

    interpreter = tflite.Interpreter(model_path=MODEL_PATH)
    interpreter.allocate_tensors()

    input_details = interpreter.get_input_details()
    output_details = interpreter.get_output_details()
    input_shape = input_details[0]["shape"]
    input_height, input_width = input_shape[1], input_shape[2]

    cap = cv2.VideoCapture(CAMERA_INDEX)
    if not cap.isOpened():
        raise RuntimeError("Nie mogę otworzyć kamery")

    prev_time = time.time()
    fps = 0.0

    while True:
        ret, frame = cap.read()
        if not ret:
            print("Brak klatki z kamery, kończę.")
            break

        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        resized = cv2.resize(frame_rgb, (input_width, input_height))
        input_data = np.expand_dims(resized, axis=0)

        if input_details[0]["dtype"] == np.uint8:
            scale, zero_point = input_details[0]["quantization"]
            input_data = input_data / 255.0
            input_data = input_data / scale + zero_point
            input_data = input_data.astype(np.uint8)
        else:
            input_data = input_data.astype(np.float32) / 255.0

        interpreter.set_tensor(input_details[0]["index"], input_data)
        interpreter.invoke()

        output_data = interpreter.get_tensor(output_details[0]["index"])[0]
        if output_details[0]["dtype"] == np.uint8:
            scale, zero_point = output_details[0]["quantization"]
            output_data = scale * (output_data.astype(np.int32) - zero_point)

        top_index = int(np.argmax(output_data))
        top_label = labels[top_index] if top_index < len(labels) else "unknown"
        top_score = float(output_data[top_index])

        current_time = time.time()
        dt = current_time - prev_time
        prev_time = current_time
        fps = 0.9 * fps + 0.1 * (1.0 / dt) if dt > 0 else fps

        text = f"{top_label} ({top_score:.2f})  FPS: {fps:.1f}"
        cv2.putText(frame, text, (10, 30),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)

        cv2.imshow("Edge AI - klasyfikacja", frame)
        key = cv2.waitKey(1) & 0xFF
        if key == 27 or key == ord("q"):  # ESC lub q
            break

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

Uruchomienie:

python classify_camera.py

Na podglądzie z kamery w lewym górnym rogu pojawi się nazwa klasy oraz przybliżone FPS. Jeśli wszystko jest poprawnie skonfigurowane, Raspberry Pi 4 z takim modelem powinno osiągać kilka–kilkanaście klatek na sekundę.

Typowe problemy przy pierwszym uruchomieniu

Pierwsze podejście często kończy się jednym z kilku powtarzalnych błędów. Dobrze je znać, żeby nie utknąć na drobiazgach:

  • „Illegal instruction” przy imporcie TFLite – zwykle oznacza niekompatybilną binarkę z twoją wersją Raspberry Pi/OS; spróbuj innej wersji tflite-runtime albo oficjalnego tensorflow dla ARM.
  • „Cannot open camera” – sprawdź, czy kamera działa w innych aplikacjach (np. libcamera-hello, fswebcam), czy nie jest używana przez inny proces i czy masz poprawny indeks (0, 1 itd.).
  • Nieczytelny, „migający” obraz – czasem pomaga ustawienie rozdzielczości w VideoCapture:
    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)
  • Niska liczba FPS – zacznij od zmniejszenia rozdzielczości wejścia modelu lub przełącz tryb pracy na klasyfikację co N-tą klatkę, zamiast każdej.

Proste optymalizacje pętli inferencji

Jeżeli system już działa, ale widać, że Raspberry Pi jest na granicy wydajności, można go odciążyć kilkoma prostymi trikami:

  • pomijanie klatek – np. klasyfikacja co drugiej lub trzeciej klatki, a między nimi tylko odświeżanie obrazu,
  • zmniejszenie rozdzielczości kamery – nawet 320×240 potrafi być wystarczające przy prostych zadaniach,
  • standaryzacja rozmiaru okna – brak dynamicznej zmiany rozdzielczości potrafi ustabilizować pipeline.

W skrajnych przypadkach można rozważyć pipeline w dwóch procesach: jeden odpowiada za przechwytywanie i wstępne skalowanie obrazu, drugi tylko za inferencję. Komunikacja między nimi przez kolejkę (np. ZeroMQ, multiprocessing.Queue) pozwala lepiej wykorzystać wiele rdzeni.

Dostosowanie modelu do własnych klas

W pewnym momencie sam ImageNet przestaje wystarczać. Jeśli chcesz odróżniać na przykład konkretne produkty na półce lub typy narzędzi w warsztacie, przydaje się prosty fine-tuning:

  1. Na mocniejszej maszynie ładujesz pretrenowany model (np. MobileNetV2) z odciętą ostatnią warstwą.
  2. Doklejasz własną warstwę klasyfikującą do kilku nowych klas.
  3. Trenujesz tę ostatnią część na swoim zbiorze zdjęć (często wystarczy kilkadziesiąt-kilkaset przykładów na klasę).
  4. Eksportujesz do TFLite lub ONNX jak wcześniej.

Kluczowe Wnioski

  • Edge AI na Raspberry Pi przenosi przetwarzanie danych z chmury na lokalne urządzenie, dzięki czemu zyskujesz niższą latencję, większą prywatność, możliwość pracy offline i przewidywalne koszty bez opłat za transfer i usługi chmurowe.
  • Raspberry Pi, mimo niewielkich rozmiarów, jest pełnoprawnym komputerem z procesorem ARM i bogatym ekosystemem akcesoriów, który w wersjach 4 i 5 spokojnie radzi sobie z lekkimi modelami AI zaprojektowanymi pod edge.
  • Obawy, że „Pi jest za słabe” albo „trzeba być zawodowym programistą”, są zwykle przesadzone – dobrze dobrane modele (MobileNet, EfficientNet-Lite, TinyYOLO) i podstawowa znajomość Pythona wystarczą, żeby uzyskać kilka–kilkanaście klatek na sekundę w typowych zastosowaniach.
  • Raspberry Pi świetnie sprawdza się w praktycznych projektach: od domowego monitoringu z detekcją ruchu, przez rozpoznawanie dźwięków i prosty asystent głosowy offline, po liczenie obiektów i wykrywanie anomalii w danych z czujników.
  • Dobry start to prosty proof-of-concept: jedna płytka, podstawowy zasilacz, kamera lub mikrofon i skrypt, który realizuje pełny przepływ danych – od pobrania sygnału, przez preprocessing i model, po decyzję (np. wysłanie powiadomienia).
  • Jeśli projekt ma działać miesiącami bez nadzoru, trzeba zadbać nie tylko o model, ale też o „otoczkę produkcyjną”: stabilne zasilanie (często z UPS), chłodzenie i obudowę, trwały nośnik (SSD zamiast karty SD) oraz mechanizmy aktualizacji, logowania i monitoringu.
  • Opracowano na podstawie

  • Raspberry Pi 5 Product Brief. Raspberry Pi Ltd (2023) – Specyfikacja sprzętowa Raspberry Pi 5, CPU, RAM, I/O
  • Raspberry Pi 4 Model B Product Brief. Raspberry Pi Ltd (2019) – Oficjalne dane o wydajności, pamięci i zastosowaniach Pi 4
  • Edge AI: The Key to Scaling Enterprise AI. McKinsey & Company (2022) – Omówienie koncepcji Edge AI, latencji, kosztów i prywatności
  • TinyML: Machine Learning with TensorFlow Lite on Arduino and Ultra-Low-Power Microcontrollers. O’Reilly Media (2020) – Modele lekkie, kwantyzacja, projektowanie ML pod urządzenia brzegowe