私は短いビデオとフォルダの画像を持つフォルダを持っています。ほとんどの画像はビデオの中の1枚の画像ですが、正確に同じではないかもしれません(サイズ、ノイズ、圧縮のために詳細が失われるなど)。私の目標は、すべての画像を撮影したビデオにマッチさせることです。これまではOpenCVライブラリを使って1つのビデオを読み込み、各ビデオフレームと各画像の間のSSIMスコアを計算しました。私はすべての画像の最高のSSIMスコアを保存します。その後、SSIMスコアが最も高い画像を取得し、それを動画と関連付けて、2番目の動画のために再び機能を実行します。ビデオとスクリーンショットのペアリングを高速にする
は、ここに私のコードです:
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")
...
このアルゴリズムは、画像と動画を関連付けるために良い十分のようですが、それは、私はより多くのスレッドを使用したい場合でも、かなり遅いです。それを速くする方法はありますか?たぶん異なるアルゴリズムやビデオや画像のいくつかの前処理?私はどんなアイデアにも喜んでいただけます!
各スクリーンショットごとにすべてのビデオのすべてのフレームのサイズを変更するのではなく、スクリーンショットのサイズを一度変更してビデオのサイズに合わせるのは理にかなっていませんか? –
@DanMašekたぶん、私はそれを試みます。スクリーンショットはビデオフレームよりも解像度が低いので、解像度を下げるとSSIMの計算が速くなると思いました。 –
なぜ知覚ハッシュ(例えば、img - > 128ビット)を使用して検索/検索に効率的なkd-trees/ball-treeなどを使用してみませんか? – sascha