Erstellen Sie verschiedene Photoshop-Videos mit Python + OpenCV. ④ Beheben Sie Probleme

0. Einleitung

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.

1. Politik

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.

2. Klassenimplementierung (FacePostion, FaceFrame)

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.

3. Klassenimplementierung (FrameManager)

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.

4. Eingebauter FrameManager

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()

5. Ergebnis

Sie können Ihrem Gesicht sicher eine ID zuweisen. ID割り振り1人.JPG

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. ID割り振り3人.JPG

6. Schließlich

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

Erstellen Sie verschiedene Photoshop-Videos mit Python + OpenCV. ④ Beheben Sie Probleme
Erstellen verschiedener Photoshop-Videos mit Python + OpenCV ③ Erstellen Sie verschiedene Photoshop-Videos
Erstellen verschiedener Photoshop-Videos mit Python + OpenCV ② Erstellen Sie Photoshop-Standbilder
Erstellen Sie mit Python eine Datei im Photoshop-Format (.psd)
Binarisierung mit OpenCV / Python
"Apple-Verarbeitung" mit OpenCV3 + Python3
Bildbearbeitung mit Python OpenCV
Kameraerfassung mit Python + OpenCV
Erstellen Sie ein 3D-GIF mit Python3
[Python] Verwenden von OpenCV mit Python (Basic)
Gesichtserkennung mit Python + OpenCV
Erstellen Sie ein Verzeichnis mit Python
Verwenden von OpenCV mit Python @Mac
Erstellen Sie mit python wxpython + openCV ein einfaches Videoanalysetool
Leuchtendes Leben mit Python und OpenCV
Erstellen Sie eine Plotanimation mit Python + Matplotlib
[Python] Verwenden von OpenCV mit Python (Bildfilterung)
Erstellen Sie Awaitable mit der Python / C-API
Neuronales Netzwerk mit OpenCV 3 und Python 3
[Python] Verwenden von OpenCV mit Python (Bildtransformation)
[Python] Verwenden von OpenCV mit Python (Kantenerkennung)
Erstellen Sie eine gestreifte Illusion mit Gammakorrektur für Python3 und openCV3
Erstellen Sie eine virtuelle Umgebung mit Python!
Einfache Python + OpenCV-Programmierung mit Canopy
Versuchen Sie die Gesichtserkennung mit Python + OpenCV
Schneiden Sie das Gesicht mit Python + OpenCV aus
Gesichtserkennung mit Kamera mit opencv3 + python2.7
Laden Sie das GIF-Bild mit Python + OpenCV
Finden Sie Bildähnlichkeit mit Python + OpenCV
Verwenden Sie OpenCV mit Python 3 in Window
Zeichnen Sie eine Illustration mit Python + OpenCV
Mit Python und OpenCV lassen Sie Unschärfevideos wie Festkommakameras aussehen
Verfolgen Sie Baseballbälle mit Python + OpenCV
Graphbasierte Segmentierung mit Python + OpenCV
Zeichnen Sie einen Pfeil (Vektor) mit opencv / python
Grundlegendes Studium von OpenCV mit Python
Erstellen Sie mit Python + OpenCV Ihre eigene virtuelle Kamera und wenden Sie Originaleffekte an
Erstellen Sie mit Class einen Python-Funktionsdekorator
Erstellen Sie automatisch eine Python-API-Dokumentation mit Sphinx
Erstellen Sie mit python3 eine Wortwolke aus Ihrem Tweet
Erstellen Sie mit Python + PIL ein Dummy-Image.
Speichern Sie Videos Frame für Frame mit Python OpenCV
[Python] Erstellen Sie mit Anaconda eine virtuelle Umgebung
Erstellen wir mit Python eine kostenlose Gruppe
Erstellen Sie schnell eine Excel-Datei mit Python #python
Bilder mit Pupil, Python und OpenCV aufnehmen
Ich habe versucht, mit Python + opencv nicht realistisch zu rendern
Bildverarbeitung mit Python & OpenCV [Tonkurve]
Erstellen Sie mit Docker eine Python + uWSGI + Nginx-Umgebung
Erstellen und entschlüsseln Sie Caesar-Code mit Python
Bildaufnahme von der Kamera mit Python + OpenCV
[python, openCV] base64 Gesichtserkennung in Bildern
Erstellen Sie eine Excel-Datei mit Python + Ähnlichkeitsmatrix
Erstellen Sie mit Python 3.4 einen Worthäufigkeitszähler
Erstellen Sie eine OpenCV3 + python3-Umgebung unter OSX
[Python] Bilder mit OpenCV lesen (für Anfänger)
[Python] Erstellen Sie schnell eine API mit Flask
Erstellen Sie eine englische Wort-App mit Python