動画を保存する際のフレームレートの調整方法

概要

UVCカメラを使った映像録画は、実験のデータ収集や生産ラインの監視など、多くの実用的なシチュエーションで使用されます。例えば、新しい製品やシステムのパフォーマンスを評価するために高速カメラが使用されることがあります。また、UVC対応の業用カメラ等では2000fpsなど非常に高いフレームレートで動作が可能です。しかし、これらの映像データは非常に大きなファイルサイズになるため注意が必要です。ここではフレームレートの設定とビデオ保存方法について説明を行っています。

出力結果

OpenCVでUVCカメラで撮影した動画のフレームレート設定と保存する方法

プログラム全体

#解説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は、画像処理やコンピュータビジョンのためのオープンソースライブラリです。これを使うことで、画像の読み込み、変換、保存等、画像処理に関連する多くの機能を利用することができます。

産業用UVCのすすめ

解説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が作成したすべてのウィンドウを閉じます。