2015-04-18 24 views
17

我想申請一個scikit-image功能(特別是模板匹配功能match_template)到mp4視頻,h264編碼的幀。對於我的應用程序來說,跟蹤每幀的時間非常重要,但我知道幀速率,所以我可以從幀數中輕鬆計算出幀速率。如何閱讀由scikit-image處理的mp4視頻?

請注意,我在低資源下運行,並且我想盡可能保持依賴關係:無論如何我需要numpy,並且由於我打算使用scikit-image,因此我會避免導入(並編譯) openCV只是爲了閱讀視頻。

我在this頁面的底部看到scikit-image可以seamleassly處理存儲爲numpy數組的視頻,因此獲得這樣的結果是理想的。

+0

嗯,我試過OpenCV的同時開發一個原型我的PC應用。但是,由於我要在覆盆子pi上提供應用程序,因此我正在評估更輕的替代方案,同時還考慮了在raspi上編譯opencv的努力和依賴關係。 – gaggio

+3

參見我們正在爲用戶指南準備的[本概述](https://github.com/danielballan/scikit-image/blob/video-guide/doc/source/user_guide/video.txt)。 –

+0

@StefanvanderWalt:這個概述實際上非常有用,謝謝。可以通過增加'imageio'來改進,這也可以解決訪問特定幀編號的問題,這也在您的評論中提到。 – gaggio

回答

35

Imageio python包應該做你想做的。下面是一個使用這個包一個Python代碼片段:

import pylab 
import imageio 
filename = '/tmp/file.mp4' 
vid = imageio.get_reader(filename, 'ffmpeg') 
nums = [10, 287] 
for num in nums: 
    image = vid.get_data(num) 
    fig = pylab.figure() 
    fig.suptitle('image #{}'.format(num), fontsize=20) 
    pylab.imshow(image) 
pylab.show() 

enter image description here enter image description here

您也可以直接在文件中的圖像迭代(see the documentation):

for i, im in enumerate(vid): 
    print('Mean of frame %i is %1.1f' % (i, im.mean())) 

要安裝的ImageIO就可以使用點子:

pip install imageio 

另一種解決方案是使用moviepy(它使用類似的代碼來閱讀視頻),但我認爲imageio更輕,可以完成這項工作。


響應的第一個評論

爲了檢查是否標稱幀速率是在整個文件一樣,你可以指望幀的數量迭代器:

count = 0 
try: 
    for _ in vid: 
     count += 1 
except RuntimeError: 
    print('something went wront in iterating, maybee wrong fps number') 
finally: 
    print('number of frames counted {}, number of frames in metada {}'.format(count, vid.get_meta_data()['nframes'])) 


In [10]: something went wront in iterating, maybee wrong fps number 
     number of frames counted 454, number of frames in metada 461 

爲了顯示每個幀的時間戳:

try: 
    for num, image in enumerate(vid.iter_data()): 
     if num % int(vid._meta['fps']): 
      continue 
     else: 
      fig = pylab.figure() 
      pylab.imshow(image) 
      timestamp = float(num)/ vid.get_meta_data()['fps'] 
      print(timestamp) 
      fig.suptitle('image #{}, timestamp={}'.format(num, timestamp), fontsize=20) 
      pylab.show() 
except RuntimeError: 
    print('something went wrong') 
+0

感謝您的有用鏈接和示例。所遺漏的僅僅是每幀對應的時間。我會告訴它,時間可能在幀元數據中,否則它必須根據幀編號計算,在假設標稱幀率在整個視頻錄製期間被正確保持的情況下是可以的。 – gaggio

+0

好問題,並在一些視頻標稱幀率不正確維護。要檢查它,您可以計算迭代器中的幀數,並與元數據中的幀數進行比較,如果它們是相等的,則可以基於frame_number/fps_rate計算每個幀的時間戳。我已經更新了我的答案,以比較兩個數字。 – head7

+1

這對我很好。非常感謝。 IMO比ffmpeg/avconv/opencv/scikit-video的opencv更友好。希望我早點發現了這一點。 – rd11

16

你可以使用scikit-video,像這樣:

from skvideo.io import VideoCapture 

cap = VideoCapture(filename) 
cap.open() 

while True: 
    retval, image = cap.read() 
    # image is a numpy array containing the next frame 
    # do something with image here 
    if not retval: 
     break 

它使用avconv或ffmpeg的引擎蓋下。性能相當不錯,與將avconv中的視頻解碼相比,將數據移入python的開銷很小。

scikit-video的優點是API與OpenCV的視頻讀寫API完全相同;只需用skvideo.io.VideoCapture替換cv2.VideoCapture即可。