Exécutez Python YOLOv3 en C ++ sur Visual Studio 2017

Contexte

Dans l'article précédent, j'ai résumé comment créer un environnement pour exécuter du code Python en C ++. Exécutez Python en C ++ sur Visual Studio 2017 Je ne pense pas que vous puissiez comprendre ** merci ** d'avoir appelé Python en C ++ à partir de cet article uniquement. Par conséquent, j'aimerais exécuter YOLO v3 qui peut détecter des objets par apprentissage en profondeur. Vous pouvez utiliser le modèle d'apprentissage en profondeur en C ++, mais ce n'est pas aussi bon que le Python actuel (pleurer).

Environnement de développement

・ Système d'exploitation: windos10 64 bits -CPU: Intel i3-8100 ・ GPU: NVIDIA GeForce GTX 1050 Ti ・ Visual Studio 2017 ・ C ++ ・ Python 3.7.3 Article précédent a des spécifications plus élevées que l'environnement ().

procédure

Les deux constructions d'environnement suivantes sont requises comme prérequis. Nous travaillerons sur chaque construction une fois qu'elle sera terminée. -Reportez-vous à l'article suivant pour savoir comment créer un environnement qui appelle Python en C ++. Exécutez Python en C ++ sur Visual Studio 2017 -Vérifiez l'article suivant pour savoir comment créer un environnement qui vous permet d'utiliser le GPU avec Python. Préférences tensorflow-gpu

Je voudrais continuer avec le flux suivant. Si vous le souhaitez, rejoignez-nous. Ceux qui sont venus des articles précédents peuvent sauter certaines étapes.

Extrayez le fichier git directement sous le lecteur C

Je souhaite extraire le fichier directement sous le lecteur C.

URL


git clone https://github.com/yusa0827/200121_Cplus2_with_Python

La méthode est 2.

  1. Si vous pouvez utiliser git clone, créez un dossier arbitraire directement sous le lecteur C et git clonez-le.
  2. Si vous ne pouvez pas utiliser git clone, accédez à l'URL ci-dessus, téléchargez-la et placez-la directement sous le lecteur C.

図1.png

Lancez .sln dans un fichier dans Visual Studio 2017

En regardant le contenu du dossier DL, il y a un fichier .sln. Parce que l'exemple de programme est inclus dans .sln Double-cliquez ici ou Faites un clic droit ⇒ Ouvrir à partir du programme ⇒ Cliquez sur Microsoft Visual Studio 2017 Ensuite, vous pouvez démarrer l'exemple de programme dans Visual Studio. Ce programme est construit avec ver2017. Je pense qu'il peut être utilisé en 2019, mais d'ici 2019 Je dois le déposer dans la version 2017.

図3.png

Définition du chemin d'environnement de l'exemple de programme

Vous devez modifier le chemin de l'environnement.

1.Configuration de la solution et plateforme de solution
Changé de Debug à Release
x86 → x64

2. C++→ Général → Inclure supplémentaire
C:\boost_1_70_0
C:\Users\○○\AppData\Local\Programs\Python\Python37\include 
↑ Correction requise

3. C++→ Génération de code → Avec bibliothèque d'exécution
Multithread (/Changer en MT)

4.Linker → Général → Répertoire de bibliothèque supplémentaire
C:\boost_1_70_0\stage\lib\x64
C:\Users\○○\AppData\Local\Programs\Python\Python37\libs
↑ Correction requise

Exécutez l'exemple de programme

Le résultat de l'exécution est le suivant. 図4.png

Si cela ne fonctionne pas, vérifiez le chemin de votre environnement.

Préparation pour YOLO v3

YOLOv3 est une méthode de détection d'objets qui utilise l'apprentissage en profondeur et se caractérise par ses excellentes performances en temps réel. Cette fois, nous utiliserons la version keras couramment utilisée. Beaucoup de gens apprennent à l'utiliser, donc si vous le recherchez sur Google, ce sera un coup, mais je vais le décrire.

Installation de la version keras de yolov3

URL


git clone https://github.com/qqwweee/keras-yolo3.git

Accédez à ce répertoire. (Cd keras-yolov3) Les modules requis pour Python incluent Tensorflow, Keras, Matplotlib, Pillow et opencv (installés avec opencv-python). Si vous ne l'avez pas encore installé sur python, veuillez l'installer avec pip.

Télécharger les fichiers appris

Vous pouvez également DL directement à partir de l'URL suivante sans utiliser wget. Après le téléchargement, placez-le dans le dossier keras-yolo3. Nom du fichier: yolov3.weights Taille: 237MB

URL


wget https://pjreddie.com/media/files/yolov3.weights

Convertir les fichiers formés

Passez à la version keras. Entrez le code suivant sur l'invite de commande.

python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5

Le résultat de l'exécution est le suivant.

:
:
conv2d_75 (Conv2D)              (None, None, None, 2 65535       leaky_re_lu_72[0][0]
==================================================================================================
Total params: 62,001,757
Trainable params: 61,949,149
Non-trainable params: 52,608
__________________________________________________________________________________________________
None
Saved Keras model to model_data/yolo.h5
Read 62001757 of 62001757.0 from Darknet weights.

C:\demo_Cplus2_Py_YOLOv3\keras-yolo3>

Détection d'objets en temps réel avec une webcam

Cette fois, nous utiliserons une webcam. Vous pouvez utiliser une vidéo au lieu d'une caméra, mais j'ai choisi cette option car la caméra était plus facile à vérifier.

Modifiez facilement yolo.py, le code principal pour la détection d'objets. C'est autour de la 173ème ligne.

yolo.py


    import cv2
    vid = cv2.VideoCapture(video_path)
    
    #↓ Corrigé ci-dessous

    import cv2
    #vid = cv2.VideoCapture(video_path)
    vid = cv2.VideoCapture(0)

Si vous donnez 0 à l'argument de VideoCapture, vous avez sélectionné l'appareil photo. Modifiez le code et exécutez YOLO V3.

Exécution de YOLO v3 et ses résultats

Code d'exécution.

cmd


python yolo_video.py

Résultat de l'exécution. Doraemon semble être un ballon de sport. 図5.png

J'ai pu confirmer que YOLO v3 fonctionne. Ensuite, je vais imaginer d'extraire le code Pyhton en C ++.

Extraire YOLO v3 avec C ++

Afin d'appeler YOLOv3 à partir de C ++, nous devons concevoir certaines choses. L'un d'eux est de définir l'objet généré à partir de la classe YOLO sur C ++. Normalement, la détection d'objet doit être effectuée en Python, mais si vous ne créez pas d'objet, vous devrez appeler Tensoflow à chaque fois que vous détectez un objet, ce qui entraînera un retard important. Il faut environ 15 secondes sur mon PC pour lancer Tensorflow. Par conséquent, en créant un objet YOLO à l'avance, il est possible d'empêcher chaque appel.

Modifiez le yolo.py.

Contenu du programme

Détectez les objets avec une webcam.

  1. Appelez Python en C ++
  2. Insérez l'image obtenue à partir de la webcam dans le détecteur d'objet d'apprentissage en profondeur YOLO v3
  3. Trouvez l'axe central de l'objet détecté sur l'axe horizontal (axe x) et renvoyez-le en C ++
  4. Sortie de l'axe central renvoyé par Python en C ++ Si vous n'avez pas de caméra Web, vous pouvez spécifier cv2.VideoCapture ("chemin vidéo") dans yolo.py.

organisation des fichiers

Préparez le fichier visul stusio cloné git et le fichier keras-yolo3. Copiez uniquement les fichiers keras-yolo3 requis pour la détection d'objet dans le fichier visul stusio. La configuration est la suivante. Modifiez les fichiers marqués d'un cercle. De plus, les fichiers requis pour YOLO v3 ont été placés directement sous le lecteur C.

Lecteur C ── modèle_data
       │  ├── yolo.h5 ← keras-modèle yolo3_Existe dans le dossier de données
       │  ├── yolo_anchors.txt ← keras-modèle yolo3_Existe dans le dossier de données
       │  ├── coco_classes.txt ← keras-modèle yolo3_Existe dans le dossier de données
       │  └── FiraMono-Medium.otf ← keras-Existe dans le dossier des polices de yolo3
       │  
       └─ 200121_Cplus2_with_Python
          ├── test_Cplus2_with_Python
          │  ├── test_Cplus2_with_Python.cpp 〇
          │  ├── x64
          │  └── others
          ├── x64
          │  └── Release
          │       ├── test_Cplus2_with_Python.exe
          │       ├── yolo3 ← keras-Existe dans le dossier yolo3
          │       ├── yolo.py 〇 ← keras-Existe dans le dossier yolo3
          │       └── others
          ├── (others( .git .vs))
          └── test_Cplus2_with_Python.sln

Correction du code principal

Il y a deux cercles dans la structure du fichier. C'est la partie principale du code de C ++ et Python, respectivement. Modifiez chacun comme suit.

Code principal C ++

J'ai apporté quelques corrections à l'article précédent. Il définit les fichiers py Python, les fonctions de fichier py, les objets, etc. Fondamentalement, c'est un type automatique et C ++ décide. Avant de tourner avec while, l'objet YOLO est défini à l'avance. Dans while, exécutez uniquement la fonction de détection d'objet de Pytohn. Si vous souhaitez ajouter un autre traitement original, insérez le code dans un endroit approprié.

test_Cplus2_with_Python.cpp


#define BOOST_PYTHON_STATIC_LIB
#define BOOST_NUMPY_STATIC_LIB

#include <iostream>
#include <boost/python.hpp>

//Définir l'espace de noms
namespace py = boost::python;

/*YOLO v3 C++Courir*/
int main()
{	
	//Initialiser Python
	Py_Initialize();
	//Fichier py YOLO v3(yolo.py)Importer
	py::object YOLOv3 = py::import("yolo").attr("__dict__");
	//yolo.En py"object_YOLOv3"Définir la fonction
	auto object_YOLOv3 = YOLOv3["object_YOLOv3"];
	//object_Définir des variables d'objet dans la fonction YOLOv3
	py::object object_YOLOv3_init;
	//object_Initialiser les variables d'objet dans la fonction YOLOv3
	auto object_YOLOv3_maker = object_YOLOv3(object_YOLOv3_init);
	//Définir une fonction pour la détection d'objets
	auto insert_object_YOLOv3 = YOLOv3["insert_object_YOLOv3"];
	//Valeur observée
	double py_y;
	
	/*Détection d'objets en temps réel par YOLO v3*/
	while (true) {

		//Déplacement sur l'axe X du centre détecté par l'objet par apprentissage profond
		auto x_centor = insert_object_YOLOv3(object_YOLOv3_maker);
		//Déplacement C++Convertir en un type pouvant être utilisé dans
		py_y = py::extract<double>(x_centor);

		/*
Si vous souhaitez traiter d'autres choses, décrivez de manière appropriée
		*/

		//commentaire
		std::cout << "py_y = " << py_y << std::endl;

	}
}

Code principal Python

Afin d'obtenir l'image de la webcam, l'objet qui a ouvert la webcam est défini dans l'initialisation (init) de la classe YOLO. De plus, le centre de l'axe horizontal qui a détecté l'objet est calculé et renvoyé. De plus, "1_fonction pour initialiser les objets" et "2_fonction pour détecter les objets" sont nouvellement ajoutées.

yolo.py


# -*- coding: utf-8 -*-
"""
Class definition of YOLO_v3 style detection model on image and video
"""
import colorsys
import os
from timeit import default_timer as timer
import numpy as np
from keras import backend as K
from keras.models import load_model
from keras.layers import Input
from PIL import Image, ImageFont, ImageDraw
from yolo3.model import yolo_eval, yolo_body, tiny_yolo_body
from yolo3.utils import letterbox_image
import os
from keras.utils import multi_gpu_model

#ajouter à
import cv2
#Ajouté: Limitation de l'utilisation de la mémoire GPU de TensorFlow
import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3
set_session(tf.Session(config=config))
#Ajouter une définition de variable globale
model_path_ = 'C:/model_data/yolo.h5'
anchors_path_ = 'C:/model_data/yolo_anchors.txt'
classes_path_ = 'C:/model_data/coco_classes.txt'
font_path_ = 'C:/model_data/FiraMono-Medium.otf'

class YOLO(object):
    _defaults = {
        "model_path": model_path_,#point de changement
        "anchors_path": anchors_path_,#point de changement
        "classes_path": classes_path_,#point de changement
        "score" : 0.3,
        "iou" : 0.45,
        "model_image_size" : (416, 416),
        "gpu_num" : 1,
    }

    @classmethod
    def get_defaults(cls, n):
        if n in cls._defaults:
            return cls._defaults[n]
        else:
            return "Unrecognized attribute name '" + n + "'"

    def __init__(self, **kwargs):
        self.__dict__.update(self._defaults) # set up default values
        self.__dict__.update(kwargs) # and update with user overrides
        self.class_names = self._get_class()
        self.anchors = self._get_anchors()
        self.sess = K.get_session()
        self.boxes, self.scores, self.classes = self.generate()
        #Caméra ajoutée ouverte
        self.cap = cv2.VideoCapture(0)

    def _get_class(self):
        classes_path = os.path.expanduser(self.classes_path)
        with open(classes_path) as f:
            class_names = f.readlines()
        class_names = [c.strip() for c in class_names]
        return class_names

    def _get_anchors(self):
        anchors_path = os.path.expanduser(self.anchors_path)
        with open(anchors_path) as f:
            anchors = f.readline()
        anchors = [float(x) for x in anchors.split(',')]
        return np.array(anchors).reshape(-1, 2)

    def generate(self):
        model_path = os.path.expanduser(self.model_path)
        assert model_path.endswith('.h5'), 'Keras model or weights must be a .h5 file.'

        # Load model, or construct model and load weights.
        num_anchors = len(self.anchors)
        num_classes = len(self.class_names)
        is_tiny_version = num_anchors==6 # default setting
        try:
            self.yolo_model = load_model(model_path, compile=False)
        except:
            self.yolo_model = tiny_yolo_body(Input(shape=(None,None,3)), num_anchors//2, num_classes) \
                if is_tiny_version else yolo_body(Input(shape=(None,None,3)), num_anchors//3, num_classes)
            self.yolo_model.load_weights(self.model_path) # make sure model, anchors and classes match
        else:
            assert self.yolo_model.layers[-1].output_shape[-1] == \
                num_anchors/len(self.yolo_model.output) * (num_classes + 5), \
                'Mismatch between model and given anchor and class sizes'

        print('{} model, anchors, and classes loaded.'.format(model_path))

        # Generate colors for drawing bounding boxes.
        hsv_tuples = [(x / len(self.class_names), 1., 1.)
                      for x in range(len(self.class_names))]
        self.colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
        self.colors = list(
            map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
                self.colors))
        np.random.seed(10101)  # Fixed seed for consistent colors across runs.
        np.random.shuffle(self.colors)  # Shuffle colors to decorrelate adjacent classes.
        np.random.seed(None)  # Reset seed to default.

        # Generate output tensor targets for filtered bounding boxes.
        self.input_image_shape = K.placeholder(shape=(2, ))
        if self.gpu_num>=2:
            self.yolo_model = multi_gpu_model(self.yolo_model, gpus=self.gpu_num)
        boxes, scores, classes = yolo_eval(self.yolo_model.output, self.anchors,
                len(self.class_names), self.input_image_shape,
                score_threshold=self.score, iou_threshold=self.iou)
        return boxes, scores, classes

    #Correction C++Correction de la position de détection d'objet pour
    def detect_image_for_Cplus2(self, image):

        if self.model_image_size != (None, None):
            assert self.model_image_size[0]%32 == 0, 'Multiples of 32 required'
            assert self.model_image_size[1]%32 == 0, 'Multiples of 32 required'
            boxed_image = letterbox_image(image, tuple(reversed(self.model_image_size)))
        else:
            new_image_size = (image.width - (image.width % 32),
                              image.height - (image.height % 32))
            boxed_image = letterbox_image(image, new_image_size)
        image_data = np.array(boxed_image, dtype='float32')

        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.

        out_boxes, out_scores, out_classes = self.sess.run(
            [self.boxes, self.scores, self.classes],
            feed_dict={
                self.yolo_model.input: image_data,
                self.input_image_shape: [image.size[1], image.size[0]],
                K.learning_phase(): 0
            })
        
        font = ImageFont.truetype(font=font_path_,
                    size=np.floor(3e-2 * image.size[1] + 0.5).astype('int32'))
        thickness = (image.size[0] + image.size[1]) // 300

        #Déplacement X de l'objet
        self.x_centor = .0

        for i, c in reversed(list(enumerate(out_classes))):           
                       
            predicted_class = self.class_names[c]
            box = out_boxes[i]
            score = out_scores[i]

            label = '{} {:.2f}'.format(predicted_class, score)
            draw = ImageDraw.Draw(image)
            label_size = draw.textsize(label, font)

            #Il y a une position du centre de gravité ici
            top, left, bottom, right = box
            top = max(0, np.floor(top + 0.5).astype('int32'))
            left = max(0, np.floor(left + 0.5).astype('int32'))
            bottom = min(image.size[1], np.floor(bottom + 0.5).astype('int32'))
            right = min(image.size[0], np.floor(right + 0.5).astype('int32'))
            print(label, (left, top), (right, bottom))

            #centre de gravité axe x x_centor = ( x1 + x2 ) / 2
            self.x_centor = ( left + right ) / 2.

            if top - label_size[1] >= 0:
                text_origin = np.array([left, top - label_size[1]])
            else:
                text_origin = np.array([left, top + 1])

            # My kingdom for a good redistributable image drawing library.
            for i in range(thickness):
                draw.rectangle(
                    [left + i, top + i, right - i, bottom - i],
                    outline=self.colors[c])
            draw.rectangle(
                [tuple(text_origin), tuple(text_origin + label_size)],
                fill=self.colors[c])
            draw.text(text_origin, label, fill=(0, 0, 0), font=font)
            del draw

        return image, self.x_centor

    def close_session(self):
        self.sess.close()

# 1_Fonction d'initialisation d'un objet
def object_YOLOv3(object_YOLO):
    #Créer un objet à partir d'une classe
    object_YOLO = YOLO()
    #C++Renvoie un objet yolo à
    return object_YOLO

# 2_Fonction de détection d'objets
def insert_object_YOLOv3(object_YOLO):    
    #Obtenir l'image de la caméra
    ret, frame = object_YOLO.cap.read()
    #Changer l'ordre de RGGB
    frame = np.asarray(frame)[..., ::-1]
    #Passer de l'ouverture à l'oreiller
    frame = Image.fromarray(frame)
    #Détecte un objet et renvoie le résultat de sortie et le centre de l'axe des x de l'objet
    r_image, x_centor = object_YOLO.detect_image_for_Cplus2(frame)
    #Affichage de l'image
    cv2.imshow("out",np.asarray(r_image)[..., ::-1])
    #1 ms pour afficher
    cv2.waitKey(1)
    #C++Renvoie le centre de l'axe des x de l'objet
    return x_centor

Résultat d'exécution

Puisqu'il utilise un modèle entraîné, il est détecté en tant que personne, etc. ダウンロード.gif

Puisqu'il s'agit d'un exemple de programme, même si vous souhaitez utiliser le modèle d'origine, vous pouvez l'utiliser simplement en modifiant le chemin d'accès dans le fichier py.

Utiliser des applications

Quand dois-je appeler Python en C ++ ... Je pense que certaines personnes sont inquiètes. La raison est -Lorsque vous souhaitez vraiment intégrer le traitement du deep learning sur un appareil compatible C ++ (carte de contrôle de mouvement, etc.) ・ Un ingénieur préféré (personne étrange) qui ne peut pas quitter C ++ ・ Quoi qu'il en soit, bizarre C'est tout pour la blague.

commentaire

Nous espérons sincèrement qu'il sera utile pour ceux qui s'inquiètent de la dépendance environnementale entre les langues du programme.

Recommended Posts

Exécutez Python YOLOv3 en C ++ sur Visual Studio 2017
Exécutez Python en C ++ sur Visual Studio 2017
Développement Python avec Visual Studio 2017
Développement Python avec Visual Studio
Exécutez AzureKinect en Python la veille de Noël.
Bash, Python, Javascript, commande de code, etc. dans Visual Studio Code sur Mac
Next Python en langage C
Remarque sur l'encodage lorsque LANG = C en Python
API C en Python 3
Paramètres de codage Python avec Visual Studio Code
TensorFlow: exécuter des données apprises en Python sur Android
Développement d'applications pour tweeter en Python à partir de Visual Studio 2017
Essayez de déboguer Python sur Raspberry Pi avec Visual Studio.
Exécutez CGI écrit en python sur le serveur de location de Sakura
Jusqu'à ce que vous exécutiez le serveur Django avec Visual Studio Code
Sortie japonaise lors de l'utilisation de python dans Visual Studio
Développement du kit SDK AWS pour Python (Boto3) dans Visual Studio 2017
Étendre python en C ++ (Boost.NumPy)
Exécutez Openpose sur Python (Windows)
Installez numpy dans Visual Studio 2019
Exécuter des commandes shell en Python
Exécuter Python unittest en parallèle
Exécutez Tensorflow 2.x sur Python 3.7
Recherche binaire en Python / C ++
Exécutez le CGI de Python sur CORESERVER
Bottle Pug dans Visual Studio 2019
Exécutez la commande unix sur python
Comment déboguer une bibliothèque Python standard dans Visual Studio
Faites quelque chose comme un interpréteur Python avec Visual Studio Code
Installer python et Visual Studio Code sur Windows10 (version d'avril 2020)
Créer Python3 pour Windows 10 sur ARM avec Visual Studio 2019 (x86) sur Windows 10 sur ARM
Lançons "python -m antigravity" en python
ABC166 en Python A ~ C problème
Exécutez Python selon la planification sur AWS Lambda
Exécutez l'image Docker de TensorFlow sur Python3
Résoudre ABC036 A ~ C avec Python
Comment envelopper C en Python
Débogage à distance dans Visual Studio (Linux)
Exécutez des scripts Python de manière synchrone à partir de C #
Exécutez unittest en Python (pour les débutants)
Résoudre ABC037 A ~ C avec Python
Exécutez un algorithme simple en Python
Ecrire un test unitaire de langage C en Python
Appeler C / C ++ depuis Python sur Mac
Exécutez régulièrement Python sur Heroku Scheduler
Comment installer OpenCV sur Cloud9 et l'exécuter en Python
Une note à ceux qui utilisent Python dans Visual Studio (moi)
Exécutez Python en C ++ sur Visual Studio 2017
Exécutez Python YOLOv3 en C ++ sur Visual Studio 2017
Essayez de déboguer Python sur Raspberry Pi avec Visual Studio.
Sortie japonaise lors de l'utilisation de python dans Visual Studio
Installation du code Visual Studio et installation de python
Créez des raccourcis pour exécuter des fichiers Python sur le terminal avec VScode
Exécutez le servo avec Python sur ESP32 (Windows)
Comment masquer l'invite de commande lors de l'exécution de python dans Visual Studio 2015
Trouver des fichiers comme Linux Find en Python
Note de nfc.ContactlessFrontend () de nfcpy de python
Algorithme en Python (ABC 146 C Dichotomy
Implémenter le filtre FIR en langage Python et C
[Python] Exécutez Flask sur Google App Engine
Créez un environnement de développement Python sur Windows (WSL distant Visual Studio Code).
[C] [python] Lire avec AquesTalk sous Linux
Ecrire le fichier O_SYNC en C et Python