Python+OpenCVでやってみた
- ある動画をopencvで読み込みする
- 動画のnフレーム目を画像で保存したい
- 全フレームを連番で画像保存したい
そういうことが実現したかったです。
ところがPython+OpenCVを使うと驚くほど簡単、
本当に簡単に動画フレームの画像保存ができました。
その方法とかコード例を簡単にまとめます。
このページの目次
1.pip経由でOpenCV-Pythonをインストールする
まず大前提のOpenCVのインストールから
開発環境はminiconda/condaでやってます。
ただpipが使える環境ならどこでもOKです。
▼ 次のようにpipからopencvインストール
1 |
pip install opencv-python |
▼ インストールが完了した
1 2 3 4 5 6 7 8 |
install opencv-python Collecting opencv-python Downloading opencv_python-4.6.0.66-cp36-abi3-win_amd64.whl (35.6 MB) |■■■■■■■■■■| 35.6 MB 6.4 MB/s Collecting numpy>=1.13.3 Using cached numpy-1.19.5-cp36-cp36m-win_amd64.whl (13.2 MB) Installing collected packages: numpy, opencv-python Successfully installed numpy-1.19.5 opencv-python-4.6.0.66 |
ひとまずOpenCVをインストールしておきます。
恐らくextra・contribとかは気にしなくていいはず
※ 結論としてはopencv-pythonだけで十分だった
2.動画の0~n番目のフレームを一気に抽出するコード
OpenCV使うとメチャクチャ簡単に書けました。
最初から最後まで全フレームを取得してみます。
▼ 例えばこのようなコード例
1 2 3 4 5 6 7 8 9 |
fileName = "/path/to/sample.mp4" videoCapture = cv2.VideoCapture(fileName) totalFrames = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT) success,image = videoCapture.read() count = 0 while success: cv2.imwrite("./frames/frame%d.jpg" % count, image) success,image = videoCapture.read() count += 1 |
▼ 今回はこのサンプル動画を使った
▼ 実行の結果。全フレーム画像を保存完了!
0番目~n番目までフレームを画像保存に成功しました。
単純に cv2.VideoCapture(fileName) に対して動画パスを渡して解析、そのあと動画終端フレームになるまで videoCapture.read() を使ってフレーム読み込みしてるだけです。
動画フレームを frame0.jpg 、 frame1.jpg 、 frame2.jpg みたいに連番にして画像保存してます。もちろんMP4だけじゃなくてAVI・OGG・etcでもフレーム抽出は可能です。
本当に説明するまでもないくらい簡単。
3.動画のn番目フレームだけ取得する場合のコード
先ほどのコードは全フレーム取得です。
ここではn番目フレームだけ取得がしたかった
そこでこんなコードを書いてみました。
▼ n番目だけ取得するコード例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
## 動画キャプチャ videoCapture = cv2.VideoCapture(fileNames[0]) ## フレーム総数 totalFrames = videoCapture.get(cv2.CAP_PROP_FRAME_COUNT) ## n番目のフレーム画像を返す def retrieveFrameImage(frameIndex): ## インデックスがフレームの範囲内なら… if(frameIndex >= 0 & frameIndex < totalFrames): videoCapture.set(cv2.CAP_PROP_POS_FRAMES, frameIndex) ret, image = videoCapture.read() return image else: return None |
n番目のフレーム読み込みするメソッドはないです。
だから初めにフレーム総数を videoCapture.get(cv2.CAP_PROP_FRAME_COUNT) から取得してます。例えば30FPSで5秒の動画だったらフレーム総数は 150 として値が返ってきます。
そのあとは def retrieveFrameImage(frameIndex) という関数を定義し、フレームの範囲内にあるなら読み込みして返す処理をしてるだけです。
このようにframeIndex番目のフレームが取得可能
動画のnフレームを画像保存しようと思った動機
そもそもOpenCVでフレーム画像保存した理由ですが…
- 動画を一旦フレームにバラバラにしたい
- それらを1つのGIF動画にまとめてみたい
こういう事情があったからです。
Python+OpenCVだと思いのほか簡単にできました。
以上、動画フレームの画像保存について。ではまた