Einer der ähnlichen Bildsuchalgorithmen ist dHash. Informationen zum Inhalt des Algorithmus finden Sie unter "Berechnen der Ähnlichkeit von Bildern mit Perceptual Hash". Ist leicht zu verstehen, aber ich verstehe, dass es sich um einen ähnlichen Bildsuchalgorithmus mit den folgenden Eigenschaften handelt.
Also habe ich versucht, mit diesem dHash die Position der Szene auf der Strecke anhand einer Szene (Onboard-Video) des Spiels des Rennspiels Assetto Corsa zu identifizieren.
Insbesondere ist der Fluss wie folgt.
① Zunächst werden alle Frames extrahiert und als PNG-Bilder aus einem Wiedergabevideo (Onboard-Video) gespeichert, das den Kurs umgibt.
② Berechnet den dHash-Hashwert für alle gespeicherten Frame-Bilder. Da es außerdem möglich ist, die Position des Fahrzeugs zu einem bestimmten Zeitpunkt anhand der Telemetriedaten zu identifizieren, die beim Aufnehmen des Wiedergabevideos erfasst wurden, wird der in Kombination mit den Positionsinformationen berechnete Hashwert in der Such-CSV-Datei gespeichert.
③ Wählen Sie andererseits eine Szene aus, in der Sie die Position auf dem Kurs anhand eines anderen Wiedergabevideos identifizieren möchten.
④ Berechnet den dHash-Hashwert für das ausgewählte Bild mit einer Szene.
⑤ Durchsuchen Sie die CSV-Datei nach dem Bild mit dem Hashwert, der dem berechneten dHash-Hashwert am nächsten kommt. Da die Positionsinformationen mit dem Bild verknüpft sind, das von der Suche in (2) getroffen wurde, wird diese Position als Position im Verlauf der ausgewählten Szene angesehen.
In einer Szene eines Rennspiels kommt es aufgrund von Unterschieden in den Linien, die durch jedes Spiel verlaufen, zu einer leichten Fehlausrichtung, selbst wenn Sie sich in der Nähe der Strecke befinden. Ich denke, der Punkt dieser Zeit ist, ob es möglich ist, nach ähnlichen Bildern zu suchen, indem solche Unterschiede absorbiert werden.
Dieses Mal werden wir den obigen Prozess in Python implementieren.
Diesmal habe ich OpenCV verwendet, um alle Einzelbilder aus der Wiedergabevideodatei (MP4-Datei) zu extrahieren. Ich verweise auf die folgende Seite.
Das Bild wird mit dem Dateinamen "(Bildnummer) .png " gespeichert.
01_extract_frames.py
import cv2
import sys
def extract_frame(video_file, save_dir):
capture = cv2.VideoCapture(video_file)
frame_no = 0
while True:
retval, frame = capture.read()
if retval:
cv2.imwrite(r'{}\{:06d}.png'.format(save_dir, frame_no), frame)
frame_no = frame_no + 1
else:
break
if __name__ == '__main__':
video_file = sys.argv[1]
save_dir = sys.argv[2]
extract_frame(video_file, save_dir)
Dieses Skript wird auch in ③ verwendet.
Von den extrahierten Rahmenbildern wird der Hashwert von dHash unter Verwendung der Dhash-Funktion des ImageHash-Pakets für das Bild berechnet, das einer bestimmten Periode (einem bestimmten Überlappungsteil) entspricht. Darüber hinaus wird es mit den Telemetriedaten verknüpft (wobei nur der relevante Teil im Voraus extrahiert wird), die vom folgenden In-Game-App-Skript erfasst und in die Such-CSV-Datei ausgegeben werden.
02_calc_dhash.py
from PIL import Image, ImageFilter
import imagehash
import csv
import sys
frame_width = 1280
frame_hight = 720
trim_lr = 140
trim_tb = 100
dhash_size = 8
def calc_dhash(frame_dir, frame_no_from, frame_no_to, telemetry_file, output_file):
#Telemetriedatendatei lesen
position_data = [row for row in csv.reader(open(telemetry_file), delimiter = '\t')]
writer = csv.writer(open(output_file, mode = 'w', newline=''))
for i in range(frame_no_from, frame_no_to + 1):
#Lesen Sie das extrahierte Bild und schneiden Sie es zu (um die am Bildrand angezeigte Zeit usw. zu löschen).
frame = Image.open(r'{}\{:06d}.png'.format(frame_dir, i))
trimed_frame = frame.crop((
trim_lr,
trim_tb,
frame_width - trim_lr,
frame_hight - trim_tb))
#Berechnung des dHash-Wertes
dhash_value = str(imagehash.dhash(trimed_frame, hash_size = dhash_size))
#Verknüpfung mit Telemetriedaten
#Da sowohl Bilder als auch Telemetrie in regelmäßigen Abständen ausgegeben werden, werden sie einfach proportional zur Anzahl der Zeilen verknüpft.
position_no = round((len(position_data) - 1) * (i - frame_no_from) / (frame_no_to - frame_no_from))
writer.writerow([
i,
dhash_value,
position_data[position_no][9],
position_data[position_no][10]
])
if __name__ == '__main__':
frame_dir = sys.argv[1]
frame_no_from = int(sys.argv[2])
frame_no_to = int(sys.argv[3])
telemetry_file = sys.argv[4]
output_file = sys.argv[5]
calc_dhash(frame_dir, frame_no_from, frame_no_to, telemetry_file, output_file)
Als Ergebnis dieses Skripts werden die folgenden Informationen (Frame-Nummer), (Hash-Wert) und (2D-Koordinatenposition in Metern) in die CSV-Datei ausgegeben.
731,070b126ee741c080,-520.11,139.89
732,070b126ee7c1c080,-520.47,139.90
733,070b126ee7c1c480,-520.84,139.92
Dieses Skript wird auch in ④ verwendet.
Das Bild mit dem Hash-Wert, der dem angegebenen Hash-Wert am nächsten kommt, wird in der Ausgabe der CSV-Suchdatei in 2-2 gesucht.
Der Brummabstand wird für die Nähe von Hashwerten verwendet. Ich benutze popcount aus dem gmpy2-Paket, um die Brummentfernung zu berechnen (weil es sehr schnell zu sein scheint).
03_match_frame.py
import csv
import gmpy2
import sys
def match_frame(base_file, search_hash):
base_data = [row for row in csv.reader(open(base_file))]
min_distance = 64
min_line = None
results = []
for base_line in base_data:
distance = gmpy2.popcount(
int(base_line[1], 16) ^
int(search_hash, 16)
)
if distance < min_distance:
min_distance = distance
results = [base_line]
elif distance == min_distance:
results.append(base_line)
print("Distance = {}".format(min_distance))
for min_line in results:
print(min_line)
if __name__ == '__main__':
base_file = sys.argv[1]
search_hash = sys.argv[2]
match_frame(base_file, search_hash)
Wie unten gezeigt, werden die Positionsinformationen ausgegeben, die den Informationen des Bildes mit dem nächstgelegenen Hashwert zugeordnet sind. (Wenn mehrere Bilder mit derselben Entfernung vorhanden sind, werden alle Bildinformationen angezeigt.)
> python.exe 03_match_frame.py dhash_TOYOTA_86.csv cdc9cebc688f3f47
Distance = 8
['13330', 'c9cb4cb8688f3f7f', '-1415.73', '-58.39']
['13331', 'c9eb4cbc688f3f7f', '-1415.39', '-58.44']
Dieses Mal wurden alle Frames des Spielvideos extrahiert, das auf dem Nürburgring-Nordkurs (Gesamtlänge 20,81 km) mit TOYOTA 86 GT lief. ⇒ Die Berechnung des Hash-Werts wurde durchgeführt und entspricht in etwa dem Bild einiger Szenen eines anderen Spielvideos, das auf dem BMW Z4 lief. Ich werde nach dem Bild suchen.
Lassen Sie uns zunächst prüfen, ob die Bilder der drei berühmten Ecken richtig durchsucht werden können.
Bild für die Suche verwendet | Hit Bild | |
---|---|---|
Bild | ||
Hashwert | ced06061edcf9f2d | 0c90e064ed8f1f3d |
Standortinformationen | (-2388.29, 69.74) | (-2416.50, 66.67) |
Hash-Wert Abstand = 10, Positionsinformationsabweichung = 28,4 m
In dHash wird gesagt, dass wenn der Hashwertabstand 10 oder weniger beträgt, er als dasselbe Bild angesehen wird, aber nur knapp. Selbst auf dem Bild ist die Form der Ecken ähnlich, aber die Positionen der umgebenden Bäume unterscheiden sich geringfügig, sodass es schwierig ist zu beurteilen, ob sie ähnlich sind oder nicht.
Bild für die Suche verwendet | Hit Bild | |
---|---|---|
Bild | ||
Hashwert | 7c5450640c73198c | 7c7c50642d361b0a |
Standortinformationen | (317.58, -121.52) | (316.18, -121.45) |
Hash-Wert Abstand = 11, Positionsinformationsabweichung = 1,4 m
Dies ist in Bezug auf Bilder ziemlich nah. Der Hashwertabstand beträgt jedoch 11, was größer als zuvor ist.
Bild für die Suche verwendet | Hit Bild | |
---|---|---|
Bild | ||
Hashwert | 665d1d056078cde6 | 665c1d856050da8d |
Standortinformationen | (2071.48, 77.01) | (2071.23, 77.12) |
Hash-Wert Abstand = 13, Positionsinformationsabweichung = 0,27 m
Die Position des Fahrzeugs ist ebenfalls sehr nah und die Bilder sehen ziemlich ähnlich aus, aber wenn Sie genau hinschauen, ist die Ausrichtung etwas anders. Der Hashwertabstand beträgt 13, was ziemlich groß ist.
Wie oben erwähnt, habe ich es in drei berühmten Ecken versucht, aber es scheint, dass ich die nächstgelegene Position identifizieren kann.
Außerdem habe ich es in 10 zufällig ausgewählten Szenen versucht und es wurde wie folgt.
Nur ein Fall, in dem nur die falsche Position getroffen wurde, ist unten dargestellt.
Bild für die Suche verwendet | Hit Bild | |
---|---|---|
Bild | ||
Hashwert | b7b630b24c1e1f1e | b7b43839481e3f1f |
Standortinformationen | (1439.61, -18.69) | (2059.41, 37.44) |
Hash-Wert Abstand = 9, Positionsinformationsabweichung = 622,34 m
Es scheint, dass die Art und Weise, wie die Bäume links und rechts wachsen, und die Spitze des Kurses sich stark von der linken Kurve oder der Geraden unterscheiden, aber der Abstand der Hashwerte liegt relativ nahe bei 9.
Übrigens, die Bilder, die ich möchte, dass Sie treffen, sind wie folgt.
Bild für die Suche verwendet | Hit Bild |
---|---|
Hash-Wertdifferenz = 13
Auf den ersten Blick sehen die Bilder ähnlich aus, aber wenn Sie genau hinschauen, sind sie nicht ausgerichtet, und daher denke ich, dass der Unterschied relativ groß ist.
In diesem Artikel habe ich dHash nach ähnlichen Bildern von Rennspielszenen durchsucht.
Die Genauigkeit ist für charakteristische Szenen wie berühmte Ecken relativ gut, aber als ich die Szenen zufällig auswählte, betrug die Gewinnrate 70% (bitte verzeihen Sie mir die geringe Anzahl bestätigter Fälle).
Es ist keine solide Interpretation, aber als persönlicher Eindruck ist es wie folgt.
Wenn Sie die Genauigkeit verbessern möchten, können Sie sich die folgenden Maßnahmen vorstellen.
Recommended Posts