Vogelspotter
Het Raspberry Pi idee was tamelijk eenvoudig: een (Pi) camera gebruiken om vogels te detecteren.
Een Pi camera kost ongeveer 30 EUR. De voordelen: het ding is superklein/plat en er is geen externe voeding nodig. Ik heb voor dit project uiteindelijk een externe webcam gebruikt. Dat vereist dan wel het gebruik van een USB hub met voeding.
Ik begon met het downloaden van de laatste versie van Raspbian OS (“bookworm”). Dat leverde uiteindelijk teveel probelemen op (in deze versie is bijv “libcamera” vervangen door “rpicam”, maar daarvoor bestaan (nog) bar weinig ondersteuning en voorbeelden). Ik ben ook begonnen met het zoeken naar een standaard oplossing, maar die gebruiken ‘Docker’, wat een vracht aan extra problemen opleverde.
Ik ben dus overgestapt op de “bullseye” versie met een Python programma. Die combinatie krijgt de webcam zonder problemen aan de praat. Het video beeld streamen naar een website is ook een eitje.
Op zoek naar beeldherkenning liep ik al vlot aan tegen “Bird recognition with Google Coral“. Wow! Zo’n ding snel besteld en toen was er snel resultaat:

Ik heb inmiddels een CSV met Nederlandse vogelnamen, en dan herkennen wij dit als een Pimpelmees!
(Gelukkig wordt de autoband Ara uit Bonaire genegeerd)
Het programma is een video stream mbv Flask, met een overlay met soortnaam en confidence (classificatiemodel) mbv de Google Coral. Er worden automatisch snapshots gemaakt van herkende vogel (als de herkennings score hoger is dan x)
Stukje code: (Python is echt fantastisch)
def overlay_and_classify(frame_rgb: np.ndarray, threshold: float, top_k: int):
"""
Classificeert het frame met Coral en plaatst overlay-tekst in het BGR-frame.
(Classificatie: geen bounding boxes.)
"""
pil_img = Image.fromarray(frame_rgb).convert("RGB").resize((in_w, in_h), Image.LANCZOS)
common.set_input(interpreter, pil_img)
t0 = time.time()
interpreter.invoke()
infer_ms = (time.time() - t0) * 1000.0
classes = classify.get_classes(interpreter, top_k=top_k, score_threshold=threshold)
frame_bgr = cv2.cvtColor(frame_rgb, cv2.COLOR_RGB2BGR)
# Tekst overlay
y = 28
info_color = (255, 255, 0)
ok_color = (0, 200, 0)
if classes:
top = classes[0]
label = labels.get(top.id, str(top.id))
cv2.putText(frame_bgr, f"{label}: {top.score:.2f}", (10, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, ok_color, 2)
y += 28
for c in classes[1:]:
l2 = labels.get(c.id, str(c.id))
cv2.putText(frame_bgr, f"{l2}: {c.score:.2f}", (10, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (200, 200, 200), 1)
y += 22
else:
cv2.putText(frame_bgr, "Geen klasse boven threshold", (10, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
y += 28
cv2.putText(frame_bgr, f"Infer {infer_ms:.1f} ms", (10, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, info_color, 2)
return frame_bgr, classes