[PYTHON] J'ai essayé de déplacer l'apprentissage automatique (détection d'objet) avec TouchDesigner

introduction

Pendant mes études, je voulais déplacer le modèle que j'avais créé de manière appropriée dans Touch Designer, alors je l'ai essayé.

Quand je l'essaye, ça ressemble à ça! (Il est différent du modèle utilisé dans cet article, mais il ressemble à ceci)

https://www.youtube.com/watch?v=ycBvOQUzisU

Le référentiel d'exemples est ici!

Au fait, cette fois j'ai écrit un article en supposant Windows, mais cela peut aussi fonctionner sur Mac!

À propos de Python dans Touch Designer

TouchDesigner vous permet d'utiliser Python comme extension (Python 3.7.2 semble fonctionner en interne dans mon environnement).

Vous pouvez utiliser l'interpréteur Python à partir de Dialogues> Textport et DAT.

En pré-installation, vous pouvez utiliser des bibliothèques standard, OpenCV, numpy, etc.

touch1.png

Cette fois, en plus de cela, j'aimerais utiliser une bibliothèque souvent utilisée dans l'apprentissage automatique pour effectuer la détection d'objets dans Touch Desginer.

La façon de le faire est de spécifier le chemin vers la bibliothèque externe dans "Ajouter Python externe au chemin de recherche" de Edition> Préférences afin qu'il puisse être utilisé dans Touch Designer.

À propos de la détection d'objets

Je n'expliquerai pas les détails d'ObjectDetection, mais c'est comme détecter des objets tels que des personnes et des choses comme l'image ci-dessous (entourées d'un carré pour indiquer ce que c'est).

result.png

Cette fois, je vais essayer d'utiliser MobileNetv2-SSD, qui fonctionne sur les terminaux mobiles, avec l'esprit d'essayer de gagner des FPS en adoptant un algorithme le plus léger possible!

En tant que bibliothèque (framework) qui gère l'apprentissage automatique (principalement DNN) en Python

Quelque chose existe.

Je traite généralement ** Tensorflow / Keras ** (parfois j'utilise aussi Pytorch), mais cette fois j'utilise ONNX. (Pour être exact, il utilise un environnement d'inférence appelé ONNX Runtime)

La raison en est que dans mon environnement, lors de l'utilisation de Tensorflow ou Pytorch de Python dans TouchDesigner, TouchDesigner se bloque sans lancer de message d'erreur.

Après cela, j'ai essayé ONNX sans aucune utilité et cela a fonctionné, donc je vais l'utiliser! (Je ne connais pas MXNet ...)

Pour le modèle essentiel, nous avons préparé un modèle créé avec Tensorflow et exporté au format ONNX. (Inclus dans Repository)

Environnement de travail

1. Construction de l'environnement

Une fois que vous avez un environnement de travail, essayez d'installer ONNX!

1-1. Créer un environnement virtuel avec Anaconda

$conda create -n touchdesigner python=3.7.2

1-2. Installez ONNX dans l'environnement virtuel

$source activate touchdesigner
$pip install onnxruntime==1.1.0

1-3. Passez le chemin de l'environnement virtuel via Touch Designer

Cliquez sur Modifier> Préférences pour ouvrir les Préférences.

Cochez "Ajouter Python externe au chemin de recherche" comme indiqué dans l'image ci-dessous, et passez le chemin vers l'environnement virtuel d'Anaconda à "Chemin du module Python 64 bits".

touch2.png

Dans mon environnement, je suivrais le chemin suivant.

C:/Users/T-Sumida/Anaconda3/envs/touchdesigner/Lib/site-packages

Veuillez vous y référer et essayer le chemin!

2. Préparation d'ONNX

Maintenant, confirmons que ONNX fonctionne sur Touch Desiger!

Lancez l'interpréteur Python à partir de Dialogues> Textport et DAT, collez-y le code suivant et exécutez-le.

** * Veuillez définir le chemin d'accès au modèle et le chemin de l'image que vous souhaitez essayer de manière appropriée. ** **

import cv2
import numpy as np
import onnxruntime

#numéro de classe du jeu de données coco: nom de la classe
coco_classes = {
    1: 'person',
    2: 'bicycle',
    3: 'car',
    4: 'motorcycle',
    5: 'airplane',
    6: 'bus',
    7: 'train',
    8: 'truck',
    9: 'boat',
    10: 'traffic light',
    11: 'fire hydrant',
    12: 'stop sign',
    13: 'parking meter',
    14: 'bench',
    15: 'bird',
    16: 'cat',
    17: 'dog',
    18: 'horse',
    19: 'sheep',
    20: 'cow',
    21: 'elephant',
    22: 'bear',
    23: 'zebra',
    24: 'giraffe',
    25: 'backpack',
    26: 'umbrella',
    27: 'handbag',
    28: 'tie',
    29: 'suitcase',
    30: 'frisbee',
    31: 'skis',
    32: 'snowboard',
    33: 'sports ball',
    34: 'kite',
    35: 'baseball bat',
    36: 'baseball glove',
    37: 'skateboard',
    38: 'surfboard',
    39: 'tennis racket',
    40: 'bottle',
    41:'wine glass',
    42: 'cup',
    43: 'fork',
    44: 'knife',
    45: 'spoon',
    46: 'bowl',
    47: 'banana',
    48: 'apple',
    49: 'sandwich',
    50: 'orange',
    51: 'broccoli',
    52: 'carrot',
    53: 'hot dog',
    54: 'pizza',
    55: 'donut',
    56: 'cake',
    57: 'chair',
    58: 'couch',
    59: 'potted plant',
    60: 'bed',
    61: 'dining table',
    62: 'toilet',
    63: 'tv',
    64: 'laptop',
    65: 'mouse',
    66: 'remote',
    67: 'keyboard',
    68: 'cell phone',
    69: 'microwave',
    70: 'oven',
    71: 'toaster',
    72: 'sink',
    73: 'refrigerator',
    74: 'book',
    75: 'clock',
    76: 'vase',
    77: 'scissors',
    78: 'teddy bear',
    79: 'hair drier',
    80: 'toothbrush'
}

#Chargez le modèle
session = onnxruntime.InferenceSession("Spécifiez le chemin d'accès au modèle ONNX")

#Charger l'image
img = cv2.imread("Spécifiez le chemin de l'image que vous souhaitez essayer")

#OpenCV lit les données d'image avec BGR, alors convertissez-les en BGR
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

width, height = img.shape[0], img.shape[1]

img_data = np.expand_dims(img, axis=0)

#Préparation de l'inférence de modèle
input_name = session.get_inputs()[0].name   # 'image'
output_name_boxes = session.get_outputs()[0].name     # 'boxes'
output_name_classes = session.get_outputs()[1].name   # 'classes'
output_name_scores = session.get_outputs()[2].name    # 'scores'
output_name_num = session.get_outputs()[3].name       # 'number of detections'

#inférence
outputs_index = session.run(
    [output_name_num, output_name_boxes, output_name_scores, output_name_classes],
    {input_name: img_data}
)

#Recevoir des résultats
output_num = outputs_index[0] #Nombre d'objets détectés
output_boxes = outputs_index[1] #Boîte indiquant l'emplacement de l'objet détecté
output_scores = outputs_index[2] #Probabilité de prédiction de l'objet détecté
output_classes = outputs_index[3] #Numéro de classe de l'objet détecté

#Seuil de probabilité de prédiction
threshold = 0.6

#Convertir les résultats d'inférence en images
img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
for detection in range(0, int(output_num[0])):
    if output_scores[0][detection] > threshold:
        classes = output_classes[0][detection]
        boxes = output_boxes[0][detection]
        scores = output_scores[0][detection]
        top = boxes[0] * width
        left = boxes[1] * height
        bottom = boxes[2] * width
        right = boxes[3] * height

        top = max(0, top)
        left = max(0, left)
        bottom = min(width, bottom)
        right = min(height, right)
        img = cv2.rectangle(img, (int(left), int(top)), (int(right), int(bottom)), (0,0,255), 3)
        img = cv2.putText(
        	img, "{}: {:.2f}".format(coco_classes[classes], scores),
        	(int(left), int(top)),
        	cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA
        )

cv2.imshow('img', img)
k = cv2.waitKey(0)

Lorsque vous l'exécutez, l'image suivante sera dessinée.

result.png

Si cela fonctionne bien, ça va!

3. Écrivez Python avec Touch Designer

Ensuite, nous allons le faire fonctionner avec le patch Touch Desiger.

Je vais me référer à cet article (merci!) Et faire une détection d'objet pour l'entrée de l'image de la caméra.

https://qiita.com/komakinex/items/5b84b88d537d393afc98

Le projet lui-même est très simple, et je l'ai fait quelque chose comme recevoir l'entrée de "Video Device In" avec "OP Execute" et dessiner avec la fonction Opencv.

Le contenu de "OP Execute" est le suivant.

# me - this DAT.
# changeOp - the operator that has changed
#
# Make sure the corresponding toggle is enabled in the OP Execute DAT.

import cv2
import numpy as np
import onnxruntime

#Comme c'est le même que le test ci-dessus, il est omis (lors de son utilisation, copiez-le par le haut et utilisez-le)
coco_classes = {
    1: 'person',
    2: 'bicycle',
    ...
}

session = onnxruntime.InferenceSession("C:/Users/TomoyukiSumida/Documents/Hatena/ObjetDetection4TD/ssdlite_mobilenetv2.onnx")

def onPreCook(changeOp):
	return

def onPostCook(changeOp):
	#Chargement des images
	frame = changeOp.numpyArray(delayed=True)
	arr = frame[:, :, 0:3]
	arr = arr * 255
	arr = arr.astype(np.uint8)
	arr = np.flipud(arr)
	width, height = arr.shape[0:2]
	image_data = np.expand_dims(arr, axis=0)

	#Préparation de l'inférence de modèle
	input_name = session.get_inputs()[0].name   # 'image'
	output_name_boxes = session.get_outputs()[0].name     # 'boxes'
	output_name_classes = session.get_outputs()[1].name   # 'classes'
	output_name_scores = session.get_outputs()[2].name    # 'scores'
	output_name_num = session.get_outputs()[3].name       # 'number of detections'

	#inférence
	outputs_index = session.run([output_name_num, output_name_boxes,
                                output_name_scores, output_name_classes],
                                {input_name: image_data})

	#Recevoir des résultats
	output_num = outputs_index[0] #Nombre d'objets détectés
	output_boxes = outputs_index[1] #Boîte indiquant l'emplacement de l'objet détecté
	output_scores = outputs_index[2] #Probabilité de prédiction de l'objet détecté
	output_classes = outputs_index[3] #Numéro de classe de l'objet détecté

	#Seuil de probabilité de prédiction
	threshold = 0.6

	#Convertir les résultats d'inférence en images
	for detection in range(0, int(output_num[0])):
		if output_scores[0][detection] > threshold:
			classes = output_classes[0][detection]
			boxes = output_boxes[0][detection]
			scores = output_scores[0][detection]
			top = boxes[0] * width
			left = boxes[1] * height
			bottom = boxes[2] * width
			right = boxes[3] * height

			top = max(0, top)
			left = max(0, left)
			bottom = min(width, bottom)
			right = min(height, right)
			arr = cv2.rectangle(arr, (int(left), int(top)), (int(right), int(bottom)), (0,0,255), 3)
			arr = cv2.putText(
				arr, "{}: {:.2f}".format(coco_classes[classes], scores),
				(int(left), int(top)),
				cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2, cv2.LINE_AA)
	arr = cv2.cvtColor(arr, cv2.COLOR_RGB2BGR)
	cv2.imshow('img', arr)
	return

def onDestroy():
	return

def onFlagChange(changeOp, flag):
	return

def onWireChange(changeOp):
	return

def onNameChange(changeOp):
	return

def onPathChange(changeOp):
	return

def onUIChange(changeOp):
	return

def onNumChildrenChange(changeOp):
	return

def onChildRename(changeOp):
	return

def onCurrentChildChange(changeOp):
	return

def onExtensionChange(changeOp, extension):
	return


Si vous pouvez écrire ceci, spécifiez "Video Device In" dans Monitor OPs de "OP Execute" et activez Post Cook.

**déplacé! ** **

example.png

en conclusion

Cette fois, j'ai essayé de déplacer la détection d'objets en utilisant ONNX dans Touch Designer. J'avais des problèmes parce que Tensorflow n'a pas fonctionné pour une raison quelconque, mais je suis content d'avoir réussi à faire quelque chose qui fonctionne.

Cependant, l'exécution de la détection d'objets (et donc de l'apprentissage automatique) dans TouchDesigner présente les inconvénients suivants.

Par conséquent, il est préférable de démarrer un processus Python derrière TouchDesigner et d'envoyer des informations à partir de là avec OSC (cela peut être utile si le multithreading peut être utilisé avec TouchDesigner à l'avenir).

J'ai également essayé le modèle ONNX avec mon propre modèle cette fois, mais il est possible de télécharger le fichier de modèle depuis onnx / model et de l'utiliser. (J'ai également téléchargé mask-rcnn à partir de là et confirmé que cela fonctionne)

De plus, l'inférence à grande vitesse à l'aide du GPU est également possible. (Ce modèle en utilisait un qui fonctionne à grande vitesse même avec un processeur)

$pip install onnxruntime==1.1.0

Au lieu de cela

$pip install onnxruntime-gpu==1.1.0

Si vous installez cela, l'inférence sera effectuée sur le GPU. Est-ce intéressant d'essayer diverses choses?

Le côté expression a été difficile à atteindre, mais je pense que je devrais aborder ce domaine à l'avenir!

Recommended Posts

J'ai essayé de déplacer l'apprentissage automatique (détection d'objet) avec TouchDesigner
J'ai essayé l'apprentissage automatique avec liblinear
J'ai essayé de déplacer GAN (mnist) avec keras
(Apprentissage automatique) J'ai essayé de comprendre attentivement la régression linéaire bayésienne avec l'implémentation
J'ai essayé de visualiser le modèle avec la bibliothèque d'apprentissage automatique low-code "PyCaret"
J'ai essayé de déplacer Faster R-CNN rapidement avec pytorch
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
J'ai essayé d'apprendre LightGBM avec Yellowbrick
J'ai essayé de déplacer le ballon
Oncle SE avec un cerveau endurci a essayé d'étudier l'apprentissage automatique
J'ai essayé l'apprentissage automatique pour convertir des phrases en style XX
Mayungo's Python Learning Episode 3: J'ai essayé d'imprimer des nombres
J'ai essayé d'implémenter ListNet d'apprentissage de rang avec Chainer
[Apprentissage automatique] J'ai essayé de résumer la théorie d'Adaboost
J'ai essayé d'écrire dans un modèle de langage profondément appris
J'ai essayé de faire une simulation de séparation de source sonore en temps réel avec l'apprentissage automatique Python
J'ai essayé de créer un environnement d'apprentissage automatique avec Python (Mac OS X)
J'ai essayé d'implémenter Autoencoder avec TensorFlow
J'ai essayé de visualiser AutoEncoder avec TensorFlow
J'ai essayé de rendre le deep learning évolutif avec Spark × Keras × Docker
J'ai essayé de commencer avec Hy
J'ai installé Python 3.5.1 pour étudier l'apprentissage automatique
J'ai essayé d'apprendre avec le Titanic de Kaggle (kaggle②)
J'ai essayé d'implémenter CVAE avec PyTorch
J'ai essayé de résoudre TSP avec QAOA
[Apprentissage automatique] J'ai essayé de faire quelque chose comme passer des images
J'ai essayé de créer Othello AI avec tensorflow sans comprendre la théorie de l'apprentissage automatique ~ Introduction ~
J'ai essayé de créer Othello AI avec tensorflow sans comprendre la théorie de l'apprentissage automatique ~ Implémentation ~
J'ai essayé de mettre en œuvre un apprentissage en profondeur qui n'est pas profond avec uniquement NumPy
Mayungo's Python Learning Episode 2: J'ai essayé de mettre des caractères avec des variables
J'ai essayé de classer les accords de guitare en temps réel en utilisant l'apprentissage automatique
J'ai commencé l'apprentissage automatique avec Python (j'ai également commencé à publier sur Qiita) Préparation des données
J'ai essayé de prédire l'année prochaine avec l'IA
[Python] Introduction facile à l'apprentissage automatique avec python (SVM)
J'ai essayé d'implémenter la lecture de Dataset avec PyTorch
J'ai essayé d'utiliser lightGBM, xg boost avec Boruta
J'ai essayé d'apprendre le fonctionnement logique avec TF Learn
J'ai essayé de sauvegarder les données avec discorde
J'ai essayé de détecter rapidement un mouvement avec OpenCV
J'ai essayé d'intégrer Keras dans TFv1.1
J'ai essayé d'obtenir des données CloudWatch avec Python
J'ai essayé de sortir LLVM IR avec Python
J'ai essayé de détecter un objet avec M2Det!
J'ai essayé d'automatiser la fabrication des sushis avec python
J'ai essayé de prédire la survie du Titanic avec PyCaret
J'ai commencé l'apprentissage automatique avec le prétraitement des données Python
J'ai essayé d'utiliser Linux avec Discord Bot
J'ai essayé d'étudier DP avec séquence de Fibonacci
J'ai essayé de démarrer Jupyter avec toutes les lumières d'Amazon
J'ai essayé de juger Tundele avec Naive Bays
[Mac] J'ai essayé de renforcer l'apprentissage avec Open AI Baselines
(Apprentissage automatique) J'ai essayé de comprendre attentivement l'algorithme EM dans la distribution gaussienne mixte avec l'implémentation.
J'ai essayé le deep learning
J'ai essayé de déboguer.
Introduction à l'apprentissage automatique
J'ai essayé de créer Othello AI avec tensorflow sans comprendre la théorie de l'apprentissage automatique ~ Battle Edition ~
J'ai essayé d'organiser les index d'évaluation utilisés en machine learning (modèle de régression)
Mayungo's Python Learning Episode 5: J'ai essayé de faire quatre règles avec des nombres