ことのはじまり
とある依頼があり、10時間ぐらいのゲーム動画を機械学習することになったので
進捗状況をコンソール出力しながら動画を読み込むモジュールを作りました。
普通のプログラム
import cv2
import sys
fpath = 'data/videos/sample_video.mp4'
video = cv2.VideoCapture(fpath)
can_read, first = video.read()
if not can_read:
sys.exit()
progress_step = 60 # 60フレームに1回、進捗を表示する
count = 0
max = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
while video.isOpened():
if(count % progress_step == 0):
print(f'Progress rate: {count}/{max}')
ok, frame = video.read()
if ok:
# やりたい処理
else:
break
video.release()
実行結果
Progress rate: 0/2700
Progress rate: 60/2700
Progress rate: 120/2700
Progress rate: 180/2700
...
所感
目的は達成できてるのですが、他のプログラムでも動画読み込み系の処理があり、そこでも使いまわしたいので、どこからでも呼べるような関数にすることに。
関数化Ver
関数
reader.py
def video_read(input):
"""
Parameters
----------
input: str
Input video path
Returns
------
Iterator[np.ndarray]
Generator of video frame
"""
# video capture start
video = cv2.VideoCapture(input)
can_read, first = video.read()
if not can_read:
print('Cannot read video file')
return
max = int(video.get(cv2.CAP_PROP_FRAME_COUNT))
yield first
progress_step = 60 # 60フレームに1回、進捗を表示する
count = 0
while video.isOpened():
if(count % progress_step == 0):
print(f'Progress rate: {count}/{max}')
ok, frame = video.read()
if ok:
count += 1
yield frame
else:
break
video.release()
呼び出し元
import reader
it = reader.video_read('data/videos/sample_video.mp4')
try:
first = next(it)
except StopIteration:
sys.exit()
for image in it:
# やりたい処理
まとめ
呼び出し元はすごくスッキリしました。
動画読み込み系の処理と、メインのやりたい処理が分離され明確になったと思います。
Pythonのジェネレータを上手に活かせた気がします。
今回の記事、スマブラー関係なくてすみません...