La sortie
L'interface utilisateur doit afficher l'image originale avec les poses mélangées.
Cartographie JSON-UI
Le résultat des fichiers JSON est constitué d'un ensemble de points clefs, dont l'ordre est lié au résultat de l'interface utilisateur comme suit :
- Format de sortie de la pose (BODY_25)
- Format de sortie des poses (COCO)
- Format de sortie des visages
- Format de sortie des mains
Format de sortie JSON
Il existe deux options pour enregistrer la sortie OpenPose. Toutes deux respectent l'ordre des points clefs décrit dans la section «Ordre des points clefs en C++/Python» (à lire ensuite).
L'option --write_json enregistre les données de pose des personnes dans des fichiers JSON. Chaque fichier représente une image et contient un tableau d'objets, chaque objet contenant :
- pose_keypoints_2d : Emplacements des parties du corps (x, y) et fiabilité de détection (c) au format x0,y0,c0,x1,y1,c1,.... Les coordonnées x et y peuvent être normalisées dans la plage [0,1], [-1,1], [0, taille source], [0, taille de sortie], etc. (voir l'option --keypoint_scale pour plus d'informations), tandis que le score de confiance (c) est compris dans la plage [0,1]. De plus, le nombre de points clés générés dans ce tableau reste cohérent entre les fichiers JSON.
- face_keypoints_2d, hand_left_keypoints_2d et hand_right_keypoints_2d sont analogues à pose_keypoints_2d, mais appliqués aux parties du visage et des mains.
- body_keypoints_3d, face_keypoints_3d, hand_left_keypoints_2d et hand_right_keypoints_2d sont analogues, mais appliqués aux parties 3D. Ils sont vides si l'option --3d n'est pas activée. Leur format est x0,y0,z0,c0,x1,y1,z1,c1,..., où c vaut 1 ou 0 selon que la reconstruction 3D a réussi ou non.
- part_candidates (facultatif et avancé) : Les candidats des parties du corps avant leur assemblage en personnes. Vide si l'option --part_candidates n'est pas activée.
- {
- "version":1.1,
- "people":[
- {
- "pose_keypoints_2d":[582.349,507.866,0.845918,746.975,631.307,0.587007,...],
- "face_keypoints_2d":[468.725,715.636,0.189116,554.963,652.863,0.665039,...],
- "hand_left_keypoints_2d":[746.975,631.307,0.587007,615.659,617.567,0.377899,...],
- "hand_right_keypoints_2d":[617.581,472.65,0.797508,0,0,0,723.431,462.783,0.88765,...]
- "pose_keypoints_3d":[582.349,507.866,507.866,0.845918,507.866,746.975,631.307,0.587007,...],
- "face_keypoints_3d":[468.725,715.636,715.636,0.189116,715.636,554.963,652.863,0.665039,...],
- "hand_left_keypoints_3d":[746.975,631.307,631.307,0.587007,631.307,615.659,617.567,0.377899,...],
- "hand_right_keypoints_3d":[617.581,472.65,472.65,0.797508,472.65,0,0,0,723.431,462.783,0.88765,...]
- }
- ],
- // Si `--part_candidates` actif
- "part_candidates":[
- {
- "0":[296.994,258.976,0.845918,238.996,365.027,0.189116],
- "1":[381.024,321.984,0.587007],
- "2":[313.996,314.97,0.377899],
- "3":[238.996,365.027,0.189116],
- "4":[283.015,332.986,0.665039],
- "5":[457.987,324.003,0.430488,283.015,332.986,0.665039],
- "6":[],
- "7":[],
- "8":[],
- "9":[],
- "10":[],
- "11":[],
- "12":[],
- "13":[],
- "14":[293.001,242.991,0.674305],
- "15":[314.978,241,0.797508],
- "16":[],
- "17":[369.007,235.964,0.88765]
- }
- ]
- }
- (Obsolète) --write_keypoint utilise les formats par défaut d'OpenCV cv::FileStorage, à savoir JSON (si OpenCV 3 ou supérieur), XML et YML. Il affiche uniquement les informations corporelles en 2D (pas de 3D ni de visage/mains).
(Détails de bas niveau) Si vous souhaitez modifier ce format de fichier (par exemple, le nom du fichier de sortie), vous pouvez vérifier et/ou modifier peopleJsonSaver.cpp.
Points clés en C++/Python
Ordre des points clés en C++/Python
L'ordre de cartographie des parties du corps de tout modèle de corps (par exemple, BODY_25, COCO, MPI) peut être extrait des API C++ et Python.
En C++, getPoseBodyPartMapping(const PoseModel poseModel) est disponible dans poseParameters.hpp :
- // Appel C++ API
- #include <openpose/pose/poseParameters.hpp>
- const auto& poseBodyPartMappingBody25 = getPoseBodyPartMapping(PoseModel::BODY_25);
- const auto& poseBodyPartMappingCoco = getPoseBodyPartMapping(PoseModel::COCO_18);
- const auto& poseBodyPartMappingMpi = getPoseBodyPartMapping(PoseModel::MPI_15);
- const auto& poseBodyPartMappingBody25B = getPoseBodyPartMapping(PoseModel::BODY_25B);
- const auto& poseBodyPartMappingBody135 = getPoseBodyPartMapping(PoseModel::BODY_135);
-
- // Résultat pour BODY_25 (25 parties du corps composées de COCO + pied)
- // const std::map<unsigned int, std::string> POSE_BODY_25_BODY_PARTS {
- // {0, "Nose"},
- // {1, "Neck"},
- // {2, "RShoulder"},
- // {3, "RElbow"},
- // {4, "RWrist"},
- // {5, "LShoulder"},
- // {6, "LElbow"},
- // {7, "LWrist"},
- // {8, "MidHip"},
- // {9, "RHip"},
- // {10, "RKnee"},
- // {11, "RAnkle"},
- // {12, "LHip"},
- // {13, "LKnee"},
- // {14, "LAnkle"},
- // {15, "REye"},
- // {16, "LEye"},
- // {17, "REar"},
- // {18, "LEar"},
- // {19, "LBigToe"},
- // {20, "LSmallToe"},
- // {21, "LHeel"},
- // {22, "RBigToe"},
- // {23, "RSmallToe"},
- // {24, "RHeel"},
- // {25, "Background"}
- // };
Vous pouvez également les vérifier sur Python :
Format des points clefs dans Datum (Avancé)
Cette section est réservée aux utilisateurs expérimentés prévoyant d'utiliser l'API C++. Elle n'est pas nécessaire pour la démonstration OpenPose et/ou l'API Python.
La classe Datum contient trois éléments Array<float> de points clés différents :
- Tableau posePoints clefs : Pour accéder à la personne personne et à la partie du corps partie (où l'index correspond à POSE_COCO_BODY_PARTS ou POSE_MPI_BODY_PARTS), vous pouvez simplement afficher :
- // Paramètres communs nécessaires
- const auto numberPeopleDetected = poseKeypoints.getSize(0);
- const auto numberBodyParts = poseKeypoints.getSize(1);
- // Version facile
- const auto x = poseKeypoints[{person, part, 0}];
- const auto y = poseKeypoints[{person, part, 1}];
- const auto score = poseKeypoints[{person, part, 2}];
- // Version légèrement plus efficace
- // Si vous souhaitez accéder à ces éléments dans une boucle volumineuse, vous pouvez obtenir l'index
- // vous-même, mais ce n'est généralement pas assez rapide pour être utile.
- const auto baseIndex = poseKeypoints.getSize(2)*(person*numberBodyParts + part);
- const auto x = poseKeypoints[baseIndex];
- const auto y = poseKeypoints[baseIndex + 1];
- const auto score = poseKeypoints[baseIndex + 2];
- Tableau faceKeypoints : il est complètement analogue à poseKeypoints :
- // Paramètres communs nécessaires
- const auto numberPeopleDetected = faceKeypoints.getSize(0);
- const auto numberFaceParts = faceKeypoints.getSize(1);
- // Version facile
- const auto x = faceKeypoints[{person, part, 0}];
- const auto y = faceKeypoints[{person, part, 1}];
- const auto score = faceKeypoints[{person, part, 2}];
- // Version légèrement plus efficace
- const auto baseIndex = faceKeypoints.getSize(2)*(person*numberFaceParts + part);
- const auto x = faceKeypoints[baseIndex];
- const auto y = faceKeypoints[baseIndex + 1];
- const auto score = faceKeypoints[baseIndex + 2];
- std::array<Array, 2> handKeypoints, où handKeypoints[0] correspond à la main gauche et handKeypoints[1] à la main droite. Chaque handKeypoints[i] est analogue à poseKeypoints et faceKeypoints :
- // Paramètres communs nécessaires
- const auto numberPeopleDetected = handKeypoints[0].getSize(0); // = handKeypoints[1].getSize(0)
- const auto numberHandParts = handKeypoints[0].getSize(1); // = handKeypoints[1].getSize(1)
- // Version facile
- // Main gauche
- const auto xL = handKeypoints[0][{person, part, 0}];
- const auto yL = handKeypoints[0][{person, part, 1}];
- const auto scoreL = handKeypoints[0][{person, part, 2}];
- // Main droite
- const auto xR = handKeypoints[1][{person, part, 0}];
- const auto yR = handKeypoints[1][{person, part, 1}];
- const auto scoreR = handKeypoints[1][{person, part, 2}];
- // Version légèrement plus efficace
- const auto baseIndex = handKeypoints[0].getSize(2)*(person*numberHandParts + part);
- // Main gauche
- const auto xL = handKeypoints[0][baseIndex];
- const auto yL = handKeypoints[0][baseIndex + 1];
- const auto scoreL = handKeypoints[0][baseIndex + 2];
- // Main droite
- const auto xR = handKeypoints[1][baseIndex];
- const auto yR = handKeypoints[1][baseIndex + 1];
- const auto scoreR = handKeypoints[1][baseIndex + 2];
Lecture des résultats enregistrés
Nous utilisons les formats standards (JSON, PNG, JPG,...) pour enregistrer nos résultats. Il existe donc de nombreuses bibliothèques open source permettant de les lire dans la plupart des langages de programmation (notamment Python). Pour C++, vous pouvez consulter include/openpose/filestream/fileStream.hpp. En particulier, loadData (pour les fichiers JSON, XML et YML) et loadImage (pour les formats d'image tels que PNG ou JPG) pour charger les données au format cv::Mat.
Avancé
Format de sortie de la matrice de caméra
Si vous devez utiliser les modules d'étalonnage de la caméra ou 3D, le format de sortie de la matrice de caméra est détaillé dans doc/advanced/calibration_module.md#camera-matrix-output-format.
Cartes thermiques
Si vous devez utiliser des cartes thermiques, consultez doc/advanced/heatmap_output.md.