Ich habe einen Ordner mit kurzen Videos und Ordner mit Bildern. Die meisten Bilder sind Szenenbilder von einem der Videos, aber sie sind vielleicht nicht genau gleich (unterschiedliche Größe, Rauschen, Verlust von Details wegen Komprimierung usw.). Mein Ziel ist es, jedes Bild mit dem Video zu vergleichen, aus dem es stammt. Bisher verwende ich die OpenCV-Bibliothek, um ein Video zu laden und den SSIM-Score zwischen jedem Videoframe und jedem Bild zu berechnen. Ich speichere den höchsten SSIM-Wert jedes Bildes. Dann würde ich das Bild mit der höchsten SSIM-Punktzahl aufnehmen, es mit dem Video verknüpfen und die Funktion für das zweite Video erneut ausführen.Schneller Weg, um Screenshots mit Videos zu paaren
Hier ist mein Code:
import cv2
import numpy as np
from skimage.measure import compare_ssim
import sqlite3
#screenshots - list that contains dict(id=screenshot id, image=jpeg image data)
#video_file - str - path to video file
def generate_matches(screenshots, video_file):
for screenshot in screenshots:
screenshot["cv_img"] = cv2.imdecode(np.fromstring(screenshot["image"], np.uint8), 0)
screenshot["best_match"] = dict(score=0, frame=0)
screenshot.pop('image', None) #remove jpg data from RAM
vidcap = cv2.VideoCapture(video_file)
success,image = vidcap.read()
count = 1
while success:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
for screenshot in screenshots:
c_image = cv2.resize(image, screenshot["cv_img"].shape[1::-1])
score = compare_ssim(screenshot["cv_img"], c_image, full=False)
if score > screenshot["best_match"]["score"]:
screenshot["best_match"] = dict(score=score,frame=count)
count += 1
success,image = vidcap.read()
if count % 500 == 0:
print("Frame {}".format(count))
print("Last Frame {}".format(count))
for screenshot in screenshots:
c.execute("INSERT INTO matches(screenshot_id, file, match, frame) VALUE (?,?,?,?)",
(screenshot["id"], video_file, screenshot["best_match"]["score"], screenshot["best_match"]["frame"]))
generate_matches(list_of_screenshots, "video1.mp4")
generate_matches(list_of_screenshots, "video2.mp4")
...
Dieser Algorithmus scheint gut genug zu sein, um Videos mit Bildern zu verknüpfen, aber es ist ziemlich langsam, auch wenn ich mehrere Threads verwenden würde. Gibt es eine Möglichkeit, es schneller zu machen? Vielleicht ein anderer Algorithmus oder eine Vorverarbeitung von Videos und Bildern? Ich werde mich für irgendwelche Ideen freuen!
Anstatt die Größe jedes Frames jedes Videos einmal pro Screenshot zu ändern, wäre es nicht sinnvoller, die Screenshots einmal der Größe des Videos anzupassen? –
@ DanMašek Vielleicht werde ich es versuchen. Screenshots haben eine niedrigere Auflösung als Videoframes, daher dachte ich, dass die Verwendung der kleineren Auflösung die Berechnung von SSIM beschleunigen wird. –
Warum nicht perceptual-hash (img -> 128 bit zum Beispiel) und dann effiziente kd-trees/ball-trees oder ähnliches für die Suche/Suche verwenden? – sascha