Dies ist eine Fortsetzung von Versuchen wir die Gesichtserkennung mit Chainer (Lernphase), und diesmal ist es die Vorhersagephase.
Versuchen wir die Gesichtserkennung mit einer über USB angeschlossenen Webcam.
-Software- Windows 10 Home Anaconda3 64-bit(Python3.7) Spyder -Library- Chainer 7.0.0 opencv-python 4.1.2.30 -Hardware- CPU: Intel core i9 9900K GPU: NVIDIA GeForce RTX2080ti RAM: 16GB 3200MHz (Es kann sogar auf einem PC ausgeführt werden, wenn Sie eine Webcam haben)
** Bücher ** OpenCV4-Programmierung beginnend mit Python Naohiro Kitayama (Autor) ([Amazon-Seite](https://www.amazon.co.jp/Python%E3%81%A7%E5%A7%8B%E3%82%81%E3%82%8BOpenCV-4%E3%83% 97% E3% 83% AD% E3% 82% B0% E3% 83% A9% E3% 83% 9F% E3% 83% B3% E3% 82% B0-% E5% 8C% 97% E5% B1% B1 -% E7% 9B% B4% E6% B4% 8B / dp / 4877834613)) Seite? ˅ Chainer-API-Referenz
Vorerst werde ich es auf Github veröffentlichen. https://github.com/himazin331/Face-Recognition-Chainer- Das Repository enthält eine Lernphase, eine Vorhersagephase, ein Datenverarbeitungsprogramm und Haar-Cascade.
Für den Betrieb dieses Programms ist eine Cascade-Datei mit Haar-ähnlichen Funktionen erforderlich. Dieses Mal werden wir Haar-Cascade von OpenCV verwenden. Cascade ist im Repository enthalten, sodass Sie es nicht separat vorbereiten müssen.
** Bitte beachten Sie, dass der Code verschmutzt ist ... **
face_recog_CH.py
from PIL import Image
import numpy as np
import cv2
import sys
import os
import argparse as arg
import chainer
import chainer.links as L
import chainer.functions as F
import chainer.serializers as S
# ==================================== face_recog_train_CH.Gleiche Netzwerkkonfiguration wie py====================================
class CNN(chainer.Chain):
def __init__(self, n_out):
super(CNN, self).__init__(
conv1=L.Convolution2D(1, 16, 5, 1, 0),
conv2=L.Convolution2D(16, 32, 5, 1, 0),
conv3=L.Convolution2D(32, 64, 5, 1, 0),
link=L.Linear(None, 1024),
link_class=L.Linear(None, n_out),
)
def __call__(self, x):
h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)
h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)
h3 = F.relu(self.conv3(h2))
h4 = F.relu(self.link(h3))
return self.link_class(h4)
# ================================================================================================================
def main():
#Optionale Argumente für die Befehlszeile
parser = arg.ArgumentParser(description='Face Recognition Program(Chainer)')
parser.add_argument('--param', '-p', type=str, default=None,
help='Gelernte Parameter angeben(Fehler, wenn nicht angegeben)')
parser.add_argument('--cascade', '-c', type=str, default=os.path.dirname(os.path.abspath(__file__))+'/haar_cascade.xml'.replace('/', os.sep),
help='Haar-Spezifikation der Kaskade(Standardwert=./haar_cascade.xml)')
parser.add_argument('--device', '-d', type=int, default=0,
help='Angeben der Kamera-Geräte-ID(Standardwert=0)')
args = parser.parse_args()
#Wenn keine Parameterdatei angegeben ist->Ausnahme
if args.param == None:
print("\nException: Trained Parameter-File not specified.\n")
sys.exit()
#Wenn eine nicht vorhandene Parameterdatei angegeben wird->Ausnahme
if os.path.exists(args.param) != True:
print("\nException: Trained Parameter-File {} is not found.\n".format(args.param))
sys.exit()
#Haar, das es nicht gibt-Wenn Kaskade angegeben ist->Ausnahme
if os.path.exists(args.cascade) != True:
print("\nException: Haar-cascade {} is not found.\n".format(args.cascade))
sys.exit()
#Informationsausgabe einstellen
print("=== Setting information ===")
print("# Trained Prameter-File: {}".format(os.path.abspath(args.param)))
print("# Haar-cascade: {}".format(args.cascade))
print("# Camera device: {}".format(args.device))
print("===========================")
#Generierung von Kamerainstanzen
cap = cv2.VideoCapture(args.device)
#FPS-Werteinstellung
cap.set(cv2.CAP_PROP_FPS, 60)
#Satz Gesichtsdetektoren
detector = cv2.CascadeClassifier(args.cascade)
#Gelernte Parameter laden
model = L.Classifier(CNN(2))
S.load_npz(args.param, model)
red = (0, 0, 255)
green = (0, 255, 0)
p = (10, 30)
while True:
#Holen Sie sich Rahmen
_, frame = cap.read()
#Kameraerkennung nicht möglich->Ausnahme
if _ == False:
print("\nException: Camera read failure.\n".format(args.param))
sys.exit()
#Gesichtserkennung
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray)
#Gesicht unentdeckt->continue
if len(faces) == 0:
cv2.putText(frame, "face is not found",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
continue
#Wenn das Gesicht erkannt wird
for (x, y, h, w) in faces:
#Gesichtsbereichsanzeige
cv2.rectangle(frame, (x, y), (x+w, y+h), red, thickness=2)
#Durch, wenn das Gesicht zu klein ist
if h < 50 and w < 50:
cv2.putText(frame, "detected face is too small",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
cv2.imshow("frame", frame)
break
#Zeigen Sie das erkannte Gesicht an
cv2.imshow("gray", cv2.resize(gray[y:y + h, x:x + w], (250, 250)))
#Bildverarbeitung
face = gray[y:y + h, x:x + w]
face = Image.fromarray(face)
face = np.asarray(face.resize((32, 32)), dtype=np.float32)
recog_img = face[np.newaxis, :, :]
#Gesichtserkennung
y = model.predictor(chainer.Variable(np.array([recog_img])))
c = F.softmax(y).data.argmax()
if c == 0:
cv2.putText(frame, "Unknown",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)
elif c == 1:
cv2.putText(frame, "Kohayakawa",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
#Ressourcenfreigabe
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
main()
Dieses Mal habe ich versucht, Shinzo Abe und Taro Aso zu identifizieren. Die Anzahl der Trainingsdaten beträgt für beide 100.
Befehl
python face_recog_CH.py -p <Parameterdatei> -c <Kaskade> (-d <Kamera-Geräte-ID>)
Da es sich um die Vorhersagephase handelt, handelt es sich um ein Programm, das das Gesicht mit einer Kamera identifiziert.
CNN-Klasse, aber genau das gleiche wie das Netzwerkmodell der Lernphase (face_recog_train_CH.py) Bitte beschreiben Sie, wie es ist. Es wird nicht funktionieren, wenn die Struktur etwas anders ist. Unterschiedliche Hyperparameter und Ebenen haben unterschiedliche Anzahlen von Parametern wie Gewichten, also lernoptimierte Parameter. Kann nicht angewendet werden.
CNN-Klasse
# ==================================== face_recog_train_CH.Gleiche Netzwerkkonfiguration wie py====================================
class CNN(chainer.Chain):
def __init__(self, n_out):
super(CNN, self).__init__(
conv1=L.Convolution2D(1, 16, 5, 1, 0),
conv2=L.Convolution2D(16, 32, 5, 1, 0),
conv3=L.Convolution2D(32, 64, 5, 1, 0),
link=L.Linear(None, 1024),
link_class=L.Linear(None, n_out),
)
def __call__(self, x):
h1 = F.max_pooling_2d(F.relu(self.conv1(x)), ksize=2)
h2 = F.max_pooling_2d(F.relu(self.conv2(h1)), ksize=2)
h3 = F.relu(self.conv3(h2))
h4 = F.relu(self.link(h3))
return self.link_class(h4)
# ================================================================================================================
Es erstellt eine Kamerainstanz, lädt eine Kaskade und importiert Parameter.
#Generierung von Kamerainstanzen
cap = cv2.VideoCapture(args.device)
#FPS-Werteinstellung
cap.set(cv2.CAP_PROP_FPS, 60)
#Satz Gesichtsdetektoren
detector = cv2.CascadeClassifier(args.cascade)
Wenden Sie mit "chainer.serializers.load_npz ()" Parameter auf das Netzwerkmodell an. Beachten Sie, dass ich in der Lernphase das Modell mit "L.Classifier ()" umbrochen und eine Instanz erstellt habe. Sie müssen das Modell auch in der Vorhersagephase in "L.Classifier ()" einschließen.
#Gelernte Parameter laden
model = L.Classifier(CNN(2))
S.load_npz(args.param, model)
Machen Sie zuerst ein Bild mit der Kamera. Sie können mit "cap.read ()" schießen. Wenn Sie "cap.read ()" einmal ausführen, erhalten Sie ein Standbild. Verwenden Sie die while-Anweisung und die for-Anweisung, um "cap.read ()" nacheinander auszuführen, und geben Sie die erhaltenen Standbilder kontinuierlich aus, damit sie so aussehen, als würden sie sich bewegen.
cap.read ()
gibt zwei Werte zurück.
Das erste ist eine Flagge (_
im Code), ob ein Schießen möglich ist oder nicht.
Das zweite tatsächlich aufgenommene Standbild (Frame
im Code).
Im Folgenden wird das Standbild als Rahmen bezeichnet.
while True:
#Holen Sie sich Rahmen
_, frame = cap.read()
#Kameraerkennung nicht möglich->Ausnahme
if _ == False:
print("\nException: Camera read failure.\n".format(args.param))
sys.exit()
#Gesichtserkennung
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
faces = detector.detectMultiScale(gray)
#Gesicht unentdeckt->continue
if len(faces) == 0:
cv2.putText(frame, "face is not found",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
continue
Nach dem Erfassen des Rahmens wird der Rahmen grau skaliert und die Gesichtserkennung wird unter Verwendung von Cascade durchgeführt, einer haarähnlichen Funktion.
detector.detectMultiScale ()
gibt Informationen zur Erkennungsposition (Koordinaten und Breite Höhe) zurück, wenn ein Gesicht erkannt wird und wenn es nicht erkannt werden kann.
Ich werde nichts zurückgeben.
Wenn ein Gesicht nicht erkannt werden kann, wird im Fenster "Gesicht wird nicht gefunden" ausgegeben und fortgefahren.
Ich werde die Verarbeitung erklären, wenn ein Gesicht erkannt wird.
Die Bildverarbeitung wird unter Verwendung der x- und y-Koordinaten, der Breite und der Höhe des zurückgegebenen Erkennungsorts durchgeführt.
#Wenn das Gesicht erkannt wird
for (x, y, h, w) in faces:
#Gesichtsbereichsanzeige
cv2.rectangle(frame, (x, y), (x+w, y+h), red, thickness=2)
#Durch, wenn das Gesicht zu klein ist
if h < 50 and w < 50:
cv2.putText(frame, "detected face is too small",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, red, thickness=2)
cv2.imshow("frame", frame)
break
#Zeigen Sie das erkannte Gesicht an
cv2.imshow("gray", cv2.resize(gray[y:y + h, x:x + w], (250, 250)))
#Bildverarbeitung
face = gray[y:y + h, x:x + w]
face = Image.fromarray(face)
face = np.asarray(face.resize((32, 32)), dtype=np.float32)
recog_img = face[np.newaxis, :, :]
#Gesichtserkennung
y = model.predictor(chainer.Variable(np.array([recog_img])))
c = F.softmax(y).data.argmax()
if c == 0:
cv2.putText(frame, "Abe Sinzo",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)
elif c == 1:
cv2.putText(frame, "Aso Taro",
p, cv2.FONT_HERSHEY_SIMPLEX, 1.0, green, thickness=2)
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
Die Bildverarbeitung ist konkret ① Schneiden Sie den Gesichtsbereich aus dem Rahmen aus ② Konvertieren Sie einmal von Array zu Bild, um die Größe des Gesichtsbereichs zu ändern ③ Ändern Sie die Größe auf 32 x 32 Pixel ④ Fügen Sie die Dimension des Arrays hinzu (Addition der Anzahl der Kanäle, [Anzahl der Kanäle, Höhe, Breite]) Ich mache.
Wenn wir nun die Daten in eine identifizierbare Form bringen können, ist es endlich Zeit, das Gesicht zu erkennen.
y = model.predictor(chainer.Variable(np.array([recog_img])))
Beginnen Sie die Vorhersage mit. chainer.Variable ()
ist eine Funktion, die Daten einer Kettenregel zuordnet.
Verwenden Sie als Nächstes c = F.softmax (y) .data.argmax ()
, um das Vorhersageergebnis durch die Softmax-Funktion zu leiten, und verwenden Sie dann argmax.
Das größte Element (Index) wird zurückgegeben.
Und schließlich wird mit der if-Anweisung der Klassenname ausgegeben, der dem Element (Index) entspricht.
Dieses Mal gibt es zwei Klassen, Shinzo Abe und Taro Aso, aber lernen wir ein Gesicht, das keines von beiden ist. Wenn Sie ein Gesicht eingeben, das weder Shinzo Abe noch Taro Aso ist, können Sie so etwas wie "weder" ausgeben.
Ursprünglich wurden diese Programme in der High-School-Aufgabenforschung (Abschlussforschung) entwickelt, daher ist der Code angemessen. Sie können die Anzahl der zu klassifizierenden Klassen leicht ändern, solange Sie über Lerndaten verfügen. Machen Sie also bitte, was Sie möchten.
Recommended Posts