Im vorherigen Artikel habe ich zusammengefasst, wie eine Umgebung zum Ausführen von Python-Code in C ++ erstellt wird. Führen Sie Python in C ++ unter Visual Studio 2017 aus Ich glaube nicht, dass Sie verstehen können, danke, dass Sie Python in C ++ allein aus diesem Artikel heraus aufgerufen haben. Daher möchte ich YOLO v3 ausführen, das Objekte durch tiefes Lernen erkennen kann. Sie können das Deep-Learning-Modell in C ++ verwenden, es ist jedoch nicht so gut wie das aktuelle Python (Weinen).
・ Betriebssystem: windos10 64bit -CPU: Intel i3-8100 ・ GPU: NVIDIA GeForce GTX 1050 Ti ・ Visual Studio 2017 ・ C ++ ・ Python 3.7.3 Vorheriger Artikel hat höhere Spezifikationen als die Umgebung ().
Die folgenden zwei Umgebungskonstruktionen sind als Voraussetzungen erforderlich. Wir werden an jeder Konstruktion arbeiten, nachdem sie fertiggestellt ist.
Ich möchte mit dem folgenden Ablauf fortfahren. Wenn Sie möchten, schließen Sie sich uns bitte an. Diejenigen, die aus früheren Artikeln stammen, können einige der Schritte überspringen.
Ich möchte die Datei direkt unter dem Laufwerk C extrahieren.
URL
git clone https://github.com/yusa0827/200121_Cplus2_with_Python
Die Methode ist 2.
Wenn Sie sich den Inhalt des DL-Ordners ansehen, finden Sie eine SLN-Datei. Weil das Beispielprogramm in .sln enthalten ist Doppelklicken Sie hier oder Rechtsklick ⇒ Aus Programm öffnen ⇒ Klicken Sie auf Microsoft Visual Studio 2017 Anschließend können Sie das Beispielprogramm in Visual Studio starten. Dieses Programm wurde mit ver2017 erstellt. Ich denke, es kann im Jahr 2019 verwendet werden, aber innerhalb von 2019 Ich muss es auf die Version 2017 fallen lassen.
Sie müssen den Umgebungspfad ändern.
1.Lösungskonfiguration und Lösungsplattform
Von Debug zu Release geändert
x86 → x64
2. C++→ Allgemein → Zusätzliches Include
C:\boost_1_70_0
C:\Users\○○\AppData\Local\Programs\Python\Python37\include
↑ Korrektur erforderlich
3. C++→ Codegenerierung → Mit Laufzeitbibliothek
Multi Thread(/Wechsel zu MT)
4.Linker → Allgemein → Zusätzliches Bibliotheksverzeichnis
C:\boost_1_70_0\stage\lib\x64
C:\Users\○○\AppData\Local\Programs\Python\Python37\libs
↑ Korrektur erforderlich
Das Ausführungsergebnis ist wie folgt.
Wenn dies nicht funktioniert, überprüfen Sie Ihren Umgebungspfad.
YOLOv3 ist eine Objekterkennungsmethode, die Deep Learning verwendet und sich durch eine hervorragende Echtzeitleistung auszeichnet. Dieses Mal werden wir die häufig verwendete Keras-Version verwenden. Viele Leute lehren, wie man es benutzt. Wenn Sie es also googeln, wird es ein Schuss sein, aber ich werde es beschreiben.
URL
git clone https://github.com/qqwweee/keras-yolo3.git
Gehen Sie in dieses Verzeichnis. (Cd keras-yolov3) Erforderliche Module für Python sind Tensorflow, Keras, Matplotlib, Pillow und opencv (installiert mit opencv-python). Wenn Sie es noch nicht auf Python installiert haben, installieren Sie es bitte mit pip.
Sie können DL auch direkt von der folgenden URL aus verwenden, ohne wget zu verwenden. Legen Sie es nach dem Herunterladen im Ordner keras-yolo3 ab. Dateiname: yolov3.weights Größe: 237 MB
URL
wget https://pjreddie.com/media/files/yolov3.weights
Wechseln Sie zur Keras-Version. Geben Sie den folgenden Code an der Eingabeaufforderung ein.
python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
Das Ausführungsergebnis ist wie folgt.
:
:
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>
Dieses Mal werden wir eine Webkamera verwenden. Sie können ein Video anstelle einer Kamera verwenden, aber ich habe dies gewählt, weil die Kamera leichter zu überprüfen war.
Bearbeiten Sie einfach yolo.py, den Hauptcode für die Objekterkennung. Es ist um die 173. Linie.
yolo.py
import cv2
vid = cv2.VideoCapture(video_path)
#↓ Unten korrigiert
import cv2
#vid = cv2.VideoCapture(video_path)
vid = cv2.VideoCapture(0)
Wenn Sie dem Argument von VideoCapture 0 geben, haben Sie das Kameragerät ausgewählt. Bearbeiten Sie den Code und führen Sie YOLO V3 aus.
Ausführungscode.
cmd
python yolo_video.py
Ausführungsergebnis. Doraemon scheint ein Sportball zu sein.
Ich konnte bestätigen, ob YOLO v3 funktioniert. Als nächstes werde ich den Pyhton-Code in C ++ ziehen.
Um YOLOv3 von C ++ aus aufzurufen, müssen wir einige Dinge entwickeln. Eine davon besteht darin, das aus der YOLO-Klasse in C ++ generierte Objekt zu definieren. Normalerweise sollte die Objekterkennung in Python erfolgen. Wenn Sie jedoch kein Objekt erstellen, müssen Sie Tensoflow jedes Mal aufrufen, wenn Sie ein Objekt erkennen, was zu einer großen Verzögerung führt. Auf meinem PC dauert es ungefähr 15 Sekunden, um Tensorflow zu starten. Daher ist es durch vorheriges Erstellen eines YOLO-Objekts möglich, jeden Aufruf zu verhindern.
Ändern Sie die vorhandene Datei yolo.py.
Erkennen Sie Objekte mit einer Webkamera.
Bereiten Sie die git-geklonte visul stusio-Datei und die keras-yolo3-Datei vor. Kopieren Sie nur die für die Objekterkennung erforderlichen keras-yolo3-Dateien in die visul stusio-Datei. Die Konfiguration ist wie folgt. Ändern Sie die mit einem Kreis markierten Dateien. Außerdem wurden die für YOLO v3 erforderlichen Dateien direkt unter dem Laufwerk C abgelegt.
C-Laufwerk ── Modell_data
│ ├── yolo.h5 ← keras-yolo3 Modell_Existiert im Datenordner
│ ├── yolo_anchors.txt ← keras-yolo3 Modell_Existiert im Datenordner
│ ├── coco_classes.txt ← keras-yolo3 Modell_Existiert im Datenordner
│ └── FiraMono-Medium.otf ← keras-Existiert im Font-Ordner von 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-Existiert im Ordner yolo3
│ ├── yolo.py 〇 ← keras-Existiert im Ordner yolo3
│ └── others
├── (others( .git .vs))
└── test_Cplus2_with_Python.sln
Die Dateistruktur besteht aus zwei Kreisen. Dies ist der Hauptcodeteil von C ++ bzw. Python. Ändern Sie sie wie folgt.
Ich habe einige Korrekturen am vorherigen Artikel vorgenommen. Es definiert Python-Py-Dateien, Py-Datei-Funktionen, Objekte usw. Grundsätzlich ist es ein Auto-Typ und C ++ entscheidet. Vor dem Drehen mit while wird das YOLO-Objekt im Voraus definiert. Führen Sie währenddessen nur die Objekterkennungsfunktion von Pytohn aus. Wenn Sie eine andere Originalverarbeitung hinzufügen möchten, geben Sie den Code an einer geeigneten Stelle ein.
test_Cplus2_with_Python.cpp
#define BOOST_PYTHON_STATIC_LIB
#define BOOST_NUMPY_STATIC_LIB
#include <iostream>
#include <boost/python.hpp>
//Namespace definieren
namespace py = boost::python;
/*YOLO v3 C.++Laufen Sie weiter*/
int main()
{
//Python initialisieren
Py_Initialize();
//YOLO v3 py Datei(yolo.py)Importieren
py::object YOLOv3 = py::import("yolo").attr("__dict__");
//yolo.In py"object_YOLOv3"Funktion definieren
auto object_YOLOv3 = YOLOv3["object_YOLOv3"];
//object_Definieren Sie Objektvariablen in der YOLOv3-Funktion
py::object object_YOLOv3_init;
//object_Objektvariablen in der YOLOv3-Funktion initialisieren
auto object_YOLOv3_maker = object_YOLOv3(object_YOLOv3_init);
//Definieren Sie eine Funktion zur Objekterkennung
auto insert_object_YOLOv3 = YOLOv3["insert_object_YOLOv3"];
//Beobachteter Wert
double py_y;
/*Echtzeit-Objekterkennung durch YOLO v3*/
while (true) {
//X-Achsen-Verschiebung des Zentrums, die vom Objekt durch tiefes Lernen erfasst wird
auto x_centor = insert_object_YOLOv3(object_YOLOv3_maker);
//Verschiebung C.++In einen Typ konvertieren, der in verwendet werden kann
py_y = py::extract<double>(x_centor);
/*
Wenn Sie andere Dinge verarbeiten möchten, beschreiben Sie diese entsprechend
*/
//Kommentar
std::cout << "py_y = " << py_y << std::endl;
}
}
Um das Bild von der Webkamera abzurufen, wird das Objekt, das die Webkamera geöffnet hat, in der Initialisierung (init) der YOLO-Klasse definiert. Außerdem wird der Mittelpunkt der horizontalen Achse, die das Objekt erkannt hat, berechnet und zurückgegeben. Zusätzlich werden "1_Funktion zum Initialisieren von Objekten" und "2_Funktion zum Erkennen von Objekten" neu hinzugefügt.
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
#hinzufügen
import cv2
#Hinzugefügt: Einschränkung der GPU-Speichernutzung von 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))
#Globale Variablendefinition hinzufügen
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_,#Wechselpunkt
"anchors_path": anchors_path_,#Wechselpunkt
"classes_path": classes_path_,#Wechselpunkt
"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()
#Kamera offen hinzugefügt
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
#Korrektur C.++Korrektur der Objekterkennungsposition für
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
#X Verschiebung des Objekts
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)
#Hier gibt es eine Position des Schwerpunkts
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))
#x-Achse Schwerpunkt 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_Funktion zum Initialisieren eines Objekts
def object_YOLOv3(object_YOLO):
#Erstellen Sie ein Objekt aus einer Klasse
object_YOLO = YOLO()
#C++Gibt ein Yolo-Objekt an zurück
return object_YOLO
# 2_Funktion zur Objekterkennung
def insert_object_YOLOv3(object_YOLO):
#Holen Sie sich ein Bild von der Kamera
ret, frame = object_YOLO.cap.read()
#Ändern Sie die Reihenfolge von RGGB
frame = np.asarray(frame)[..., ::-1]
#Wechseln Sie von opencv zu Kissen
frame = Image.fromarray(frame)
#Erkennt ein Objekt und gibt das Ausgabeergebnis und die Mitte der x-Achse des Objekts zurück
r_image, x_centor = object_YOLO.detect_image_for_Cplus2(frame)
#Bildschirm
cv2.imshow("out",np.asarray(r_image)[..., ::-1])
#1ms anzuzeigen
cv2.waitKey(1)
#C++Gibt den Mittelpunkt der x-Achse des Objekts zurück
return x_centor
Da es ein trainiertes Modell verwendet, wird es als Person usw. erkannt.
Da es sich um ein Beispielprogramm handelt, können Sie das Originalmodell auch dann verwenden, wenn Sie den Pfad in der py-Datei ändern.
Wann muss ich Python in C ++ aufrufen ... Ich denke, einige Leute sind besorgt. Der Grund ist -Wenn Sie wirklich Deep-Learning-Verarbeitung auf einem C ++ - kompatiblen Gerät (Motion Control Board usw.) integrieren möchten ・ Ein Lieblingsingenieur (fremde Person), der C ++ nicht verlassen kann ・ Wie auch immer, Verrückter Das ist alles für den Witz.
Wir hoffen aufrichtig, dass dies für diejenigen nützlich sein wird, die sich Sorgen über die Umweltabhängigkeit zwischen den Programmsprachen machen.
Recommended Posts