動画保存時のカラーフォーマット変更方法
概要
グレースケール動画の保存は、色情報が不要な場合やデータのサイズを抑えたい場合に有用です。例えば、人や物体の動きを追跡するモーショントラッキングや、明暗によるテクスチャーの分析など、色情報が重要でない画像処理タスクでは、グレースケール動画が使用されます。また、グレースケール動画はカラー動画に比べてデータ量が少ないため、ストレージの節約やデータ転送量の削減にも寄与します。
出力結果
プログラム全体
#解説1
import cv2
#解説2
# UVCカメラを開きます
cap = cv2.VideoCapture(0)
#解説3
# ビデオライターを作成します グレースケール使える
fps = 30
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (640, 480))
#解説4
# カメラが開いている間、フレームを読み込みます
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
# カラーフォーマットを変更します(ここではグレースケールに変換します)
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ビデオライターにフレームを書き込みます
out.write(gray_frame)
# フレームを表示します
cv2.imshow('frame',gray_frame)
# 'q'キーが押されたらループを抜けます
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
#解説5
# カメラとビデオライターを解放します
cap.release()
out.release()
# すべてのOpenCVウィンドウを閉じます
cv2.destroyAllWindows()
解説
解説1:ライブラリのインポート
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 = 30
fourcc = cv2.VideoWriter_fourcc(*'H264')
out = cv2.VideoWriter('output.mp4', fourcc, fps, (640, 480), isColor=False)
ここでは、ビデオを保存するためのビデオライターオブジェクトを作成しています。
cv2.VideoWriter_fourcc()
の中の引数はビデオコーデックとしてH.264のコーデックを使用しています。
その後OpenCVのVideoWriterオブジェクトを作成しています。
cv2.VideoWriter_fourcc(*'H264')
とすることで、H.264コーデックを使用して動画をエンコードします。H.264は、高い圧縮率を持ちながらも高品質な動画を提供することで広く使用されているコーデックです。
最後に、cv2.VideoWriter
を使用して、VideoWriterオブジェクトoutを作成します。このオブジェクトは、指定したパラメータに基づいて動画ファイルを生成します。ここでは、出力ファイル名('output.mp4')、コーデック(fourcc)、フレームレート(fps)、そしてフレームのサイズ((640, 480)ピクセル)を指定しています。
ここで、cv2.VideoWriter
の第4引数をisColor=False
と指定することで、グレースケール画像を保存する設定にすることができます。
多くのコーデックはカラー映像とグレースケール映像の両方をサポートしていますが特定のコーデックがグレースケール映像をサポートしているかどうかは、そのコーデックの仕様によります。したがって、特定のコーデックでグレースケール映像を保存する際に問題が発生する場合は、別のコーデックを試すか、映像をRGBカラー形式に変換してから保存することを検討してみてください。
また、動画ファイルの互換性や再生性を確保するためには、一般的に広くサポートされているコーデック(例えばH.264('mp4v')やMJPEG('MJPG')など)を使用することが推奨されます。
cv2.VideoWriter
オブジェクト自体は、動画ファイルを作成するためのもので、個々のフレームを連続して保存し、それらを一つの動画ファイルに結合する機能を持っています。
解説4:フレームの取得と保存
# カメラが開いている間、フレームを読み込みます
while(cap.isOpened()):
ret, frame = cap.read()
if ret==True:
# カラーフォーマットを変更します(ここではグレースケールに変換します)
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ビデオライターにフレームを書き込みます
out.write(gray_frame)
# フレームを表示します
cv2.imshow('frame',gray_frame)
# 'q'キーが押されたらループを抜けます
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
ここでは、カメラからのビデオストリームを読み込み、各フレームをグレースケールに変換し、その結果を動画ファイルに書き込み、同時に画面に表示するという処理を行っています。
まず、while(cap.isOpened()):
という行で、カメラが正常に開いている間、カメラから画像を取得し動画ファイルに書き込むという処理を繰り返し実行するというループを実行しています。
cap.read()というメソッドを使ってカメラからフレームを読み込んでいます。ret
は読み込みが成功したかどうかを示すブール値(TrueまたはFalse)で、frame
は読み込んだフレームのデータです。
次に、if ret==True:
という行で、ret
を参照することでフレームの読み込みが成功を判断(retがTrueの場合)し、cv2.cvtColor
という関数を使って、読み込んだフレームframe
をグレースケールに変換しています。
ちなみにグレースケールの動画を保存する場合、使用するコーデックは限られます。
しかし、これらのコーデックがすべての環境で動作するわけではないため、具体的な環境によって適切なコーデックを選択する必要があります。
cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
でグレースケールに変換したフレームを未対応のコーデックで保存しようとすると、エラーが発生するか、期待通りの結果が得られないことがあります。
その後、ビデオライターのwrite
というメソッドを使って、そのグレースケールに変換したフレームgray_frame
を逐次動画ファイルに書き込んでいます。
さらに、cv2.imshow
という関数を使って、そのグレースケールに変換したフレームを画面に表示しています。
なお、else: break
という行で、もしフレームの読み込みが失敗した場合(retがFalseの場合)も、ループから抜け出すという処理を行っています。これは、ビデオストリームの終わりに達した、または何らかのエラーが発生した場合に対応しています。
おまけ:GPUエンコード
カメラから送られてくるデータの圧縮をするのにCPUの処理負荷がかかりますが、PCに搭載されているGPUを利用してエンコード(ハードウェアエンコード)を行うことが可能です。 このハードウェアエンコードを行うことでCPUへの負荷が軽く抑えられます。詳細は下記のサンプルをご覧ください。
ttps://www.argocorp.com/software/sdk/ICImagingControl/Sample_program/Python_34/pythonnet-qt5-mediastreamsink.html
解説5: リソースの解放
# カメラとビデオライターを解放します
cap.release()
out.release()
# すべてのOpenCVウィンドウを閉じます
cv2.destroyAllWindows()
プログラムの最後でカメラとビデオライターのリソースを解放しています。プログラムが終了した際に、リソースのリークを防ぐために必要となります。cap.release()
とout.release()
はカメラと解説4で指定したビデオライターのリソースを解放し、最後にcv2.destroyAllWindows()
はOpenCVが作成したすべてのウィンドウを閉じます。