Cette fois, je vais spécifier la cible de suivi de la vidéo avec un clic de souris et essayer de suivre l'objet dans l'espace 3D en temps réel. Comparé à la correspondance de modèles, il utilise un algorithme basé sur des fonctionnalités qui nécessite moins de calculs et peut être suivi même lorsqu'il est pivoté.
OpenCV OpenCV (Open Source Computer Vision Library) est une collection de bibliothèques de traitement vidéo / image sous licence BSD. Il existe de nombreux algorithmes tels que le filtrage d'images, la mise en correspondance de modèles, la reconnaissance d'objets, l'analyse vidéo et l'apprentissage automatique.
■ Exemple de suivi de mouvement avec OpenCV (OpenCV Google Summer of Code 2015) https://www.youtube.com/watch?v=OUbUFn71S4s
■ Cliquez ici pour une installation et une utilisation facile Installer OpenCV 3 (core + contrib) dans l'environnement Python 3 & Différence entre OpenCV 2 et OpenCV 3 & Easy operation check
■ Cliquez ici pour filtrer les images fixes Essayez la détection des bords avec OpenCV Effectuer divers filtres avec OpenCV (Gradient, Highpass, Laprasian, Gaussian) Extraire des points caractéristiques avec OpenCV (AgastFeature, FAST, GFTT, MSER, AKAZE, BRISK, KAZE, ORB, SimpleBlob)
■ Cliquez ici pour le traitement des fichiers vidéo Essayez de convertir des vidéos en temps réel avec OpenCV Essayez de convertir des vidéos de caméra Web / caméra vidéo en temps réel avec OpenCV Dessinez un flux optique en temps réel avec OpenCV (méthode Shi-Tomasi, méthode Lucas-Kanade)
Cette fois, créez un programme avec les fonctions suivantes.
La fonction de pause est très importante lors de la spécification des points caractéristiques d'une vidéo avec un clic de souris. Mettez la vidéo en pause avec la touche "s" et spécifiez lentement les points caractéristiques.
Environnement d'exploitation
Données vidéo J'ai utilisé l'exemple de vidéo fourni avec OpenCV. OpenCV\opencv\sources\samples\data\768x576.avi
motion.py
import cv2
import numpy as np
#Touche Echap
ESC_KEY = 0x1b
#clé s
S_KEY = 0x73
#touche r
R_KEY = 0x72
#Nombre maximum de points caractéristiques
MAX_FEATURE_NUM = 500
#Condition de terminaison de l'algorithme itératif
CRITERIA = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)
#Intervalle (1000/fréquence d'images)
INTERVAL = 30
#Données vidéo
VIDEO_DATA = '768x576.avi'
class Motion:
#constructeur
def __init__(self):
#Fenêtre d'affichage
cv2.namedWindow("motion")
#Enregistrement de rappel pour les événements de souris
cv2.setMouseCallback("motion", self.onMouse)
#Vidéo
self.video = cv2.VideoCapture(VIDEO_DATA)
#intervalle
self.interval = INTERVAL
#Cadre actuel (couleur)
self.frame = None
#Cadre actuel (gris)
self.gray_next = None
#Dernier cadre (gris)
self.gray_prev = None
#Point caractéristique
self.features = None
#État des points caractéristiques
self.status = None
#Boucle principale
def run(self):
#Traitement de la première image
end_flag, self.frame = self.video.read()
self.gray_prev = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
while end_flag:
#Convertir en échelle de gris
self.gray_next = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
#Calculer le flux optique lorsque les points caractéristiques sont enregistrés
if self.features is not None:
#Calcul du flux optique
features_prev = self.features
self.features, self.status, err = cv2.calcOpticalFlowPyrLK( \
self.gray_prev, \
self.gray_next, \
features_prev, \
None, \
winSize = (10, 10), \
maxLevel = 3, \
criteria = CRITERIA, \
flags = 0)
#Ne laissez que les points caractéristiques valides
self.refreshFeatures()
#Dessinez des points caractéristiques valides sur le cadre
if self.features is not None:
for feature in self.features:
cv2.circle(self.frame, (feature[0][0], feature[0][1]), 4, (15, 241, 255), -1, 8, 0)
#afficher
cv2.imshow("motion", self.frame)
#Préparation de la prochaine boucle
self.gray_prev = self.gray_next
end_flag, self.frame = self.video.read()
if end_flag:
self.gray_next = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
#intervalle
key = cv2.waitKey(self.interval)
# "Esc"Appuyez sur la touche pour terminer
if key == ESC_KEY:
break
# "s"Pause en appuyant sur une touche
elif key == S_KEY:
self.interval = 0
elif key == R_KEY:
self.interval = INTERVAL
#Terminer le traitement
cv2.destroyAllWindows()
self.video.release()
#Spécifiez des points caractéristiques en un clic de souris
#S'il y a un point caractéristique existant dans le voisinage cliqué, supprimez le point caractéristique existant
#S'il n'y a pas de point caractéristique existant dans le voisinage cliqué, ajoutez un nouveau point caractéristique
def onMouse(self, event, x, y, flags, param):
#Autre que le clic gauche
if event != cv2.EVENT_LBUTTONDOWN:
return
#Premier point caractéristique ajouté
if self.features is None:
self.addFeature(x, y)
return
#Rayon de recherche (pixel)
radius = 5
#Rechercher des points caractéristiques existants à proximité
index = self.getFeatureIndex(x, y, radius)
#Puisqu'il existe un point caractéristique existant à proximité du clic, supprimez le point caractéristique existant
if index >= 0:
self.features = np.delete(self.features, index, 0)
self.status = np.delete(self.status, index, 0)
#Puisqu'il n'y a aucun point caractéristique existant près de la zone cliquée, un nouveau point caractéristique est ajouté.
else:
self.addFeature(x, y)
return
#Obtenez un index des points caractéristiques existants dans le rayon spécifié
#S'il n'y a pas de points caractéristiques dans l'index de rayon spécifié= -Répondre 1
def getFeatureIndex(self, x, y, radius):
index = -1
#Aucun point caractéristique n'est enregistré
if self.features is None:
return index
max_r2 = radius ** 2
index = 0
for point in self.features:
dx = x - point[0][0]
dy = y - point[0][1]
r2 = dx ** 2 + dy ** 2
if r2 <= max_r2:
#Ce point caractéristique se trouve dans le rayon spécifié
return index
else:
#Ce point caractéristique est en dehors du rayon spécifié
index += 1
#Tous les points caractéristiques sont en dehors du rayon spécifié
return -1
#Ajouter de nouveaux points caractéristiques
def addFeature(self, x, y):
#Les points caractéristiques ne sont pas enregistrés
if self.features is None:
#Créer un ndarray et enregistrer les coordonnées des points caractéristiques
self.features = np.array([[[x, y]]], np.float32)
self.status = np.array([1])
#Points caractéristiques très précis
cv2.cornerSubPix(self.gray_next, self.features, (10, 10), (-1, -1), CRITERIA)
#Dépasse le nombre maximum de points caractéristiques enregistrés
elif len(self.features) >= MAX_FEATURE_NUM:
print("max feature num over: " + str(MAX_FEATURE_NUM))
#Points caractéristiques supplémentaires enregistrés
else:
#Ajouter des coordonnées de point d'entité à la fin d'un ndarray existant
self.features = np.append(self.features, [[[x, y]]], axis = 0).astype(np.float32)
self.status = np.append(self.status, 1)
#Points caractéristiques très précis
cv2.cornerSubPix(self.gray_next, self.features, (10, 10), (-1, -1), CRITERIA)
#Ne laissez que les points caractéristiques valides
def refreshFeatures(self):
#Les points caractéristiques ne sont pas enregistrés
if self.features is None:
return
#Vérifier tous les statuts
i = 0
while i < len(self.features):
#Ne peut pas être reconnu comme un point caractéristique
if self.status[i] == 0:
#Supprimer du ndarray existant
self.features = np.delete(self.features, i, 0)
self.status = np.delete(self.status, i, 0)
i -= 1
i += 1
if __name__ == '__main__':
Motion().run()
Le programme a utilisé l'exemple de vidéo OpenCV (768x576.avi), mais il n'a pas toujours la même apparence sur le même écran.
Toute vidéo est OK. Changez la partie VIDEO_DATA
du programme en votre vidéo préférée.
Par exemple, à titre d'exemple du résultat de l'exécution, utilisons Uchimura, qui joue la barre de fer lors de la finale individuelle de gymnastique olympique de Rio de Janeiro 2016. Dans cette vidéo, Uchimura, qui joue la barre de fer, bouge également, mais le cadre d'arrière-plan se déplace également de haut en bas selon Uchimura. Utilisez la touche "s" pour mettre la vidéo en pause et définir le point pour suivre les chaussettes d'Uchimura. Les points jaunes représentent les points caractéristiques. Lorsque vous lisez la vidéo, vous pouvez voir que les points jaunes suivent les chaussettes d'Uchimura. (Parce que les orteils d'Uchimura sont parfaitement alignés, on peut dire qu'il peut continuer à le reconnaître comme le même point caractéristique.)
Lorsque vous exécutez réellement le programme, vous pouvez voir que ce programme (en utilisant simplement cv2.calcOpticalFlowPyrLK ()) a trois problèmes.
Dans les deux cas, le montant du calcul augmentera, mais il existe des moyens de le gérer. Je vais essayer de faire une version compatible bientôt.
Recommended Posts