Personensuche mit einer Lepton

Dies ist ein Tutorial zur Implementierung eines grundlegenden Algorithmus zur Personensuche mit einer FLIR Lepton-Kamera unter Verwendung der Open-Source-Computer-Vision-Bibliothek OpenCV.

Das Ziel

Wärmebildkameras eignen sich hervorragend zum Auffinden von Säugetieren bei fast allen Lichtverhältnissen. Als Übung, um herauszufinden, was diese Kameras alles können, versuchen wir, Personen im Sichtfeld der Lepton zu finden und sie mit OpenCV zu skizzieren.

Die Tools

Benötigte Geräte:

  1. Eine Lepton
  2. Ein PureThermal Board
  3. Eine Python 2.7-Umgebung mit installierten OpenCV-Bindungen. Diese kann unter Windows, OSX oder Linux eingerichtet werden.
  4. PIL, wenn Sie Bilder speichern möchten.

Das Setup

Folgen Sie einem Tutorial für Ihre spezifische Plattform, um die Python-Umgebung einzurichten und OpenCV zu installieren. Wenn Sie fertig sind, überprüfen Sie, ob alles funktioniert, indem Sie einen Webcam-Stream anzeigen.

import cv2
cv2.namedWindow("preview")
cameraID = 0
vc = cv2.VideoCapture(cameraID)

if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
rval = False

while rval:
cv2.imshow("preview", frame)
rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
break

Dies sollte Ihnen einen Stream anzeigen. Wenn Sie eine Webcam angeschlossen oder in Ihren Computer integriert haben, müssen Sie die Kamera-ID möglicherweise auf einen anderen Wert als 0 ändern. Auf meinem Entwicklungscomputer ist die PureThermal-Board-ID 1.

Der Ansatz

OpenCVs Webcam-Capture-Code ist nicht in der Lage, radiometrische Wärmedaten zu erfassen, was ein ideales Format für die Personenzählung wäre, aber Sie können damit den kolorierten Feed von einer PureThermal-Platine erfassen, was gut genug ist, um mit ein wenig Vorverarbeitung Umrisse zu zeichnen.

Insbesondere Menschen neigen dazu, in der Standardfarbpalette sehr hell zu erscheinen, sodass die Umwandlung der RGB-Bilder in HSV und das Betrachten des V-Kanals ein ziemlich klares Bild davon liefern, wo sich Körpertemperaturobjekte in der Szene befinden.

Probieren Sie es aus, indem Sie cv2.imshow("preview", frame) durch Folgendes ersetzen:

frame_hsv = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)
frame_v = frame_hsv[:,:,2]
cv2.imshow("preview", frame_v)

Jetzt ist es ziemlich offensichtlich, wo die Menschen sind, und wir haben etwas, worauf unsere Computer-Vision sich stützen kann.

Öffnen Sie OpenCV

OpenCV ist eine sehr beliebte Computer-Vision-Bibliothek für C++ mit Bindungen an Python. Sie bietet eine Vielzahl gängiger Computer-Vision-Operationen, mit denen wir unsere Umrisse zeichnen können.

Intelligente Kantenerkennung ist ein guter Anfang. Es handelt sich dabei um eine robuste Technik zum Auffinden von Kanten in einem Bild.

Sie können die Kanten anzeigen, die OpenCV mit diesem Code erkennt:

thresh = 50
edges = cv2.Canny(frame_v,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)

Das sieht aber nicht sehr gut aus. Die Kantenerkennung nimmt zu viel hochfrequentes Rauschen auf und verwechselt es mit Kanten. Eine kleine Bildglättung sollte das klären können. Verwenden Sie eine kantenerhaltende Bildglättungsmethode, die als bilateraler Filter bezeichnet wird. Das ist wie eine Gaußsche Unschärfe, hat jedoch weniger Auswirkungen auf die Kanten, die in erster Linie gesucht wurden.

blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
thresh = 70
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)

Das sieht viel besser aus, aber es gibt noch Raum für Verbesserungen. Versuchen wir, Dinge wie Lichter, die als Menschen dargestellt werden, zu reduzieren. Dies ist schwierig, aber OpenCV bietet eine Möglichkeit, dies zu tun. Erstellen Sie zunächst ein binäres Bild, indem Sie das Originalbild mit einem Schwellenwert versehen und eine 1 dort setzen, wo das Pixel warm ist, und eine 0, wo es nicht ist. Verwenden Sie dann OpenCV, um die durch diese Operation erzeugten 1er-Blobs zu erodieren. Danach erweitern Sie diese Blobs wieder, um ungefähr die gleiche Größe wie zuvor zu haben.

_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
import numpy as np
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))

Nach der Erosion und Dilatation bleibt das binäre Bild im Wesentlichen gleich, aber alle kleinen Formen wurden entfernt. Genau das wollen wir. Jetzt können wir damit alle Kanten maskieren, die zu kleinen Formen gehörten.

Sehen wir uns an, wie dies aussieht, wenn es auf die erkannten Kanten angewendet wird.

Nicht schlecht! Und es sieht auch ziemlich gut aus, wenn es auf das Quellbild gelegt wird.

Der endgültige Code sieht ungefähr so ​​aus. Möglicherweise müssen Sie die Konstanten nach Ihren Wünschen abstimmen, und OpenCV bietet eine große Auswahl an Tools, mit denen Sie die Ergebnisse für Ihre spezifischen Anforderungen verbessern können.

import cv2
import numpy as np
cv2.namedWindow("preview")
cameraID = 0
vc = cv2.VideoCapture(cameraID)

if vc.isOpened(): # try to get the first frame
rval, frame = vc.read()
else:
rval = False

while rval:
frame_v = cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)[:,:,2]

blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
thresh = 50
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)

_,mask = cv2.threshold(blurredBrightness,200,1,cv2.THRESH_BINARY)
erodeSize = 5
dilateSize = 7
eroded = cv2.erode(mask, np.ones((erodeSize, erodeSize)))
mask = cv2.dilate(eroded, np.ones((dilateSize, dilateSize)))

cv2.imshow("preview", cv2.resize(cv2.cvtColor(mask*edges, cv2.COLOR_GRAY2RGB) | frame, (640, 480), interpolation = cv2.INTER_CUBIC))

rval, frame = vc.read()
key = cv2.waitKey(20)
if key == 27: # exit on ESC
break

Zugehörige Artikel