Trouver des personnes avec une Lepton
Il s’agit d’un tutoriel pour la mise en œuvre d’un algorithme de recherche de personnes de base avec une caméra FLIR Lepton utilisant la bibliothèque de vision informatique à code source ouvert OpenCV.
L’objectif
Les caméras thermiques sont excellentes pour trouver des mammifères dans presque toutes les conditions d’éclairage. Pour explorer ce qu’ils peuvent faire, essayons de trouver des personnes dans le champ de vision de Lepton et d’avoir un contour autour d’eux avec OpenCV.
Les outils
Matériel dont vous avez besoin :
- Une Lepton
- Un panneau PureThermal
- Un environnement Python 2.7 avec des fixations OpenCV installées. Cela peut être configuré pour Windows, macOS ou Linux.
- PIL si vous voulez pouvoir enregistrer des images.
La configuration
Suivez un tutoriel pour votre plateforme spécifique afin de configurer l’environnement Python et OpenCV installé. Une fois que vous avez terminé, vérifiez que tout fonctionne en consultant un flux de webcaméra.
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()
touche ’cv2.waitKey(20)
Si la clé == 27 : # exit on ESC
break
Cela devrait vous montrer un flux. Si une caméra Web est connectée ou intégrée à votre ordinateur, vous devrez peut-être changer l’ID de caméra à une valeur autre que 0. Sur ma machine de développement, l’ID de la carte PureThermal est 1.
L’approche
Le code de saisie de caméra Web OpenCV est en mesure de capturer les données thermiques radiométriques, ce qui serait un format idéal pour le comptage des personnes, mais il vous permet de capturer l’alimentation colorée d’une carte PureThermal, ce qui sera suffisant pour dessiner des contours avec un peu de prétraitement.
Plus précisément, les humains ont tendance à apparaître comme très lumineux dans la palette de couleurs par défaut, donc convertir les images RVB en VHS et regarder le canal V donne une image assez claire de l’endroit où se trouvent les objets de température corporelle dans la scène.
Essayez-le en changeant cv2.imshow("preview", frame) par ce qui suit :
Frame_hsv ’ cv2.cvtColor(frame, cv2.COLOR_RGB2HSV)
Frame_v ’ Frame_hsv[:,:,2]
cv2.imshow("preview", frame)
Il est maintenant évident là où se trouvent les humains et nous avons quelque chose avec lequel nous pouvons faire la vision informatique.
Saisir OpenCV
OpenCV est une bibliothèque de vision informatique très populaire pour C++ avec des liaisons à Python. Il offre une grande variété d’opérations de vision informatique courantes, que nous utilisons pour dessiner nos contours.
La détection des bordures Canny est là où nous commencerons. Il s’agit d’une technique robuste pour trouver les bordures dans une image.
Vous pouvez afficher les bordures détectés par OpenCV avec ce code :
thresh = 50
edges = cv2.Canny(frame_v,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)
Ça n’est pas très beau par contre. La détection des bordures capte trop de bruit à haute fréquence et le confond pour les bordures. Un peu de lissage d’image devrait pouvoir le régler. Nous utilisons une méthode de lissage d’image qui préserve les bordures, appelée filtre bilatéral. C’est comme un flou gaussien, mais il a moins d’impact sur les bordures que nous cherchons à la base.
blurredBrightness = cv2.bilateralFilter(frame_v,9,150,150)
thresh = 70
edges = cv2.Canny(blurredBrightness,thresh,thresh*2, L2gradient=True)
cv2.imshow("preview", edges)
Cela est beaucoup mieux, mais il y a encore place à l’amélioration. Essayons de réduire des éléments comme les lumières qui sont indiquées comme des personnes. C’est difficile, mais OpenCV offre un moyen de le faire. Tout d’abord, nous créons une image binaire en séparant l’image originale et en plaçant un 1 partout où le pixel est chaud, et un 0 là où il ne l’est pas. Ensuite, nous utilisons OpenCV pour éroder les grappes de 1 créés par cette opération. Après cela, nous élargissons à nouveau ces grappes pour qu’ils soient à peu près de la même taille qu’auparavant.
_,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)))
Après l’érosion et la dilatation, l’image binaire est essentiellement la même, mais avec toutes les petites formes retirées. C’est exactement ce que nous voulons. Nous pouvons maintenant l’utiliser pour masquer tous les bords qui appartenaient aux petites formes.
Voyons à quoi cela ressemble lorsqu’il est appliqué aux bords détectés.
Pas mal! Et il a aussi fière allure superposé sur l’image source.
Le code final ressemble à ceci. Vous devrez peut-être régler les constantes à votre goût, et OpenCV fournit un vaste assortiment d’outils que vous pourriez utiliser pour améliorer les résultats pour vos besoins spécifiques.
import cv2
import numpy as np
cv2.namedWindow("preview")
ID de la caméra ’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