【Python/OpenCV】動画ファイル・カメラの読み込み・再生

Python版OpenCVで動画ファイル・カメラの読み込んで画面に再生・表示させる方法をソースコード付きで解説します。

【動画の読み込み】cv2.VideoCapture

Python版OpenCVでは、cv2.VideoCapture()で動画ファイルを読み込むことができます。
FLVやMP4、AVIなどに対応しています。

動画解説

サンプルコード

サンプルプログラムのソースコードです。

#-*- coding:utf-8 -*-
import cv2
import numpy as np


filepath = "C:/github/sample/python/opencv/video/input.mp4"

# 動画の読み込み
cap = cv2.VideoCapture(filepath)

# 動画終了まで繰り返し
while(cap.isOpened()):
    # フレームを取得
    ret, frame = cap.read()

    # フレームを表示
    cv2.imshow("Frame", frame)

    # qキーが押されたら途中終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
パラメータ 説明
filepath 動画ファイルのパス
frame 1コマ分のキャプチャ画像

VideoCaptureクラスは、カメラもしくは動画ファイルから画像データを取得するためのクラスです。
引数には動画ファイルのパスを指定します。
様々なメソッドがありますが、動画を読み込む場合に最低限使用するメソッドは以下の通りです。

メソッド 説明
read() 1コマ分のキャプチャ画像データを読み込みます(後述する、キャプチャデバイスをキャプチャすることもできます)。
isOpened() 正常に動画ファイルを読み込めたかはメソッドで確認できます(問題なければTrueを返す)。
release() 動画ファイルを閉じます(後述する、キャプチャデバイスをキャプチャしている場合はキャプチャデバイスを終了させます)。

動画から連続的に1コマ分のキャプチャ画像を取得するため、while内でcapture.read() を呼び出して繰り返し処理を行います。取得した1コマの画像データは、変数frameに格納されています。
そして、cv2.imshow() メソッドでウィンドウに1コマの画像データを表示します。

また、while内では、ループを止めるために「q」キーがタイプされたら break するための if 文を記述しています。
while を抜けると、処理を終了させるために VideoCapture を終了して、開いたウィンドウも終了させます。

【カメラの読み込み】cv2.VideoCapture

コンピュータに接続されているカメラ(ノートPCに搭載されているフロントカメラやUSBカメラなど)にアクセスして映像を取得することもできます。
その場合は、cv2.VideoCapture()の引数には番号を指定します。
コンピュータにカメラが1台だけしか接続されていない場合には「0」を指定し、複数のカメラが接続されている場合は「1」などの番号を指定します。
環境によっては、1台のカメラしか接続されていなくても番号が「1」だったりするので、うまくいかない場合は数値を1ずつあげて試してみてください。

 

サンプルコード

サンプルプログラムのソースコードです。

#-*- coding:utf-8 -*-
import cv2
import numpy as np


# カメラの読み込み
cap = cv2.VideoCapture(0)

# 動画終了まで繰り返し
while(cap.isOpened()):
    # フレームを取得
    ret, frame = cap.read()

    # フレームを表示
    cv2.imshow("Flame", frame)

    # qキーが押されたら途中終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

【色空間の変換】cv2.cvtColor

1コマの画像データは、変数frameに格納されています(色空間はRGB)。
よって、cv2.cvtColorで任意の色空間に変換できます。

サンプルコード

サンプルプログラムのソースコードです(グレースケールに変換する例)。

#-*- coding:utf-8 -*-
import cv2
import numpy as np


filepath = "C:/github/sample/python/opencv/video/input.mp4"

# 動画の読み込み
cap = cv2.VideoCapture(filepath)

# 動画終了まで繰り返し
while(cap.isOpened()):
    # フレームを取得
    ret, frame = cap.read()

    # グレースケール変換
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # フレームを表示
    cv2.imshow("Frame", gray)

    # qキーが押されたら途中終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows() 

カメラの映像をリアルタイムで処理して表示(再生)する場合も、このようにread()とimshow()の間に任意の処理を加えます。
ただし、1フレームを取得・処理・表示する時間がspf(1/fps)を上回ってしまうと処理落ちします。
例えば30fpsのカメラ映像でリアルタイム処理する場合、sfp=1/30=0.033なので、1フレームにかける処理時間はおおよそ30ms以内に収める必要があります。

【プロパティ】動画のサイズ、FPS、フレーム数などの取得・設定

VideoCaptureクラスのget()メソッドで、読み込んだ動画のプロパティ(サイズ、FPS、フレーム数など)を取得できます。
再生時間(秒数)は総フレーム数 / FPSで計算できます。

#-*- coding:utf-8 -*-
import cv2
import numpy as np

filepath = "C:/github/sample/python/opencv/video/input.mp4"

# 動画の読み込み
cap = cv2.VideoCapture(filepath)

# 動画のプロパティを取得
width = cap.get(cv2.CAP_PROP_FRAME_WIDTH)
height = cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_num = cap.get(cv2.CAP_PROP_FRAME_COUNT)
play_time = frame_num / fps

# 動画のプロパティを表示
print("WIDTH:", width)
print("HEIGHT:", height)
print("FPS:", fps)
print("FRAME NUM:", frame_num)
print("Play TIME[sec]:", play_time) 

"""
WIDTH: 1280.0
HEIGHT: 720.0
FPS: 25.0
FRAME NUM: 2383.0
Play TIME[sec]: 95.32
"""

VideoCaptureオブジェクトのset()メソッドを使うとプロパティを指定して値を変更できます。
第一引数にプロパティ、第二引数に変更後の値を指定します。
ただし、すべてのプロパティが変更できるわけではありません。

#-*- coding:utf-8 -*-
import cv2
import numpy as np

# カメラのキャプチャ
cap = cv2.VideoCapture(0)

# カメラのfps、サイズを変更
print(cap.set(cv2.CAP_PROP_FPS, 60))
print(cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640))
print(cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480))

# 動画終了まで繰り返し
while(cap.isOpened()):
    # フレームを取得
    ret, frame = cap.read()

    # フレームを表示
    cv2.imshow("Frame", frame)

    # qキーが押されたら途中終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

動画ファイルの場合は変更できないためset()メソッドで指定してもFalseが返されます。
カメラの場合はC変更可能でset()メソッドがTrueを返しますが、カメラが対応していないFPSを指定すると値はそのとおりに変更されないため注意が必要です。

また、取得するフレームの現在位置を任意に移動させることもできます。

#-*- coding:utf-8 -*-
import cv2
import numpy as np

filepath = "C:/github/sample/python/opencv/video/input.mp4"

# 動画の読み込み
cap = cv2.VideoCapture(filepath)

# 200フレーム目から取得
cap.set(cv2.CAP_PROP_POS_FRAMES, 200)

# 動画終了まで繰り返し
while(cap.isOpened()):
    # フレームを取得
    ret, frame = cap.read()

    # フレームを表示
    cv2.imshow("Frame", frame)

    # qキーが押されたら途中終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

ただし、総フレーム数以上の値を現在位置に設定するとそれ以上のフレームは存在しないため、read()はFalseとNoneを返します。

関連記事
1 PythonでOpenCV入門 サンプル集
2 【Python】画像処理プログラミング入門
3 【画像処理入門】アルゴリズム&プログラミング
Python画像処理
西住工房

コメント

タイトルとURLをコピーしました