基本的なことではありますが、「PythonとOpenCVを用いた動画から画像への変換」についてまとめておきます。フレームごとの画像への変換と、指定した間隔ごとの画像への変換をまとめます。
動画のプロパティを取得する
まずは動画のプロパティを取得しておきます。フレームの幅と高さ、総フレーム数、fpsを調べます。fpsとは、frames per secondの略で、「1秒あたりのフレーム数(静止画像数)」を表します。
import cv2
video_path = "動画のパス"
cap = cv2.VideoCapture(video_path)
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
fps = cap.get(cv2.CAP_PROP_FPS)
print("width:{}, height:{}, count:{}, fps:{}".format(width,height,count,fps))
動画から画像への変換(フレームごと)
ファイルから動画を読み込み、1フレームごとに処理ができるようにして、それぞれを順に画像として保存する、という流れです。
import cv2
video_path = "動画のパス"
cap = cv2.VideoCapture(video_path)
num = 0
while(cap.isOpened()):
ret, frame = cap.read()
if ret == True:
cv2.imwrite("picture{:0=3}".format(num)+".jpg",frame)
print("save picture{:0=3}".format(num)+".jpg")
num += 1
else:
break
cap.release()
動画から画像への変換(フレーム指定、時間指定)
続いて、1フレームごとではなくて、もっと間隔をあけて画像として保存したい場合の方法です。
本当は1秒ごとに画像として保存したいなあと思っていたのですが、調べてもよくわからなくて、フレーム数を指定することで「1秒ごとっぽい」間隔で保存してみました。
以下のコードで、動画の1フレーム目からfpsごとに画像として保存することができます。fps(=frames per second、1秒当たりのフレーム数)ごとなので、ほぼ1秒ごとと言ってもいいのですが、これが整数でない場合は「ずれ」が生じてしまいます。
ちなみに参考までに、1フレーム目からではなくて途中から指定することもできますし、間隔もfpsごとではなくて、例えば3フレームごとなどといった指定も可能です。
import cv2
video_path = "動画のパス"
cap = cv2.VideoCapture(video_path)
count = cap.get(cv2.CAP_PROP_FRAME_COUNT)
fps = cap.get(cv2.CAP_PROP_FPS)
print("width:{}, height:{}, count:{}, fps:{}".format(width,height,count,fps))
for num in range(1, int(count), int(fps)):
cap.set(cv2.CAP_PROP_POS_FRAMES, num)
cv2.imwrite("picture{:0=3}".format(int((num-1)/int(fps)))+".jpg", cap.read()[1])
print("save picture{:0=3}".format(int((num-1)/int(fps)))+".jpg")
cap.release()
まとめ
ちょっとOpenCVで動画をあつかう機会があったのでまとめておきました。本当はフレーム指定ではなくて、1秒ごとといった時間を指定して画像として保存したかったのですが、わからなかったのでとりあえずフレーム数でなんとかしました。ただ、よく考えてみるとわざわざ1秒ごとといった時間で指定する必要性もないような気もしてきましたが…。
参考
動画を扱う — OpenCV-Python Tutorials 1 documentation
OpenCV: Flags for video I/O