Calcul des résultats avec Python
Fonction
Cette étape exécute un script défini par l’utilisateur via Python et envoie les résultats de calcul à Mech-Vision.
Les caractéristiques de cette étape sont les suivantes :
-
Prend en charge le multithreading.
-
Charge le script Python en temps réel.
-
Prend en charge diverses conversions de types de données lors du transfert de données entre C++ et Python.
-
Permet l’affichage du journal de Python dans le panneau de journal de Mech-Vision.
Scénario d’utilisation
Lorsqu’un calcul personnalisé est nécessaire, cette étape permet d’exécuter le script Python défini par l’utilisateur afin de simplifier le flux de travail de la solution.
Entrée et sortie
-
Entrée : déterminée par le type de données saisi dans le paramètre Input Port(s). Le renommage d’un port n’est pas pris en charge.
-
Sortie : déterminée par le type de données saisi dans le paramètre Output Port(s). Le renommage d’un port n’est pas pris en charge.
|
Vous pouvez spécifier le type de données du port d’entrée/de sortie en fonction du type de données du port d’entrée/de sortie des étapes précédentes ou suivantes. |
Installation et utilisation des bibliothèques Python
Installation des bibliothèques Python
Python 3.9.13 et deux bibliothèques Python courantes, NumPy et OpenCV, sont intégrés à Mech-Vision. L’étape « Calc Results by Python » utilisera l’environnement Python intégré pendant son exécution. S’il manque une bibliothèque Python lors de l’utilisation de cette étape, vous devez l’installer dans l’environnement Python intégré de Mech-Vision. La procédure d’installation est la suivante :
-
Accédez au répertoire d’installation de Python dans Mech-Vision.
-
Dans une zone vide du répertoire d’installation de Python, maintenez la touche Shift enfoncée et cliquez avec le bouton droit, puis sélectionnez Open PowerShell window here pour ouvrir l’outil en ligne de commande PowerShell.
-
Saisissez ".\python.exe -m pip install xxx" ("xxx" est le nom de la bibliothèque Python) dans la ligne de commande pour installer la bibliothèque manquante.
Instructions d’utilisation de l’étape
Après avoir préparé le script Python, veuillez suivre la procédure ci-dessous pour utiliser l’étape. Pour une description détaillée des paramètres, veuillez vous référer à Description des paramètres.
-
Définissez le type de données des ports d’entrée et de sortie. Saisissez le type de données pour Input Port(s) et Output Port(s) en fonction du type de données des ports d’entrée/de sortie des étapes précédentes ou suivantes.
-
Indiquez le chemin du fichier du script Python. Sélectionnez le chemin du fichier du script à charger dans le paramètre Script File Path.
-
Définissez le nom de la fonction à appeler. Une fois le Script File Path spécifié, cette étape récupère automatiquement les noms de fonctions présents dans le script et vous pouvez sélectionner le nom de la fonction à appeler dans la liste déroulante Function Name.
-
Exécutez l’étape.
|
|
À partir de Mech-Vision 1.8.0, le mode d’exécution de l’étape « Calc Results by Python » est passé de séquentiel à parallèle (conforme à l’effet du module threading en Python). Lors de l’appel, dans le script, d’API caméra ne prenant pas en charge l’exécution parallèle (par exemple l’énumération des caméras), il est nécessaire d’ajouter un verrou à l’emplacement de cet appel d’API. |
Remarques
Veuillez prêter attention aux points suivants lorsque vous écrivez le script Python et l’exécutez dans cette étape.
Utiliser des noms de fichiers valides
Les noms de fichiers des scripts Python ne peuvent contenir que des lettres, des chiffres, des traits de soulignement ou des caractères chinois. Par exemple : calc_result.py, test_01.py. Les traits d’union (-) ne sont pas autorisés, sinon le nom de la fonction ne pourra pas être appelé.
Les bibliothèques tierces sont recommandées
L’exécution d’un script Python dans Mech-Vision diffère de son exécution directement dans Python, ce qui peut entraîner l’échec de l’installation de certaines bibliothèques ou leur dysfonctionnement après installation. Il est donc recommandé d’utiliser des bibliothèques tierces.
Utiliser la bibliothèque NumPy
La bibliothèque NumPy est utilisée pour prendre en charge certains formats de données complexes. Si un type de paramètre est ndarray mais que NumPy n’a pas été importé, une erreur peut survenir. Vous devez donc ajouter l’instruction import numpy au début du script.
Prêter attention à la dimension des données lors de l’écriture du script
Lors de l’écriture du script Python, veillez à la dimension des données correspondant à chaque port de l’étape.
-
0 dimension par défaut : Image ; Cloud(XYZ) ; Cloud(XYZ-Normal)
-
1 dimension par défaut : NumberList ; BoolList ; IndexList ; StringList.
-
2 dimensions par défaut : PoseList ; Pose2DList ; Size3DList
|
Utilisez « [] » après le type de données pour ajouter une dimension. Par exemple, la dimension des données de NumberList est 1, tandis que celle de NumberList[] est 2. |
Description des paramètres
- Port(s) d’entrée
-
Description : Ce paramètre sert à spécifier le(s) type(s) de données du(des) port(s) d’entrée. Les types de données d’entrée seront transmis à la fonction appelée comme paramètres dans l’ordre correspondant.
Valeur par défaut : null.
- Port(s) de sortie
-
Description : Ce paramètre sert à spécifier le(s) type(s) de données du(des) port(s) de sortie. Les données renvoyées par la fonction seront renvoyées à l’étape dans l’ordre correspondant et seront analysées selon le type de données correspondant.
Valeur par défaut : null.
Les types de données actuellement pris en charge sont les suivants :
| Type de port de l’étape | Type de données utilisé dans Python | Exemple de données d’entrée |
|---|---|---|
PoseList |
Liste |
[[10, 20, 30, 0.951, 0.255, 0.168, 0.045]], [10, 20, 30, 0.951, 0.255, 0.168, 0.045]]
|
Pose2DList |
Liste |
[[0, 0, 0]], [2, 0, 120]]
|
NumberList |
Liste |
[1.1, 2, 999.9, -22] |
StringList |
Chaîne |
['string_1', 'string_2', 'string_3'] |
Image |
Entier non signé sur 8 bits (monocanal ou trois canaux)
|
En prenant pour exemple une image en niveaux de gris, qui n’a qu’un seul canal, les données d’entrée sont les suivantes :
|
Cloud(XYZ) |
Tableau |
[[0.1, 0.2, 0.3]], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5], [0.4, 0.5, 0.6], [0.5, 0.6, 0.7]]
|
Cloud(XYZ-Normal) |
Tableau |
[[0.1, 0.2, 0.3, 0.4, 0.5, 0.6]], [0.2, 0.3, 0.4, 0.5, 0.6, 0.7], [0.3, 0.4, 0.5, 0.6, 0.7, 0.8], [0.4, 0.5, 0.6, 0.7, 0.8, 0.9], [0.5, 0.6, 0.7, 0.8, 0.9, 1.0]]
|
Cloud(XYZ-RGB) |
Tableau |
[[0.1, 0.2, 0.3, 52, 64, 13]], [0.2, 0.3, 0.4, 45, 21, 72], [0.3, 0.4, 0.5, 17, 69, 13], [0.4, 0.5, 0.6, 12, 8, 37], [0.5, 0.6, 0.7, 25, 58, 46]]
|
Size3DList |
Nombre à virgule flottante 64 bits |
[[2.5, 5, 0.001]], [6, 5, 0.02]]
|
IndexList |
Entier |
[45, 10, 90] |
BoolList |
Booléen |
[True, False, True] |
- Chemin du fichier du script
-
Description : Ce paramètre sert à sélectionner le chemin du fichier du script à charger.
Valeur par défaut : null.
- Nom de la fonction
-
Description : Ce paramètre sert à définir le nom de la fonction à appeler.
Valeur par défaut : null.
Exemples de programmes Python
Pour faciliter l’apprentissage et l’utilisation de cette étape, quelques programmes Python sont fournis dans la section suivante pour vous aider à vous familiariser avec les types de ports de l’étape.
Prise en main
Sortir des données d’un seul type avec un script Python
La fonction qui renvoie des données d’un seul type est définie dans le programme ci-dessous. Veuillez vous référer à Instructions d’utilisation pour appeler cette fonction dans l’étape.
def get_doublelist():
return [1.1,22,3.3]
Le projet Mech-Vision correspondant à cette fonction est illustré ci-dessous. Vous pouvez double-cliquer sur le flux de données correspondant au port de sortie pour vérifier le résultat.
Sortir des données de plusieurs types avec un script Python
La fonction qui renvoie des données de plusieurs types est définie dans le programme ci-dessous. Veuillez vous référer à Instructions d’utilisation pour appeler cette fonction dans l’étape.
def example_of_basic_portTypes():
numList = [1.1, 2, 999.9, -22]
indexList = [45, 10, 90]
boolList = [True, False, True]
strList = ['string_1', 'string_2', 'string_3']
poseList = [[10, 20, 30, 0.951, 0.255, 0.168, 0.045], [10, 20, 30, 0.951, 0.255, 0.168, 0.045]]
pose2dList = [[0, 0, 0], [2, 0, 0.785]]
size3dList = [[2.5, 5, 0.001], [6, 5, 0.02]]
cloudXYZ = [[0.1, 0.2, 0.3], [0.2, 0.3, 0.4], [0.3, 0.4, 0.5], [0.4, 0.5, 0.6], [0.5, 0.6, 0.7]]
cloudXYZNormal = [[0.1, 0.2, 0.3, 0.4, 0.5, 0.6], [0.2, 0.3, 0.4, 0.5, 0.6, 0.7], [0.3, 0.4, 0.5, 0.6, 0.7, 0.8], [0.4, 0.5, 0.6, 0.7, 0.8, 0.9], [0.5, 0.6, 0.7, 0.8, 0.9, 1.0]]
cloudXYZRGB = [[0.1, 0.2, 0.3, 52, 64, 13], [0.2, 0.3, 0.4, 45, 21, 72], [0.3, 0.4, 0.5, 17, 69, 13], [0.4, 0.5, 0.6, 12, 8, 37], [0.5, 0.6, 0.7, 25, 58, 46]]
return numList, indexList, boolList, strList, poseList, pose2dList, size3dList, cloudXYZ, cloudXYZNormal, cloudXYZRGB
Le projet Mech-Vision correspondant à cette fonction est illustré ci-dessous. Vous pouvez double-cliquer sur les flux de données correspondant aux ports de sortie pour vérifier les résultats.
Traiter des données avec deux étapes « Calc Results by Python »
La fonction qui produit la liste de valeurs numériques est définie dans le programme 1. La fonction qui calcule la somme des valeurs de chaque liste numérique est définie dans le programme 2.
Veuillez vous référer à Instructions d’utilisation pour utiliser les programmes suivants, connecter les étapes et calculer la somme des listes numériques d’entrée.
Programme 1 :
def get_numberlist_1():
return [[1, 2, 3],[4,5,6]]
Programme 2 :
def cal_number_list(nums_list):
sums = []
for nums in nums_list:
sum = 0
for num in nums:
sum += num
sums.append(sum)
return [sums]
Le projet Mech-Vision correspondant à cette fonction est illustré ci-dessous. Vous pouvez double-cliquer sur les flux de données correspondant aux ports de sortie pour vérifier les résultats.
Traiter des données avec plusieurs étapes « Calc Results by Python »
La fonction qui produit la liste de valeurs numériques est définie dans le programme 1. La fonction qui produit des listes de booléens est définie dans le programme 2. Dans le programme 3, la valeur « 9999 » est ajoutée à la valeur numérique et un « False » est ajouté à la liste de booléens ; la nouvelle liste de valeurs numériques et la liste de booléens seront alors renvoyées.
Veuillez vous référer à Instructions d’utilisation pour utiliser les programmes suivants dans l’étape afin de traiter les données d’entrée.
Programme 1 :
def get_doublelist():
return [1.1,22,3.3]
Programme 2 :
def get_bool_list():
return [[True,False],[True,True],[False,False]]
Programme 3 :
def print_multi_values(numberList, boolList):
numberList.append(9999)
boolList.append(False)
return numberList, boolList
Le projet Mech-Vision correspondant à cette fonction est illustré ci-dessous. Vous pouvez double-cliquer sur les flux de données correspondant aux ports de sortie pour vérifier les résultats.
Exemples d’application
Enregistrer les données anormales générées pendant l’exécution du projet
En pratique, diverses erreurs peuvent survenir dans le projet. Vous pouvez utiliser un script Python personnalisé conjointement avec la fonctionnalité Data Storage de Mech-Vision pour enregistrer les données anormales à des fins de diagnostic, améliorant ainsi la stabilité du système de vision.
Les instructions détaillées sont les suivantes.
-
Activez la fonctionnalité Data Storage.
Activez Save data and parameters dans l’assistant de projet de Mech-Vision. Si des erreurs surviennent lors de l’exécution du projet, les données brutes seront enregistrées sous Project folder/data/error_data.
-
Rédigez le script Python.
Un exemple de programme Python qui détermine si le résultat de pose renvoyé par la procédure « 3D Matching » est nul est le suivant :
def abnormal_output_detection(outputs): if len(outputs) == 0: raise Exception("NO RESULT!!!") else: pass -
Veuillez vous référer à Instructions d’utilisation pour utiliser le programme ci-dessus dans l’étape, et placez l’étape après « 3D Matching ».
Après exécution du projet, si le résultat de pose renvoyé par « 3D Matching » est nul, un message d’erreur s’affichera et les données anormales seront enregistrées sous Project folder/data/error_data.
Générer un nuage de points pseudo-coloré à partir des valeurs Z du nuage de points d’entrée
Lorsque le nuage de points de sortie ne possède pas d’informations de texture, vous pouvez utiliser un script Python personnalisé pour générer un nuage de points pseudo-coloré basé sur les valeurs Z du nuage de points d’entrée afin d’améliorer la visualisation du résultat.
Le processus de traitement peut être résumé comme suit :
Tout d’abord, les valeurs Z sont mises en correspondance avec des valeurs entre 0 et 255 pour obtenir des niveaux de gris. Ensuite, OpenCV est utilisé pour convertir ces niveaux de gris en valeurs RGB, ce qui permet de générer le nuage de points pseudo-coloré.
Le programme d’exemple est le suivant :
import math
import cv2
import numpy as np
def generate_color_point_could_by_depth(point_cloud):
x = point_cloud[:, 0]
y = point_cloud[:, 1]
z = point_cloud[:, 2]
z_min = np.min(z)
z_max = np.max(z)
if math.isclose(z_max - z_min, 0):
return np.column_stack((x, y, z, np.full(z.shape, 0xFFFFFFFF, np.uint32).view(np.float32)))
color = 255 * (z - z_min) / (z_max - z_min)
color = cv2.applyColorMap(color.astype(np.uint8), cv2.COLORMAP_JET)
color = np.squeeze(color).astype(np.uint32)
color = (0xFF000000 | (color[:, 0] << 16) | (color[:, 1] << 8) | color[:, 2]).view(np.float32)
return np.column_stack((x, y, z, color))