[PYTHON] Essayez de détecter les mouvements de fusion en utilisant AnyMotion

Aperçu

J'ai essayé de détecter le mouvement de fusion que tout le monde connaît. Utilisez AnyMotion pour calculer l'angle à partir des informations de coordonnées de l'articulation et déterminer s'il s'agit d'une posture de type fusion.

Qu'est-ce qu'AnyMotion

AnyMotion est un service de plate-forme d'API d'analyse de mouvement basé sur l'estimation de la posture à l'aide de l'IA. Il semble qu'il puisse être utilisé gratuitement car il est actuellement à l'essai.

Il est possible de visualiser / quantifier les mouvements du corps en estimant les coordonnées squelettiques d'une personne dans une image ou une vidéo montrant la personne et en calculant l'angle de la partie spécifiée en fonction de cela. ..

Écrit dans CLI, Python SDK, [Jupyter Notebook] sur GitHub Exemples](https://github.com/nttpc/anymotion-examples) est disponible.

Objectif visé

La fusion se compose à l'origine de deux guerriers exécutant des actions symétriques au même moment, mais il existe une restriction selon laquelle il n'est pas possible d'estimer la posture de deux personnes ou plus en même temps avec AnyMotion pour le moment. Par conséquent, j'analyserai le comportement un par un.

La fusion comporte trois étapes de mouvement selon le cri. fusion-right-all2.gif

  1. "Fu" L'action de tourner les bras et de s'appuyer les uns contre les autres
  2. "John" tordant le bras vers l'extérieur et la jambe vers l'intérieur
  3. "Huh!" L'action de plier le haut du corps vers l'intérieur et d'aligner les doigts

Cette fois, par souci de simplicité, nous définirons les postures 2 et 3 où le mouvement s'arrête un instant, et analyserons s'il y a un mouvement qui s'applique aux deux. Je m'en fiche si de petites pièces telles que la hauteur des doigts sont mal alignées.

L'analyse de mouvement mentionnée ci-dessus est effectuée par la personne du côté gauche et la personne du côté droit de la fusion, et si les deux bougent comme ça quel que soit le moment, la fusion est établie! Je dirais.

Définition de l'attitude de fusion

Le tableau ci-dessous résume l'état du corps considéré comme une fusion.

--Phase 1: "Jean" Tordant le bras vers l'extérieur et la jambe vers l'intérieur --Phase 2: "Huh!" L'action de plier le haut du corps vers l'intérieur et d'aligner les doigts

La personne à gauche (la personne à droite) "John" "Huh!"
Épaule gauche (épaule droite) 10〜90 130〜180
Coude gauche (coude droit) 90〜180 40〜130
Épaule droite (épaule gauche) 120〜200 50〜150
Coude droit (coude gauche) 150〜200 100〜170
Genou gauche (genou droit) 10〜80 -

Remarques

J'ai écrit le code en utilisant le SDK Python

Version utilisée

Préparation préalable

  $ pip install anymotion-sdk

Téléchargement de fichier vidéo ~ extraction de squelette

from anymotion_sdk import Client
from PIL import Image, ImageDraw
import cv2
import matplotlib.pyplot as plt
import ffmpeg
import numpy as np

#Préparation de l'API AnyMotion
client = Client(client_id="CLIENT_ID", 
                client_secret="CLIENT_SECRET")
filename = "left.mp4"

#Téléchargement vidéo (côté gauche)
left_filename = "fusion_left.mp4"
left_movie_id = client.upload(left_filename).movie_id
print(f"movie_id: {left_movie_id}")

#Extraction du squelette (extraction du point clé) (côté gauche)
left_keypoint_id = client.extract_keypoint(movie_id=left_movie_id)
left_extraction_result = client.wait_for_extraction(left_keypoint_id)
print(f"keypoint_id: {left_keypoint_id}")

#Téléchargement vidéo (côté droit)
right_filename = "fusion_right.mp4"
right_movie_id = client.upload(right_filename).movie_id
print(f"movie_id: {right_movie_id}")

#Extraction du squelette (extraction du point clé) (côté droit)
right_keypoint_id = client.extract_keypoint(movie_id=right_movie_id)
right_extraction_result = client.wait_for_extraction(right_keypoint_id)
print(f"keypoint_id: {right_keypoint_id}")

Obtenez l'angle

Spécifiez la pièce pour obtenir l'angle. La manière de spécifier est décrite dans Document officiel.

#Définition des règles d'analyse angulaire
analyze_angles_rule = [
    # left arm
    {
        "analysisType": "vectorAngle",
        "points": ["rightShoulder", "leftShoulder", "leftElbow"]
    },
    {
        "analysisType": "vectorAngle",
        "points": ["leftShoulder", "leftElbow", "leftWrist"]
    },
    # right arm
    {
        "analysisType": "vectorAngle",
        "points": ["leftShoulder", "rightShoulder", "rightElbow"]
    },
    {
        "analysisType": "vectorAngle",
        "points": ["rightShoulder", "rightElbow", "rightWrist"]
    },
    # left leg
    {
        "analysisType": "vectorAngle",
        "points": ["rightHip", "leftHip", "leftKnee"]
    },
    # right leg
    {
        "analysisType": "vectorAngle",
        "points": ["leftHip", "rightHip", "rightKnee"]
    },
]
#Démarrer l'analyse de l'angle (côté gauche)
left_analysis_id = client.analyze_keypoint(left_keypoint_id, rule=analyze_angles_rule)
#Acquisition des informations d'angle
left_analysis_result = client.wait_for_analysis(left_analysis_id).json
#Convertir les résultats au format dict en format liste (convertir simultanément les nombres de float en int)
left_angles = [list(map(lambda v: int(v) if v else None, x["values"])) for x in left_analysis_result["result"]]
print("angles analyzed.")

#Début de l'analyse d'angle (côté droit)
right_analysis_id = client.analyze_keypoint(right_keypoint_id, rule=analyze_angles_rule)
right_analysis_result = client.wait_for_analysis(right_analysis_id).json
right_angles = [list(map(lambda v: int(v) if v else None, x["values"])) for x in right_analysis_result["result"]]
print("angles analyzed.")

Détection de fusion

def is_fusion_phase1(pos, a, b, c, d, e, f):
    # pos: left or right
    # print(a, b, c, d, e, f)
    if pos == "left":  #Vérifiez qui se tient à gauche
        if not e:
            e = 70  #Considérez le cas où les jambes ne sont pas inclinées
        return (a in range(10, 90) and \
               b in range(90, 180) and \
               c in range(120, 200) and \
               d in range(150, 200) and \
               e in range(10, 80))
    else:  #Vérifiez qui se tient à droite
        if not f:
            f = 70  #Considérez le cas où les jambes ne sont pas inclinées
        return (c in range(10, 90) and \
               d in range(90, 180) and \
               a in range(120, 200) and \
               b in range(150, 200) and \
               f in range(10,80))

def is_fusion_phase2(pos, a, b, c, d, e, f):
    # pos: left or right
    # print(a, b, c, d, e, f)
    if pos == "left":  #Vérifiez qui se tient à gauche
        return a in range(130, 180) and \
               b in range(40, 130) and \
               c in range(50, 150) and \
               d in range(100, 170)
    else:
        return c in range(130, 180) and \
               d in range(40, 130) and \
               a in range(50, 150) and \
               b in range(100, 170)

def check_fusion(angles, position):
    """
        angles:Informations sur l'angle
        position: left or right
    """
    #Indicateur pour stocker si chaque étape a été détectée
    phase1 = False
    phase2 = False
    #Liste pour stocker le cadre correspondant
    p1 = []
    p2 = []
    for i in range(len(angles[0])):
        if is_fusion_phase1(position, angles[0][i], angles[1][i], angles[2][i], angles[3][i],
                            angles[4][i], angles[5][i]):
            print(i, "Phase1!!!")
            phase1 = True
            p1.append(i)
        elif phase1 and is_fusion_phase2(position, angles[0][i], angles[1][i], angles[2][i], angles[3][i],
                              angles[4][i], angles[5][i]):
            print(i, "Phase2!!!")
            phase2 = True
            p2.append(i)

    if phase1 and phase2:
        print("Fusion!!!!!!")
        
    return ((phase1 and phase2), p1, p2)

left_result, left_p1, left_p2 = check_fusion(left_angles, "left")
right_result, right_p1, right_p2 = check_fusion(right_angles, "right")

Générer une animation GIF à l'aide de l'image de fusion détectée

#Vérifiez l'orientation de la vidéo
def check_rotation(path_video_file):
    meta_dict = ffmpeg.probe(path_video_file)

    rotateCode = None
    try:
        if int(meta_dict['streams'][0]['tags']['rotate']) == 90:
            rotateCode = cv2.ROTATE_90_CLOCKWISE
        elif int(meta_dict['streams'][0]['tags']['rotate']) == 180:
            rotateCode = cv2.ROTATE_180
        elif int(meta_dict['streams'][0]['tags']['rotate']) == 270:
            rotateCode = cv2.ROTATE_90_COUNTERCLOCKWISE
    except:
        pass

    return rotateCode

#Obtenir l'image spécifiée de la vidéo
def get_frame_img(filename, frame_num):
    reader = cv2.VideoCapture(filename)
    rotateCode = check_rotation(filename)
    reader.set(1, frame_num)
    ret, frame_img = reader.read()
    reader.release()
    
    if not ret:
        return None
    if rotateCode:
        frame_img = cv2.rotate(frame_img, rotateCode)

    return frame_img

#Connectez deux cadres horizontalement
def get_frame_img_hconcat(l_filename, r_filename, l_framenum, r_framenum):
    l_img = get_frame_img(l_filename, l_framenum)
    r_img = get_frame_img(r_filename, r_framenum)
    
    img = cv2.hconcat([l_img, r_img])
    return img

#Obtenez la valeur médiane des trames détectées
left_p1_center = left_p1[int(len(left_p1)/2)]
left_p2_center = left_p2[int(len(left_p2)/2)]
right_p1_center = right_p1[int(len(right_p1)/2)]
right_p2_center = right_p2[int(len(right_p2)/2)]

#Combinez les images de la phase 1 horizontalement
p1_img = get_frame_img_hconcat(left_filename, right_filename, left_p1_center, right_p1_center)

#Combinez les images de la phase 2 horizontalement
p2_img = get_frame_img_hconcat(left_filename, right_filename, left_p2_center, right_p2_center)

#Convertir d'un tableau numpy en image PIL
im1 = Image.fromarray(cv2.cvtColor(p1_img, cv2.COLOR_BGR2RGB))
im2 = Image.fromarray(cv2.cvtColor(p2_img, cv2.COLOR_BGR2RGB))

#Générer une animation GIF
im1.save('fusion.gif', save_all=True, append_images=[im2], optimize=False, duration=700, loop=0)

fusion.gif

(Je pense qu'il y a beaucoup de choses que je veux dire, telles que mes mains se couvrent de choses et mes doigts sont mal alignés, mais s'il vous plaît, regardez bien ...)

Code source complet

Je l'ai téléchargé sur gist au format Jupyter Notebook.

en conclusion

J'ai essayé de détecter la posture de fusion en utilisant les informations de posture estimées à l'aide d'AnyMotion. En faisant ce genre de chose, il semble que vous puissiez également faire quelque chose comme un entraîneur personnel, comme vérifier la forme d'entraînement musculaire (Ietore). J'aimerais essayer diverses autres choses que je peux faire.

référence

Recommended Posts

Essayez de détecter les mouvements de fusion en utilisant AnyMotion
[Apprentissage automatique] Essayez de détecter des objets à l'aide de la recherche sélective
Essayez d'utiliser pynag pour configurer Nagios
Essayez d'obtenir des statistiques en utilisant e-Stat
Essayez d'utiliser Excel en utilisant Python (Xlwings)
Essayez d'utiliser Tkinter
Essayez d'utiliser django-import-export pour ajouter des données csv à django
Essayez d'utiliser docker-py
Essayez d'utiliser Blueprint avec Flask pour séparer les contrôleurs
Essayez d'utiliser Cookiecutter
Essayez d'utiliser PDFMiner
Essayez d'utiliser des géopandas
Essayez d'utiliser Selenium
Essayez d'utiliser scipy
Essayez d'utiliser pandas.DataFrame
Essayez de créer un serveur HTTP en utilisant Node.js
Essayez d'utiliser django-swiftbrowser
Essayez d'utiliser matplotlib
Essayez d'utiliser tf.metrics
Essayez d'utiliser PyODE
Essayez de simuler le mouvement du système solaire
Essayez de détecter les poissons avec python + OpenCV2.4 (inachevé)
(Python) Essayez de développer une application Web en utilisant Django
Essayez de créer une API RESTful avec MVC à l'aide de Flask 1.0.2
Essayez de supprimer des tweets en masse à l'aide de l'API de Twitter
Essayez d'extraire des mots à haute fréquence en utilisant NLTK (python)
Essayez de résoudre le Sudoku à une vitesse explosive en utilisant Numpy
Essayez d'utiliser virtualenv (virtualenvwrapper)
[Azure] Essayez d'utiliser Azure Functions
Essayez d'implémenter yolact
Essayez d'utiliser virtualenv maintenant
Essayez d'utiliser W & B
Essayez d'utiliser Django templates.html
[Kaggle] Essayez d'utiliser LGBM
Essayez d'utiliser l'analyseur de flux de Python.
Essayez d'utiliser Tkinter de Python
Essayez d'utiliser Tweepy [Python2.7]
Essayez d'utiliser collate_fn de Pytorch
Essayez de le faire avec GUI, PyQt en Python
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ①
Essayez d'exploiter un fichier Excel en utilisant Python (Pandas / XlsxWriter) ②
Essayez de juger des photos de plats à l'aide de l'API Google Cloud Vision
Essayez de modéliser une distribution multimodale à l'aide de l'algorithme EM
Essayez d'implémenter la régression linéaire à l'aide de Pytorch avec Google Colaboratory