Suivi OpenCV
Cette démonstration vise à apprendre à créer un système de détection et de suivi de mouvement très basique et simple à l’aide de Python et OpenCV. Nous parvenons à suivre chaque personne avec une boîte englobante rectangulaire à la fin de cet article.
Créer un système de détection et de suivi de mouvement à l’aide de Python et OpenCV
Tout d’abord, nous devons lire deux trames de l’instance CAP
.
ret, F1 = CAP.read()
De même, nous allons lire la seconde trame.
ret, F2 = CAP.read()
Nous allons maintenant déclarer une variable appelée DF
et utiliser la fonction absdiff()
. Le absdiff()
permet de trouver la différence absolue entre les trames, la première F1
et la seconde F2
.
while CAP.isOpened():
if ret == False:
print(ret)
break
DF = cv2.absdiff(F1, F2)
Convertissez cette différence en mode niveaux de gris en utilisant la méthode cvtColor()
. Le premier paramètre sera DF
.
Le deuxième argument sera COLOR_BGR2GRAY
, qui aidera à convertir la couleur du cadre BGR en mode niveaux de gris ; pourquoi découvrons-nous le mode niveaux de gris ?
Parce que nous trouverons le contour dans les étapes ultérieures, il est plus facile de trouver les contours en mode niveaux de gris qu’en mode coloré.
Gray_Scale = cv2.cvtColor(DF, cv2.COLOR_BGR2GRAY)
Une fois que nous avons le mode niveaux de gris, nous devons flouter notre cadre en niveaux de gris en utilisant la méthode GaussianBlur()
. Cela prend quelques paramètres; le premier est Gray_Scale
, le deuxième paramètre sera la taille du noyau 5x5
, et le troisième paramètre sera la valeur Sigma X
.
BL = cv2.GaussianBlur(Gray_Scale, (5, 5), 0)
Nous devons déterminer le seuil en utilisant la méthode threshold()
. Il renvoie deux objets ; nous définissons _
car nous n’avons pas besoin de la première variable et alors la seconde variable sera thresh
.
Dans le premier paramètre, nous passerons notre image floue comme source, puis le deuxième paramètre sera la valeur de seuil de 20. La valeur de seuil maximale sera de 255 ; le type sera THRESH_BINARY
.
_, thresh = cv2.threshold(BL, 20, 255, cv2.THRESH_BINARY)
Il faut dilater l’image seuillée pour combler tous les trous ; cela nous aidera à trouver de meilleurs contours. La méthode dilate()
prend quelques paramètres ; le premier paramètre sera le seuil défini, et le deuxième paramètre sera la taille du noyau, mais nous lui passons None
.
Le troisième argument est le nombre d’itérations à 3. Si cela ne fonctionne pas, vous pouvez augmenter ou diminuer le nombre d’itérations.
DL = cv2.dilate(thresh, None, iterations=3)
Dans l’étape suivante, nous allons découvrir le contour, et la méthode findContours()
nous donne deux résultats ; l’un est les contours, et l’autre est la hiérarchie, mais nous n’allons pas utiliser le deuxième résultat. On va retrouver les contours sur l’image dilatée.
On passe donc image dilatée en premier paramètre, et le suivant sera le mode RETR_TREE
qui est le plus couramment utilisé. Le paramètre suivant sera la méthode CHAIN_APPROX_SIMPLE
.
CTS, _ = cv2.findContours(DL, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Dans l’étape suivante, nous voulons dessiner les rectangles, nous allons donc parcourir tous les contours à l’aide de la boucle for
. Le CTS
est une liste, et nous itérons sur cette liste, donc la première étape sera de sauvegarder toutes les coordonnées des contours en utilisant la méthode boundingRect()
.
Dans l’étape suivante, nous découvrirons la zone de contour, et si cette zone est inférieure à une certaine valeur, nous ne dessinerons pas de rectangle. A l’intérieur de la boucle for
, on définira que si l’aire de contour est inférieure à 700, on continuera l’itération ; sinon, dessinez le rectangle.
Pour dessiner le rectangle, il faut utiliser la méthode cv2.rectangle()
, et le premier argument ici sera le source qui sera F1
; le second paramètre sera le point 1 (x,y)
. Le troisième paramètre sera le point 2, le paramètre suivant sera un tuple comme valeur de couleur et le paramètre suivant sera l’épaisseur.
for CT in CTS:
(x, y, w, h) = cv2.boundingRect(CT)
if cv2.contourArea(CT) < 900:
continue
cv2.rectangle(F1, (x, y), (x + w, y + h), (0, 255, 0), 2)
Nous placerons du texte sur l’image si un mouvement est observé. Nous utiliserons la méthode cv2.putText()
; cette méthode prendra F1
, la seconde sera le texte, et le paramètre suivant en argument sera l’origine où l’on veut mettre ce texte.
Le paramètre suivant est la font-face FONT_HERSHEY_SIMPLEX
; le paramètre suivant sera l’échelle de la police. Le prochain sera la couleur de la police; ensuite, le dernier paramètre sera l’épaisseur du texte.
cv2.putText(
F1,
"Status: {}".format("Movement"),
(10, 20),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 0, 255),
3,
)
Nous allons maintenant écrire du code en dehors de la boucle. Tout d’abord, nous allons écrire des images de sortie pour enregistrer la sortie, puis afficher F1
, le résultat après l’application du contour.
Dans la ligne suivante, nous lisons la nouvelle trame dans la variable F2
, et avant de lire la nouvelle trame, nous attribuons la valeur de F2
au F1
. De cette façon, nous lisons et trouvons la différence entre les deux cadres.
OP.write(IMG)
cv2.imshow("feed", F1)
F1 = F2
ret, F2 = CAP.read()
Code source complet :
import cv2
import numpy as np
CAP = cv2.VideoCapture("input.avi")
FR_W = int(CAP.get(cv2.CAP_PROP_FRAME_WIDTH))
FR_H = int(CAP.get(cv2.CAP_PROP_FRAME_HEIGHT))
FRC = cv2.VideoWriter_fourcc("X", "V", "I", "D")
OP = cv2.VideoWriter("output.avi", FRC, 5.0, (1280, 720))
ret, F1 = CAP.read()
ret, F2 = CAP.read()
print(F1.shape)
while CAP.isOpened():
if ret == False:
print(ret)
break
DF = cv2.absdiff(F1, F2)
Gray_Scale = cv2.cvtColor(DF, cv2.COLOR_BGR2GRAY)
BL = cv2.GaussianBlur(Gray_Scale, (5, 5), 0)
_, thresh = cv2.threshold(BL, 20, 255, cv2.THRESH_BINARY)
DL = cv2.dilate(thresh, None, iterations=3)
CTS, _ = cv2.findContours(DL, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for CT in CTS:
(x, y, w, h) = cv2.boundingRect(CT)
if cv2.contourArea(CT) < 900:
continue
cv2.rectangle(F1, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(
F1,
"Status: {}".format("Movement"),
(10, 20),
cv2.FONT_HERSHEY_SIMPLEX,
1,
(0, 0, 255),
3,
)
IMG = cv2.resize(F1, (1280, 720))
OP.write(IMG)
cv2.imshow("feed", F1)
F1 = F2
ret, F2 = CAP.read()
if cv2.waitKey(40) == 27:
break
cv2.destroyAllWindows()
CAP.release()
OP.release()
Nous pouvons voir que le statut montre du mouvement parce que tout le monde bouge. Nous pouvons également regarder des rectangles qui sont dessinés autour de la personne en mouvement.
Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.
LinkedIn