Ich konnte beim letzten Mal ein anderes Photoshop-Video erstellen (Teil ③ Verschiedene Photoshop-Videos erstellen), aber es ist noch nicht praktisch. Im Allgemeinen gibt es die folgenden Probleme. A. Wenn mehrere Personen anwesend sind, überlagern Sie das Gesicht aller Personen (Sie können nicht nur eine bestimmte Person auswählen). B. Etwas falsch erkennen, das kein Gesicht ist (Erkennungsgenauigkeit) C. Das Gesicht wird möglicherweise nicht erkannt (Erkennungsgenauigkeit) Wir wollen diese Probleme lösen.
Zunächst über A und B. Der Zweck des Erstellens verschiedener Photoshop dieses Mal ist es, "das Gesicht einer anderen Person nur auf das Gesicht einer bestimmten Person zu überschreiben". Es scheint jedoch unmöglich zu sein, automatisch eine bestimmte Person aus den erkannten Gesichtern auszuwählen, daher werden wir hier menschliche Hände verwenden. Der Weg ist ・ Videoausgabe durch Zuweisen einer ID zum erkannten Gesicht ・ Überprüfen Sie visuell die ID des Gesichts, das Sie überschreiben möchten ・ Geben Sie die ID ein Es wird durch die Methode realisiert. Wenn Sie jedoch einfach allen gefundenen Gesichtern IDs zuweisen, ist die Anzahl der einzugebenden IDs sehr groß Ich möchte dies zusammen mit der Lösung von C behandeln. Um die Anzahl der IDs zu verringern, werden die vorderen und hinteren Rahmen verwendet, um zu bestimmen, ob die Flächen von der Position und Größe durchgehend sind, und wenn sie durchgehend sind, wird dieselbe ID zugewiesen. Wenn in dem Rahmen, der von X → Y → Z ausgeht, ein Gesicht in X und Z erkannt wird, die Erkennung jedoch in Y nicht erkannt wird, wird es ergänzt, da Y auch dieses Gesicht hat.
Dieses Mal erstellen wir zum ersten Mal eine Klasse für die Implementierung. Alle Klassen werden in einer Datei namens frame_manager.py erstellt. Erstellen Sie zunächst die Klasse ** FacePosition **. Obwohl es als Klasse bezeichnet wird, ist es nur eine Struktur, die die Koordinaten und die ID des Gesichts enthält.
frame_manager.py(FacePosition)
class FacePosition:
'''
Klasse zum Halten der Gesichtsposition und der ID als Satz
Nur eine Struktur mit ID und Koordinaten als Gesichtskoordinaten und Größe
'''
def __init__(self, id, coordinate):
self.id = id
self.coordinate = coordinate
Verwenden Sie diese Option, um Gesichtsinformationen beizubehalten.
Erstellen Sie als Nächstes eine Klasse ** FaceFrame **, die die Informationen über den Frame und die darin vorhandenen Flächen enthält. Wenn Sie die Rahmen- und Gesichtskoordinaten übergeben, wird die ursprüngliche ID dem Gesicht zugewiesen und gespeichert. Zählen Sie die bisher in der Variablen für den statischen Zugriff zugewiesenen IDs, damit die ursprüngliche ID nicht abgedeckt wird.
frame_manager.py(FaceFrame)
class FaceFrame:
'''
Klasse zum Halten des erkannten Gesichts in jedem Rahmen
Da faceCount eine Variable zum Zählen der Anzahl der verwendeten IDs ist, damit die IDs nicht von der gesamten Anwendung abgedeckt werden,
Wann immer Sie FaceFrame verwenden.Zugriff mit faceCount
'''
faceCount = 0
def __init__(self, frame, coordinates):
'''
Übergeben Sie die Koordinaten und die Größe des als Rahmen erkannten Gesichts.
Erstellen Sie FacePoint-Klasseninstanzen für die Anzahl der Gesichter
coodinates:Eine Reihe von Gesichtserkennungsergebnissen. Kaskade.Übergeben Sie das Ergebnis von detectMultiScale unverändert
'''
#Sichern Sie ein Arrangement für ein paar Minuten im Gesicht
self.faces = [None]*len(coordinates)
self.frame = frame
#Erstellen Sie eine Instanz von FacePosition, indem Sie jedem übergebenen Gesicht eine ID zuweisen
for i in range(0, len(coordinates)):
self.faces[i] = FacePosition(FaceFrame.faceCount, coordinates[i])
FaceFrame.faceCount += 1
#Funktion zum späteren Hinzufügen von Gesichtern zum Rahmen
def append(self, faceId, coordinate):
self.faces.append(FacePosition(faceId, coordinate))
Jetzt können Sie die Entsprechung zwischen dem Rahmen und dem Gesicht beibehalten.
Die ** FrameManager ** -Klasse, die das Herzstück des Spiels darstellt. Von außen funktioniert diese Klasse wie folgt. ■ Wenn die Koordinateninformationen des Rahmens und der Fläche übergeben werden, werden die Rahmeninformationen (Gesichtsrahmen) zurückgegeben, die die ID zuweisen und den Erkennungsfehler ergänzen.
Zu diesem Zweck wird der empfangene Frame vorübergehend im Array gespeichert, die ID zugewiesen und der fertige Frame zurückgegeben. Die Länge des Arrays kann durch Ändern von LIST_SIZE geändert werden, hier ist es jedoch 5. Der Verarbeitungsablauf ist wie folgt. ・ Empfangen Sie Informationen zu Rahmen- und Gesichtskoordinaten.
frame_manager.py(FrameManager)
class FrameManager:
'''
Eine Klasse, die die Kontinuität des Gesichts und des fehlenden Gesichts basierend auf dem Ergebnis der übergebenen Rahmen- und Gesichtserkennung ergänzt
Weisen Sie aufeinanderfolgenden Gesichtern dieselbe ID zu.
'''
#Geben Sie an, wie viele FaceFrames die Kontinuität des Gesichts überprüfen sollen
LIST_SIZE = 5
CENTER_INDEX = int(LIST_SIZE/2)
#Wie viel Unterschied in Position und Größe sollte zulässig sein, wenn festgestellt wird, ob die Flächen zwischen den Frames gleich sind.%Spezifiziert durch
ALLOWED_GAP = 5
def __init__(self, height, width):
'''
Geben Sie die Höhe und Breite des zu verarbeitenden Videos an
'''
FrameManager.FRAME_HEIGHT = height
FrameManager.FRAME_WIDTH = width
self.__frames = [None]*self.LIST_SIZE
def put(self, frame, coordinates):
'''
Fügen Sie einen Frame basierend auf dem übergebenen Frame und dem Gesichtserkennungsergebnis hinzu
Beim Hinzufügen ID zuweisen, Kontinuität prüfen, fehlende Flächen ergänzen, LISTE_Gibt die SIZEth FaceFrame-Instanz zurück
Als Verarbeitung am Ende, nach der Verarbeitung aller Frames, LIST_Da SIZE-Frames in FrameManager verbleiben, fügen Sie None hinzu, bis Sie die verbleibenden Frames gelöscht haben.
return:Eine Instanz von FaceFrame. Allerdings LISTE_Gibt None zurück, wenn bei SIZE th keine FaceFrame-Instanz vorhanden ist.
'''
#Da bei der Ausgabe des letzten verbleibenden Frames None übergeben wird, wird in diesem Fall auch faceFrame auf None festgelegt.
if frame is None:
faceFrame = None
else:
faceFrame = FaceFrame(frame, coordinates)
#Verschieben Sie die Liste nacheinander vorwärts und fügen Sie am Ende einen Argumentrahmen hinzu. Da es viele zufällige Zugriffe auf die interne Verarbeitung gibt, halte ich es für wünschenswert, sie in einem Array zu verwalten.
returnFrame = self.__frames[0]
for i in range(0,len(self.__frames)-1):
self.__frames[i] = self.__frames[i+1]
self.__frames[FrameManager.LIST_SIZE-1] = faceFrame
#Überprüfen Sie den Durchgang von den vorderen und hinteren Rahmen
# CENTER_Vorher mit INDEX als Grenze(i)Rückseite(j)Überprüfen Sie bei jeder Kombination die Kontinuität des Gesichts
for i in range(0, FrameManager.CENTER_INDEX):
for j in range(FrameManager.CENTER_INDEX+1, FrameManager.LIST_SIZE):
#Überspringen Sie den Teil Keine
if self.__frames[i] is not None and self.__frames[FrameManager.CENTER_INDEX] is not None and self.__frames[j] is not None:
#Überprüfen Sie die Kontinuität und ergänzen Sie alle dazwischen liegenden Frames
for k in range(i+1, j):
self.connectFrame(self.__frames[i], self.__frames[k], self.__frames[j])
return returnFrame
def connectFrame(self, frameF, frameC, frameB):
# frameF.Gesichter und RahmenC.Wenn sich Gesichter in aufeinanderfolgenden Gesichtern befinden, geben Sie dieselbe ID an.
#TODO Es ist möglich, dass dieselbe ID mehreren Gesichtern zugewiesen werden kann. Erstens funktioniert in diesem Fall das aktuelle Design nicht, also habe ich es auf Eis gelegt.
frontFaceNum = len(frameF.faces)
centerFaceNum = len(frameC.faces)
backFaceNum = len(frameB.faces)
for i in range(0, frontFaceNum):
#Behält, wenn die i-te Fläche im vorherigen Bild mit einer der Flächen in Bild C übereinstimmt
matched = False
for j in range(0, centerFaceNum):
#Wenn es sich um dasselbe Gesicht handelt, verwenden Sie dieselbe ID
if self.compare(frameF.faces[i], frameC.faces[j]) == True:
frameC.faces[j].id = frameF.faces[i].id
matched = True
break
#Selbst wenn es nicht in FrameC ist, wenn es sowohl in FrameF als auch in FrameB ist, wird angenommen, dass der FramC dazwischen auch dieses Gesicht hat und ergänzt wird.
if matched == False:
for k in range(0, backFaceNum):
if self.compare(frameF.faces[i], frameB.faces[k]):
#Fügen Sie der Position / Größe zwischen FrameF und FrameB eine Fläche hinzu
frameC.append(frameF.faces[i].id, ((frameF.faces[i].coordinate + frameB.faces[k].coordinate)/2).astype(np.int))
#Erhöhen Sie die Anzahl der Gesichter um 1.(Falls im späteren Prozess ein anderes Gesicht gefunden wird)
centerFaceNum += 1
#Verhinderung von Endlosschleifen
if(centerFaceNum>10):
break
def compare(self, face1, face2):
'''
Vergleichen Sie, ob face1 und face2 fortlaufend sind.
return:Richtig, wenn gleich, Falsch, wenn anders
'''
result = True
#Überprüfen Sie, ob der Unterschied zwischen Koordinaten und Gesichtsgröße innerhalb des Fehlerbereichs liegt, und alle Fehler(ALLOWED_GAP)Wenn es drinnen ist, wird beurteilt, dass sie das gleiche Gesicht haben
#Wenn die TODO-Frames weit voneinander entfernt sind, ist es besser, die Toleranz entsprechend zu erhöhen.
for i in range(0,4):
if i%2 == 0:
gap = ((float(face1.coordinate[i])-float(face2.coordinate[i]))/FrameManager.FRAME_HEIGHT)*100
else:
gap = ((float(face1.coordinate[i])-float(face2.coordinate[i]))/FrameManager.FRAME_WIDTH)*100
if (-1*FrameManager.ALLOWED_GAP < gap < FrameManager.ALLOWED_GAP) == False:
result = False
break
return result
Um dies zu verwenden, erstellen Sie eine Instanz von FrameManager und geben Sie die Rahmen- und Gesichtsinformationen ein. Es wird ein FaceFrame mit einer ID zurückgegeben.
Wenn ich es überprüfe, überprüfe ich außerdem mehrmals die Kontinuität von IDs zwischen denselben Frames, wodurch es redundant wird. Ich schließe jedoch meine Augen aus dem später beschriebenen Grund.
Fügen Sie die erstellte FrameManager-Klasse in die zuvor erstellte Datei overlay_movie.py ein. Fügen Sie nach der Gesichtserkennung zuerst das erkannte Gesicht in FrameManager ein und schreiben Sie die ID basierend auf der ausgegebenen FaceFrame-Instanz in das gefundene Gesicht.
overlay_movie2.py
# -*- coding:utf-8 -*-
import cv2
import datetime
import numpy as np
from PIL import Image
import frame_manager
def overlay_movie2():
#Geben Sie das einzugebende Video und den Ausgabepfad an.
target = "target/test_input.mp4"
result = "result/test_output2.m4v" #.Ich erhalte eine Fehlermeldung, wenn ich m4v nicht verwende
#Laden von Videos und Abrufen von Videoinformationen
movie = cv2.VideoCapture(target)
fps = movie.get(cv2.CAP_PROP_FPS)
height = movie.get(cv2.CAP_PROP_FRAME_HEIGHT)
width = movie.get(cv2.CAP_PROP_FRAME_WIDTH)
#Geben Sie MP4V als Format an
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
#Öffnen Sie die Ausgabedatei
out = cv2.VideoWriter(result, int(fourcc), fps, (int(width), int(height)))
#Ermitteln Sie die Merkmalsmenge des Kaskadenklassifikators
cascade_path = "haarcascades/haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_path)
#FrameManager erstellen
frameManager = frame_manager.FrameManager(height, width)
#Geben Sie die Farbe des Rechtecks an, das das erkannte Gesicht umgibt. Weiß hier.
color = (255, 255, 255)
#Lesen Sie den ersten Frame
if movie.isOpened() == True:
ret,frame = movie.read()
else:
ret = False
count = 0
#Exportieren Sie weiterhin Frames, während Sie Frames erfolgreich lesen
while ret:
#In Graustufen konvertieren
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#Gesichtserkennung durchführen
facerecog = cascade.detectMultiScale(frame_gray, scaleFactor=1.1, minNeighbors=1, minSize=(1, 1))
#Fügen Sie das erkannte Gesicht in FrameManager ein
managedFrame = frameManager.put(frame, facerecog)
#Ab dem 5. Mal werden Frames vom Frame Manager zurückgegeben, also Dateiausgabe
if managedFrame is not None:
#Fügen Sie dem erkannten Gesicht eine Nummer hinzu
for i in range(0,len(managedFrame.faces)):
#Bereiten Sie Variablen für eine einfache Handhabung vor
tmpCoord = managedFrame.faces[i].coordinate
tmpId = managedFrame.faces[i].id
print("Anzahl der erkannten Gesichter(ID) = "+str(tmpId))
#In ein Rechteck einschließen
cv2.rectangle(managedFrame.frame, tuple(tmpCoord[0:2]),tuple(tmpCoord[0:2]+tmpCoord[2:4]), color, thickness=2)
#Schreiben Sie die Gesichts-ID
cv2.putText(managedFrame.frame,str(tmpId),(tmpCoord[0],tmpCoord[1]),cv2.FONT_HERSHEY_TRIPLEX, 2, (100,200,255), thickness=2)
out.write(managedFrame.frame)
if count%10 == 0:
date = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S")
print(date + 'Aktuelle Anzahl der Frames:'+str(count))
count += 1
ret,frame = movie.read()
#Auf halbem Weg enden
if count > 200 :
break
print("Anzahl der Ausgaberahmen:"+str(count))
if __name__ == '__main__':
overlay_movie2()
Sie können Ihrem Gesicht sicher eine ID zuweisen.
Es ist jetzt möglich, eine bestimmte Person aus mehreren Personen anhand der ID zu identifizieren, und es ist jetzt möglich, aufeinanderfolgende Gesichter anhand einer ID zu identifizieren.
Sie müssen lediglich die ID des Gesichts eingeben, das Sie überschreiben möchten, und das entsprechende Gesicht überschreiben. Ich würde gerne sagen, aber das war nicht der Fall. Ich habe es bisher geschafft, aber dieses Programm kann seinen Zweck nicht erfüllen. Die Erkennungsgenauigkeit des Gesichts in dem zu erkennenden Video ist schlecht, und selbst wenn die Lücke ergänzt wird, kann sie nicht behandelt werden. (Ich schaute weg, während ich mich dünn fühlte) Aus diesem Grund möchte ich eine andere Richtlinie für dieses Programm als Lagerhaus untersuchen. Es wird bis zum nächsten fortgesetzt.
Recommended Posts