Dieses Mal werde ich das Verfolgungsziel für das Video mit einem Mausklick angeben und versuchen, das Objekt im 3D-Raum in Echtzeit zu verfolgen. Im Vergleich zum Vorlagenabgleich wird ein funktionsbasierter Algorithmus verwendet, der weniger Rechenaufwand erfordert und auch bei Drehung verfolgt werden kann.
OpenCV OpenCV (Open Source Computer Vision Library) ist eine Sammlung von BSD-lizenzierten Video- / Bildverarbeitungsbibliotheken. Es gibt viele Algorithmen wie Bildfilterung, Vorlagenabgleich, Objekterkennung, Videoanalyse und maschinelles Lernen.
■ Beispiel für Bewegungsverfolgung mit OpenCV (OpenCV Google Summer of Code 2015) https://www.youtube.com/watch?v=OUbUFn71S4s
■ Klicken Sie hier für die Installation und einfache Verwendung Installieren Sie OpenCV 3 (Core + Contrib) in der Python 3-Umgebung und unterscheiden Sie zwischen OpenCV 2 und OpenCV 3 und überprüfen Sie die einfache Bedienung
■ Klicken Sie hier, um Standbilder zu filtern Versuchen Sie die Kantenerkennung mit OpenCV Führen Sie verschiedene Filter mit OpenCV durch (Gradient, Highpass, Laplacian, Gaussian) Extrahieren Sie Feature-Punkte mit OpenCV (AgastFeature, FAST, GFTT, MSER, AKAZE, BRISK, KAZE, ORB, SimpleBlob)
■ Klicken Sie hier, um Videodateien zu verarbeiten Versuchen Sie, Videos in Echtzeit mit OpenCV zu konvertieren Versuchen Sie, Webkamera- / Videokamera-Videos in Echtzeit mit OpenCV zu konvertieren Zeichnen Sie den optischen Fluss in Echtzeit mit OpenCV (Shi-Tomasi-Methode, Lucas-Kanade-Methode)
Erstellen Sie dieses Mal ein Programm mit den folgenden Funktionen.
Die Pausenfunktion ist sehr wichtig, wenn Sie mit einem Mausklick Funktionspunkte für ein Video festlegen. Halten Sie das Video mit der Taste "s" an und geben Sie die Funktionspunkte langsam an.
Betriebsumgebung
Videodaten Ich habe das mit OpenCV gelieferte Beispielvideo verwendet. OpenCV\opencv\sources\samples\data\768x576.avi
motion.py
import cv2
import numpy as np
#Esc-Taste
ESC_KEY = 0x1b
#s Schlüssel
S_KEY = 0x73
#r Taste
R_KEY = 0x72
#Maximale Anzahl von Feature-Punkten
MAX_FEATURE_NUM = 500
#Beendigungsbedingung des iterativen Algorithmus
CRITERIA = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03)
#Intervall (1000/Bildrate)
INTERVAL = 30
#Videodaten
VIDEO_DATA = '768x576.avi'
class Motion:
#Konstrukteur
def __init__(self):
#Anzeigefenster
cv2.namedWindow("motion")
#Rückrufregistrierung für Mausereignisse
cv2.setMouseCallback("motion", self.onMouse)
#Video
self.video = cv2.VideoCapture(VIDEO_DATA)
#Intervall
self.interval = INTERVAL
#Aktueller Rahmen (Farbe)
self.frame = None
#Aktueller Frame (grau)
self.gray_next = None
#Letzter Frame (grau)
self.gray_prev = None
#Funktionspunkt
self.features = None
#Funktionspunktstatus
self.status = None
#Hauptschleife
def run(self):
#Verarbeitung des ersten Frames
end_flag, self.frame = self.video.read()
self.gray_prev = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
while end_flag:
#In Graustufen konvertieren
self.gray_next = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
#Berechnen Sie den optischen Fluss, wenn Feature-Punkte registriert werden
if self.features is not None:
#Berechnung des optischen Flusses
features_prev = self.features
self.features, self.status, err = cv2.calcOpticalFlowPyrLK( \
self.gray_prev, \
self.gray_next, \
features_prev, \
None, \
winSize = (10, 10), \
maxLevel = 3, \
criteria = CRITERIA, \
flags = 0)
#Lassen Sie nur gültige Feature-Punkte
self.refreshFeatures()
#Zeichnen Sie gültige Feature-Punkte auf den Rahmen
if self.features is not None:
for feature in self.features:
cv2.circle(self.frame, (feature[0][0], feature[0][1]), 4, (15, 241, 255), -1, 8, 0)
#Anzeige
cv2.imshow("motion", self.frame)
#Vorbereitung für die nächste Schleife
self.gray_prev = self.gray_next
end_flag, self.frame = self.video.read()
if end_flag:
self.gray_next = cv2.cvtColor(self.frame, cv2.COLOR_BGR2GRAY)
#Intervall
key = cv2.waitKey(self.interval)
# "Esc"Drücken Sie die Taste, um den Vorgang abzuschließen
if key == ESC_KEY:
break
# "s"Pause durch Drücken einer Taste
elif key == S_KEY:
self.interval = 0
elif key == R_KEY:
self.interval = INTERVAL
#Verarbeitung beenden
cv2.destroyAllWindows()
self.video.release()
#Geben Sie Feature-Punkte mit einem Mausklick an
#Wenn in der angeklickten Nachbarschaft ein Feature-Point vorhanden ist, löschen Sie den vorhandenen Feature-Point
#Wenn in der angeklickten Umgebung kein Feature-Punkt vorhanden ist, fügen Sie einen neuen Feature-Punkt hinzu
def onMouse(self, event, x, y, flags, param):
#Anders als Linksklick
if event != cv2.EVENT_LBUTTONDOWN:
return
#Erster Feature-Punkt hinzugefügt
if self.features is None:
self.addFeature(x, y)
return
#Suchradius (Pixel)
radius = 5
#Suchen Sie nach vorhandenen Feature-Punkten in der Nähe
index = self.getFeatureIndex(x, y, radius)
#Da sich in der Nähe des Klicks ein vorhandener Feature-Punkt befindet, löschen Sie den vorhandenen Feature-Punkt
if index >= 0:
self.features = np.delete(self.features, index, 0)
self.status = np.delete(self.status, index, 0)
#Da in der Nähe des angeklickten Bereichs kein Feature-Punkt vorhanden ist, wird ein neuer Feature-Punkt hinzugefügt.
else:
self.addFeature(x, y)
return
#Ruft einen Index der vorhandenen Feature-Punkte innerhalb des angegebenen Radius ab
#Wenn innerhalb des angegebenen Radiusindex keine Feature-Punkte vorhanden sind= -Antwort 1
def getFeatureIndex(self, x, y, radius):
index = -1
#Es sind keine Feature-Punkte registriert
if self.features is None:
return index
max_r2 = radius ** 2
index = 0
for point in self.features:
dx = x - point[0][0]
dy = y - point[0][1]
r2 = dx ** 2 + dy ** 2
if r2 <= max_r2:
#Dieser Feature-Punkt liegt innerhalb des angegebenen Radius
return index
else:
#Dieser Feature-Punkt liegt außerhalb des angegebenen Radius
index += 1
#Alle Feature-Punkte liegen außerhalb des angegebenen Radius
return -1
#Fügen Sie neue Feature-Punkte hinzu
def addFeature(self, x, y):
#Feature Points werden nicht registriert
if self.features is None:
#Erstellen Sie ndarray und registrieren Sie die Koordinaten der Feature-Punkte
self.features = np.array([[[x, y]]], np.float32)
self.status = np.array([1])
#Hochgenaue Merkmalspunkte
cv2.cornerSubPix(self.gray_next, self.features, (10, 10), (-1, -1), CRITERIA)
#Überschreitet die maximale Anzahl registrierter Feature-Punkte
elif len(self.features) >= MAX_FEATURE_NUM:
print("max feature num over: " + str(MAX_FEATURE_NUM))
#Zusätzliche Feature-Punkte registriert
else:
#Fügen Sie am Ende eines vorhandenen ndarray Feature-Punkt-Koordinaten hinzu
self.features = np.append(self.features, [[[x, y]]], axis = 0).astype(np.float32)
self.status = np.append(self.status, 1)
#Hochgenaue Merkmalspunkte
cv2.cornerSubPix(self.gray_next, self.features, (10, 10), (-1, -1), CRITERIA)
#Lassen Sie nur gültige Feature-Punkte
def refreshFeatures(self):
#Feature Points werden nicht registriert
if self.features is None:
return
#Überprüfen Sie alle Status
i = 0
while i < len(self.features):
#Kann nicht als Feature-Punkt erkannt werden
if self.status[i] == 0:
#Aus vorhandenem ndarray entfernen
self.features = np.delete(self.features, i, 0)
self.status = np.delete(self.status, i, 0)
i -= 1
i += 1
if __name__ == '__main__':
Motion().run()
Das Programm verwendete das OpenCV-Beispielvideo (768x576.avi), es sieht jedoch nicht immer auf demselben Bildschirm gleich aus. Jedes Video ist in Ordnung. Ändern Sie den Teil "VIDEO_DATA" des Programms in Ihr Lieblingsvideo. Als Beispiel für das Ausführungsergebnis verwenden wir beispielsweise Uchimura, der die Eisenstange im individuellen Gesamtfinale der Olympischen Gymnastik 2016 in Rio de Janeiro spielt. In diesem Video bewegt sich auch Uchimura, der die Eisenstange spielt, aber laut Uchimura bewegt sich auch der Hintergrundrahmen auf und ab. Verwenden Sie die Taste "s", um das Video anzuhalten und den Punkt festzulegen, an dem Sie Uchimuras Socken folgen möchten. Die gelben Punkte repräsentieren die Merkmalspunkte. Wenn Sie das Video abspielen, können Sie sehen, dass die gelben Punkte Uchimuras Socken verfolgen. (Da Uchimuras Zehen ordentlich ausgerichtet sind, kann man sagen, dass er sie weiterhin als denselben Merkmalspunkt erkennen kann.)
Wenn Sie das Programm tatsächlich ausführen, können Sie feststellen, dass dieses Programm (einfach mit cv2.calcOpticalFlowPyrLK ()) drei Probleme hat.
In beiden Fällen erhöht sich der Rechenaufwand, es gibt jedoch Möglichkeiten, damit umzugehen. Ich werde versuchen, bald eine kompatible Version zu erstellen.
Recommended Posts