[PYTHON] Analyse de modèles de mouvement à l'aide d'OpenCV (reconnaissance des objets et de leurs directions de déplacement en temps réel)

introduction

"Motion template" est une méthode efficace d'extraction de mouvement développée par MIT Media Lab (lien 1, [lien] 2](http://alumni.media.mit.edu/~jdavis/Publications/motiontemplategradient.pdf)). Il convient au calcul en temps réel avec une petite quantité de calcul. Il a un large éventail d'applications et peut afficher visuellement les mouvements des joueurs, les trajectoires de balle, de batte, de club et de raquette grâce à la reconnaissance des gestes et aux émissions sportives. Cette fois, j'essaierai l'analyse de modèle de mouvement en utilisant OpenCV 3.

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'image, la 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 ★ Veuillez installer core + opencv_contrib pour exécuter le modèle de mouvement.

■ Cliquez ici pour filtrer les images fixes Essayez la détection des bords avec OpenCV Effectuer divers filtres avec OpenCV (Gradient, Highpass, Laplacian, 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) Suivi d'objets à l'aide d'OpenCV (suivi des points caractéristiques spécifiés par la souris par la méthode Lucas-Kanade

explication facile

Le "modèle de mouvement" peut également être facilement réalisé en utilisant OpenCV. Voici un bref résumé des méthodes OpenCV utilisées cette fois.

ID Méthode Aperçu
(a) cv2.motempl.updateMotionHistory() Mettre à jour l'image animée
(b) cv2.motempl.calcMotionGradient() Calculez la direction de chaque coordonnée à partir de l'image animée
(c) cv2.motempl.calcGlobalOrientation() Calculez l'orientation globale de l'image animée

Cette fois, nous allons créer un programme qui utilise tous les éléments (a), (b) et (c), mais il est également possible de sélectionner uniquement ceux nécessaires. Par exemple, si vous ne voulez que des images animées, vous n'avez pas besoin de (b) (c).

Les principales fonctions de ce programme sont les suivantes.

programme

motion.py


import time
import math
import cv2
import numpy as np

#Données vidéo
VIDEO_DATA = "768x576.avi"
#Touche Echap
ESC_KEY = 0x1b
#Période de mouvement restante(sec)
DURATION = 1.0
#La longueur de la ligne qui affiche la direction générale
LINE_LENGTH_ALL = 60
#La longueur de la ligne qui affiche la direction de chaque coordonnée
LINE_LENGTH_GRID = 20
#Intervalle pour calculer la direction de chaque coordonnée
GRID_WIDTH = 40
#Le rayon du cercle de la ligne indiquant la direction
CIRCLE_RADIUS = 2

#Initialisation de la fenêtre d'affichage
cv2.namedWindow("motion")
#Chargement des données vidéo
video = cv2.VideoCapture(VIDEO_DATA)

#Chargement de la première image
end_flag, frame_next = video.read()
height, width, channels = frame_next.shape
motion_history = np.zeros((height, width), np.float32)
frame_pre = frame_next.copy()

while(end_flag):
    #Calcul de la différence entre les cadres
    color_diff = cv2.absdiff(frame_next, frame_pre)

    #Conversion de l'échelle de gris
    gray_diff = cv2.cvtColor(color_diff, cv2.COLOR_BGR2GRAY)

    #Binarisation
    retval, black_diff = cv2.threshold(gray_diff, 30, 1, cv2.THRESH_BINARY)

    #Temps de traitement du processeur(sec)Avoir
    proc_time = time.clock()

    #Mettre à jour l'image de l'historique des mouvements
    cv2.motempl.updateMotionHistory(black_diff, motion_history, proc_time, DURATION)

    #Gradation de l'affichage des anciens mouvements au fil du temps
    hist_color = np.array(np.clip((motion_history - (proc_time - DURATION)) / DURATION, 0, 1) * 255, np.uint8)

    #Conversion de l'échelle de gris
    hist_gray = cv2.cvtColor(hist_color, cv2.COLOR_GRAY2BGR)

    #Calcul de la direction de changement de l'image de l'historique des mouvements
    #* L'orientation stocke la valeur (deg) dans le sens du changement pour chaque coordonnée.
    mask, orientation = cv2.motempl.calcMotionGradient(motion_history, 0.25, 0.05, apertureSize = 5)

    #Dessinez le mouvement de chaque coordonnée avec une ligne verte
    width_i = GRID_WIDTH
    while width_i < width:
        height_i = GRID_WIDTH
        while height_i < height:
            cv2.circle(hist_gray, \
                       (width_i, height_i), \
                       CIRCLE_RADIUS, \
                       (0, 255, 0), \
                       2, \
                       16, \
                       0)
            angle_deg = orientation[height_i - 1][width_i - 1]
            if angle_deg > 0:
                angle_rad = math.radians(angle_deg)
                cv2.line(hist_gray, \
                         (width_i, height_i), \
                         (int(width_i + math.cos(angle_rad) * LINE_LENGTH_GRID), int(height_i + math.sin(angle_rad) * LINE_LENGTH_GRID)), \
                         (0, 255, 0), \
                         2, \
                         16, \
                         0)
            
            height_i += GRID_WIDTH
        
        width_i += GRID_WIDTH


    #Calculer la direction générale du mouvement
    angle_deg = cv2.motempl.calcGlobalOrientation(orientation, mask, motion_history, proc_time, DURATION)

    #Dessinez tout le mouvement avec une ligne jaune
    cv2.circle(hist_gray, \
               (int(width / 2), int(height / 2)), \
               CIRCLE_RADIUS, \
               (0, 215, 255), \
               2, \
               16, \
               0)
    angle_rad = math.radians(angle_deg)
    cv2.line(hist_gray, \
             (int(width / 2), int(height / 2)), \
             (int(width / 2 + math.cos(angle_rad) * LINE_LENGTH_ALL), int(height / 2 + math.sin(angle_rad) * LINE_LENGTH_ALL)), \
             (0, 215, 255), \
             2, \
             16, \
             0)

    #Afficher une image animée
    cv2.imshow("motion", hist_gray)

    #Appuyez sur la touche Echap pour terminer
    if cv2.waitKey(20) == ESC_KEY:
        break

    #Chargez l'image suivante
    frame_pre = frame_next.copy()
    end_flag, frame_next = video.read()

#Terminer le traitement
cv2.destroyAllWindows()
video.release()

Résultat d'exécution

Il est un peu difficile de comprendre la direction générale, mais s'il s'agit d'un cadre fixe, cela montre dans quelle direction les objets à l'écran se déplacent dans leur ensemble. Dans les cas où le cadre entier se déplace, il représente la direction dans laquelle le cadre se déplace.

m1.png

Analyse de mouvement à l'aide d'informations directionnelles

À titre d'exemple pour analyser un mouvement à l'aide d'un modèle de mouvement, analysons le moment d'une prise de vue de Kei Nishikiori. Effectuez une analyse à l'aide des informations de direction calculées à partir des informations du modèle de mouvement. Exécutons le programme de modèle de mouvement sur l'image d'origine. Dans l'image animée, vous pouvez voir la trajectoire de la balle pour chaque image (image animée 1, image animée 2). En comptant le nombre de balles, l'image Motion 2 a 3 images d'avance sur l'image Motion 1.

Si vous analysez la direction de chaque grille pour l'image animée 1 et l'image animée 2, vous pouvez lire les mouvements suivants.

--L'épaule droite, qui a été arrêtée dans l'image Motion 1, se déplace vers le coin supérieur droit de l'image Motion 2.

Lorsque vous le regardez à la télévision, il semble que vous sautiez avec tout votre corps et frappiez la balle, mais au moment où vous frappez réellement la balle dans cette vidéo, après avoir fait un axe solide avec la moitié gauche du corps, utilisez le ressort de la moitié droite du corps. Vous pouvez voir que vous frappez.

n1.png ** Image originale **

n2.png ** Image animée 1 **

n3.png ** Image Motion 2 **

Pour ceux qui font du sport, il serait intéressant d'analyser les mouvements des professionnels et la différence entre les mouvements quand ils réussissent et quand ils échouent.

Recommended Posts

Analyse de modèles de mouvement à l'aide d'OpenCV (reconnaissance des objets et de leurs directions de déplacement en temps réel)
Créez et essayez un environnement OpenCV et Python en quelques minutes à l'aide de Docker
Erreur survenue dans OpenCV3 et sa solution Précautions lors de l'utilisation d'OpenCV3 sur Mac
J'ai essayé la détection d'objets en utilisant Python et OpenCV
Essayez de convertir des vidéos en temps réel avec OpenCV