動画を扱う

目的

  • 動画ファイルの読み込み方,表示方法,保存方法を学びます
  • PCに接続したカメラを使って撮影した映像を表示する方法を学びます
  • 以下の関数の使い方を学びます : cv2.VideoCapture(), cv2.VideoWriter()

カメラから動画を撮影する

OpenCVはカメラを使って動画を撮影するための非常に単純なインタフェースを用意しています.カメラ(私はノートPCに備え付けのウェブカメラを使っています)を使って撮影した動画をグレースケールの動画に変換して表示させましょう.初めの一歩として簡単な例になります.

動画を撮影するには VideoCapture 型のオブジェクトを生成しなければいけません.引数には撮影に使用するカメラのデバイス番号か読み込みたい動画ファイルのファイル名を指定します.デバイス番号はコンピュータに接続されているカメラを識別するための番号です.普通は1台のカメラが接続されているので,0もしくは -1をデバイス番号として指定します.もちろん,1やそれ以上の番号を指定することも可能です. VideoCapture 型のオブジェクトを生成してしまえば,1フレームごとに撮影することが可能です.ただし,撮影終了後にビデオ撮影を解放することを忘れないでください.

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    # Our operations on the frame come here
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Display the resulting frame
    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()

cap.read() は (True/False)の2値の値を返します.フレームの読み込みが正しく行われれば True を返すので,この関数の返戻値によって動画ファイルの最後まで到達したかどうかを確認できます.

オブジェクト cap が初期化できないことがあります.そのような場合,このコードはエラーを表示するようになっています. cap.isOpened() 関数を使い,Trueが返ってくるか見ることで初期化の成功を確認できます.別の方法としては, cap.open() 関数によってファイルを開けます.

この動画の属性は cap.get(propId) 関数を使って調べる事が出来ます. propId は0から10の間の整数値になり,各数値毎に動画の属性情報(この動画が指定された属性情報を持っていれば)が割り当てられます.属性情報の詳細についてはここ: Property Identifier を参照してください.幾つかの属性情報は cap.set(propId, value) 関数を使って変更できます.ここで,value は新しく設定したい値を表します.

例えば, cap.get(3)cap.get(4) を実行すると,フレームの横幅(width)と縦幅(height)が分かります.(著者が使用しているカメラであれば)デフォルトで640x480となりますが,320x240に変更するのであれば, ret = cap.set(3,320)ret = cap.set(4,240) と実行します.

Note

もしもエラーが生じるようであれば,カメラを扱えるソフトウェア(LinuxであればCheeseなど)を使って,カメラが正常に動作するか確認してください.

ファイルから動画を読み込む

ファイルから動画を読み込む方法は,基本的にはカメラから動画を撮影する方法と同じです.デバイス番号を動画ファイルのファイル名に変えるだけです.フレームを表示している間は cv2.waitKey() に適切な時間を設定してください.設定する時間が極端に短いと動画が高速に再生されてしまいますし,逆に長く設定すると極端なスロー再生になってしまします.通常は25ミリ秒と指定すれば問題ないでしょう.

import numpy as np
import cv2

cap = cv2.VideoCapture('vtest.avi')

while(cap.isOpened()):
    ret, frame = cap.read()

    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    cv2.imshow('frame',gray)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

Note

正しいバージョンのffmpeg か gstreamerがインストールされていることを確認してください.ffmpeg/gstreamerのインストールに間違いがあると VideoCapture が期待通りに動作しないことがあります.

動画を保存する

現時点で動画を撮影し,1フレームごとに処理ができるようになったので,次は動画をファイルに保存しましょう.画像として保存するなら cv2.imwrite() 関数を使うだけで十分ですが,動画ファイルとして保存するにはひと工夫必要です.

動画ファイルとして保存するために VideoWriter 型のオブジェクトを生成します.第1引数は保存する動画名(例: output.avi)を指定します.第2~第4引数は FourCC コード(詳細は次の段落で説明)を指定し,動画の再生速度(fps)と解像度を設定します.最後の引数は isColor フラグを指定します.このフラグが True であればカラーの動画,そうでなければグレースケールの動画として保存されます.

FourCC は動画のコーデックを指定するための4バイトのコードです.使用可能なコードのリストは fourcc.org で確認できます.プラットフォーム依存なので気を付けてください.以下のコードは著者のマシンでは正しく動作しました.

  • In Fedora: DIVX, XVID, MJPG, X264, WMV1, WMV2. (XVID is more preferable. MJPG results in high size video. X264 gives very small size video)
  • In Windows: DIVX (More to be tested and added)
  • In OSX : (I don’t have access to OSX. Can some one fill this?)

MJPG用のFourCC コードは cv2.VideoWriter_fourcc('M','J','P','G') もしくは cv2.VideoWriter_fourcc(*'MJPG) です.

以下のコードはカメラから撮影した映像を縦方向に反転させてから保存します.

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi',fourcc, 20.0, (640,480))

while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        frame = cv2.flip(frame,0)

        # write the flipped frame
        out.write(frame)

        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

# Release everything if job is finished
cap.release()
out.release()
cv2.destroyAllWindows()

補足資料

課題