OpenCV(Python Bindings)で任意の位置から動画を再生する
職場で、動画データからの物体検出機能等を自らで実装する必要が発生した(というか、職場で趣味的なプログラミング等をしたかったので、機会を捉えてそのように調整した。)
大学院生の頃に戻った気分で、OpenCVをいじっていたのだが、標記のようなことをドンピシャで日本語で書いてあるものがあまりなかった。
ドンピシャではないが、コレくらい。
Pythonでの動画の取り扱い(OpenCVで再生とキャプチャ生成)
OpenCVで動画を再生する際には、概ねこんなループを書く。
OpenCV-Pythonチュートリアル — OpenCV-Python Tutorials 1 documentation
import numpy as np import cv2 cap = cv2.VideoCapture('vtest.avi') while(cap.isOpened()): ret, frame = cap.read() cv2.imshow('frame',frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
cap = cv2.VideoCapture('vtest.avi')にて、読み込む動画ファイルを指定し、
ret, frame = cap.read()にて、変数frameに次のコマ(フレーム)の画像を、いわば本のページをめくるように入れていく(そして変数retには、次のコマがあるか無いかを示す、真偽値が代入される)。
そして、cv2.imshow()にてウィンドウに表示する。というのを繰り返し、次のコマ(フレーム)を連続で更新することにより、動画の再生という機能を実現する。
cap.read()は、次のコマを呼んでくる、という機能しかないので、当然ながらこのままでは、動画の最初から最後まで、順番に再生していくしかない。
「python opencv 任意 再生」とかで調べてたら、最初に1回通しで動画の全コマを取得しといて持っておき、それを読み出す、みたいな方法が出てきて、マジかよ、と思っていたのだが、さすがに解決策はあった。
任意の位置で再生するには、最初に貼ったリンクに答えが書いてあるのだが、VideoCaptureクラスのsetメソッドを用いて、「次にデコード/キャプチャされるフレームのインデックス」を指定してやる。
コードに戻ると、whileループの前に、こいつを差し込む。
cap.set(cv2.CAP_PROP_POS_FRAMES, nini)
niniは任意のフレーム位置で、整数値である。
cv2.CAP_PROP_POS_FRAMESは、フラグと呼ばれるもので、コレにより、setメソッド(そしてgetメソッド)でいじるプロパティを指定する。
getメソッドでは、動画のプロパティ値を取得することができる。
frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 総フレーム数の取得 frame_Num = int(cap.get(cv2.CAP_PROP_POS_FRAMES)) # 現在の再生位置(フレーム位置)の取得
めでたしめでたし。
というのが2ヶ月前の出来事です。今は、動画をプレイヤーもどきで再生し、当該の領域にタグを付けていく機能を作りましたので、そのうちgitに上げていこうと思います。