2017-12-27 81 views
1

私は短いビデオとフォルダの画像を持つフォルダを持っています。ほとんどの画像はビデオの中の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") 
... 

このアルゴリズムは、画像と動画を関連付けるために良い十分のようですが、それは、私はより多くのスレッドを使用したい場合でも、かなり遅いです。それを速くする方法はありますか?たぶん異なるアルゴリズムやビデオや画像のいくつかの前処理?私はどんなアイデアにも喜んでいただけます!

+1

各スクリーンショットごとにすべてのビデオのすべてのフレームのサイズを変更するのではなく、スクリーンショットのサイズを一度変更してビデオのサイズに合わせるのは理にかなっていませんか? –

+0

@DanMašekたぶん、私はそれを試みます。スクリーンショットはビデオフレームよりも解像度が低いので、解像度を下げるとSSIMの計算が速くなると思いました。 –

+2

なぜ知覚ハッシュ(例えば、img - > 128ビット)を使用して検索/検索に効率的なkd-trees/ball-treeなどを使用してみませんか? – sascha

答えて

0

saschaの提案に基づいて、すべてのスクリーンホストのビデオとダッシュのすべてのフレームのダッシュ(source)を計算し、ハミング距離(source)を使用して比較しました。

def dhash(image, hashSize=16): #hashSize=16 worked best for me 
    # resize the input image, adding a single column (width) so we 
    # can compute the horizontal gradient 
    resized = cv2.resize(image, (hashSize + 1, hashSize)) 

    # compute the (relative) horizontal gradient between adjacent 
    # column pixels 
    diff = resized[:, 1:] > resized[:, :-1] 

    # convert the difference image to a hash 
    return sum([2 ** i for (i, v) in enumerate(diff.flatten()) if v]) 

def hamming(a, b): 
     return bin(a^b).count('1') 

この解決策は、私のニーズに迅速かつ十分に正確です。 different hashing function(例:OpenCVのpHash)を使用した場合、結果が向上する可能性が最も高いですが、OpenCV python bidingでそれらを見つけることができませんでした。

関連する問題