動画を保存する際のフレームレートの調整方法
概要
UVCカメラを使った映像録画は、実験のデータ収集や生産ラインの監視など、多くの実用的なシチュエーションで使用されます。例えば、新しい製品やシステムのパフォーマンスを評価するために高速カメラが使用されることがあります。また、UVC対応の業用カメラ等では2000fpsなど非常に高いフレームレートで動作が可能です。しかし、これらの映像データは非常に大きなファイルサイズになるため注意が必要です。ここではフレームレートの設定とビデオ保存方法について説明を行っています。
出力結果
プログラム全体
#解説1
import cv2
#解説2
# UVCカメラを開く
cap = cv2.VideoCapture(0)
#解説3
# フレームレートを取得
fps = cap.get(cv2.CAP_PROP_FPS)
print('Original FPS:', fps)
#解説4
# フレームレートを調整(ここでは30に設定)
adjusted_fps = 30
cap.set(cv2.CAP_PROP_FPS, adjusted_fps)
#解説5
# 調整後のフレームレートを確認
adjusted_fps = cap.get(cv2.CAP_PROP_FPS)
print('Adjusted FPS:', adjusted_fps)
#解説6
# ビデオライターを作成
# fourccを'MP4V'に、出力ファイルの拡張子を'.mp4'に変更
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('output.mp4', fourcc, adjusted_fps, (640, 480), isColor=True)
#解説7
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
#解説8
# カメラとビデオライターを解放
cap.release()
out.release()
cv2.destroyAllWindows()
解説
解説1: OpenCVのインポート
import cv2
OpenCVは、画像処理やコンピュータビジョンのためのオープンソースライブラリです。これを使うことで、画像の読み込み、変換、保存等、画像処理に関連する多くの機能を利用することができます。
解説2: カメラの接続
# UVCカメラを開く
cap = cv2.VideoCapture(0)
ここでは、UVCカメラを開いて、その映像を取得するためのオブジェクトを作成しています。cv2.VideoCapture(0)
という関数は、引数にUVCカメラのIDを取り、そのカメラにアクセスするためのVideoCapture
オブジェクトを返しています。ここでの0
は、通常はシステムに接続されているデフォルトのカメラ(通常は内蔵カメラ)を指しますが、使用しているカメラによって割り振られる番号が異なりますのでご注意ください。
補足:OpenCVにおけるデバイスID
デバイスが複数接続された場合、このIDは、いつも同じとは限りません。デバイスの起動やシステムへの接続順によって変わることがほとんどです。
TheImagingSource社が提供しているSDK(ICImagingControl)ではカメラ本体にシリアル番号が割り振られており、カメラ毎に設定が容易にできます。詳細は下記をご覧ください。
https://www.argocorp.com/software/sdk/ICImagingControl/Sample_program/Python_34/open-with-built-in-dialog.html
解説3: フレームレートの取得
# フレームレートを取得
fps = cap.get(cv2.CAP_PROP_FPS)
print('Original FPS:', fps)
カメラからフレームを取得するレート(フレームレート)を取得するためのものです。フレームレートは、1秒あたりに取得されるフレーム(画像)の数を表しています。cap.get(cv2.CAP_PROP_FPS)
は、現在のフレームレートを取得します。
解説4: フレームレートの調整
# フレームレートを調整(ここでは半分に設定)
adjusted_fps = 30
cap.set(cv2.CAP_PROP_FPS, adjusted_fps)
フレームレートを設定しています。cap.set(cv2.CAP_PROP_FPS, adjusted_fps)
は、フレームレートを第2引数のadjusted_fps
に設定します。ただし、OpenCVのset関数を使用してカメラのフレームレートを変更をサポートしていないことが多いです。これは、カメラのハードウェアやドライバがフレームレートの変更を許可しないことが原因です。
解説5: 調整後のフレームレートの確認
# 調整後のフレームレートを確認
adjusted_fps = cap.get(cv2.CAP_PROP_FPS)
print('Adjusted FPS:', adjusted_fps)
フレームレートの調整が正しく行われたかを確認するためのものです。
再度cap.get(cv2.CAP_PROP_FPS)
を呼び出してフレームレートを取得し、それを表示しています。
ここで解説4で設定されているフレームレートが正しく読み込めていない場合は解説4で解説している通りカメラのハードウェアやドライバが対応していないことが考えられます。その場合はメーカー製のドライバーなどを使って開発するようにしましょう。
解説6: ビデオライターの作成
# ビデオライターを作成
# fourccを'MP4V'に、出力ファイルの拡張子を'.mp4'に変更
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('output.mp4', fourcc, adjusted_fps, (640, 480), isColor=True)
取得したフレームをビデオファイルとして保存するためのビデオライターと呼ばれる機能を実装しています。cv2.VideoWriter
はビデオライターを作成し、fourcc
は使用するビデオコーデックを指定します。ビデオコーデックとは映像や音声データをエンコード(符号化)と デコード(複合化)するプログラムのことで、動画を圧縮しながら保存する上で欠かせないプログラムです。。fourcc
は"four character code"の略で、ビデオコーデックを表す4文字のコードです。H264は一般的なビデオコーデックの一つで、高い圧縮率とビデオ画質で録画できます。
out = cv2.VideoWriter('output.mp4', fourcc, adjusted_fps, (640, 480), isColor=True)
では、ビデオファイルを書き出すためのcv2.VideoWriter
オブジェクトを作成しています。cv2.VideoWriter
の引数は以下の通りです。
output.mp4 | 書き出すビデオファイルの名前を指しています。 |
---|---|
fourcc | 使用するビデオコーデックを指定します。この例では、前述のH264コーデックが使用されます。AVIとMP4は、一般的に使用されるビデオコンテナ形式です。 |
AVI(Audio Video Interleave) | AVIは、Microsoftが開発した古いビデオコンテナ形式です。AVIは広範な互換性を持っていますが、新しいコーデックや機能をサポートしていません。 |
MP4(MPEG-4) | MP4は、動画、音声、静止画、メタデータなどを一つのファイルに格納できるコンテナ形式です。MP4は広範な互換性を持ち、高度なビデオコーデック(例えば、H.264やH.265)をサポートしています。これにより、高品質なビデオを小さなファイルサイズで保存できます。 |
adjusted_fps | ビデオのフレームレートを指定します。フレームレートは、1秒あたりのフレーム数(画像の数)を表します。 (640, 480): ビデオのフレームのサイズを指定します。この例では、各フレームのサイズは640ピクセル(幅)x 480ピクセル(高さ)です。 |
isColor=True | ビデオがカラー(True)かモノクロ(False)かを指定します。この例では、カラービデオが作成されます。この指定をしているにもかかわらずモノクロ画像になってしまう場合はカラーフォーマットに対応していない可能性があります。その場合はメーカー製のドライバーやSDKを使用するようにしてください。 |
補足:スタンダードPCで高速レコーディングを実現する
TheImagingSource社のSDK(ICImagingControl)ではフレーム落ちがないように、メモリレコーディングという手法を使って高速に画像保存できます。100fpsを超える高速画像データをHDD/SSDに書き込むと、計算上保存される枚数よりも実際に保存される画像が少ないことがあります(フレーム落ちと呼びます)。カメラから送られてくる画像データはメモリを経由してHDD/SSDに保存されますが、カメラから送られてくる画像データよりもHDD/SSDに書き込む速度が遅いため、メモリにあるデータがHDD/SSDに保存される前に上書きされてしまうことで発生しています。 このサンプルではカメラから送られてくる画像データをメモリに保存し、後処理で静止画保存しています。 予め画像を保存するためのメモリを確保することで、高速画像データであってもメモリ上の画像データを上書きすることなく画像を保存することができます。
https://www.argocorp.com/software/sdk/ICImagingControl/Sample_program/Python_34/memory.html
解説7: フレームの取得と保存
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
out.write(frame)
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
カメラが正常に開いている間、ループ処理をしています。ループ処理の中で、cap.read()
を使ってカメラからフレームを取得し、その際に正常に画像を取得できていれば、out.write(frame)
を使ってcv2.VideoWriterオブジェクトを使って、output.mp4のビデオファイルに書き込む処理を行っています。また、cv2.imshow('frame',frame)
は取得したフレームを画面に表示します。
解説8: リソースの解放
# カメラとビデオライターを解放
cap.release()
out.release()
cv2.destroyAllWindows()
プログラムの最後でカメラとビデオライターのリソースを解放しています。プログラムが終了した際に、リソースのリークを防ぐために必要となります。cap.release()
とout.release()
はカメラと解説6で指定したビデオライターのリソースを解放し、最後にcv2.destroyAllWindows()
はOpenCVが作成したすべてのウィンドウを閉じます。