ライブ表示とトリガーの制御(キーボード入力したタイミングで保存)

概要

一般的にカメラのトリガーとは、撮影や画像の保存のタイミングを人の手や外部機器からの信号などでタイミング制御する事です。例えばスマホのカメラでもシャッターボタンや録画開始ボタンを押すと思いますが、それもトリガー入力と言えます。 ここでは、OpenCVを使って任意のタイミング(トリガー入力)でライブ表示中の画像を静止画で保存する方法をプログラムコードを交えて紹介します。

補足:ハードトリガーとソフトトリガー

トリガーにも入力形式で2つに分類できます。

ハードトリガー ハードトリガー(ハードウェアトリガー)はカメラに対して外部デバイスや装置からの信号で画像を撮影する形式です、生産ラインや撮影タイミングを他の機器と同期する必要があるシステムで多く使用されており、産業用カメラによく搭載されている機能です。
ソフトトリガー ソフトトリガー(ソフトウェアトリガー)はカメラを制御するソフトウェア(DirectShowや専用ドライバ)から撮影タイミングを制御する形式です、この場合は決まった時刻や等間隔の時間で撮影したり、マウスやほかのプログラムからの命令で撮影を行ったりすることが可能です。

補足:OpenCVで実装できるトリガー

先の補足を読んで疑問に思った方も居るかと思います、実はOpenCV単体ではカメラに対する 撮影タイミングを厳密なトリガーとして制御するのは難しい部分があります。この記事では"撮影"のトリガーではなく"保存"機能としてのソフトトリガーを実装していますので、くれぐれも混同しないようにご注意ください。 あくまUVC(USB Video Class)カメラは、USB接続で汎用性が高い一方で、外部トリガー機能が実装されていないという制約があります。下記のプログラムのようにキーボード操作やソフトウェア上でタイミングをとることである程度同期を図れますが、撮影の命令を行ってから画像を取得するまでに遅延が生じてしてしまいます。

出力結果

OpenCV使ってトリガー入力でライブ表示中の画像を保存する方法

プログラム全体

#解説1 import cv2 #解説2 # カメラのビデオキャプチャを開始 cap = cv2.VideoCapture(0) #解説3 # 保存するフレームのインデックス frame_index = 0 while True: # フレームをキャプチャ ret, frame = cap.read() if not ret: break # フレームを表示 cv2.imshow('Live', frame) # キー入力を待つ key = cv2.waitKey(1) & 0xFF # 's'キーが押されたらフレームをキャプチャして保存 if key == ord('s'): cv2.imwrite(f'frame_{frame_index}.png', frame) frame_index += 1 print(f'Frame {frame_index} captured and saved.') # 'q'キーが押されたらループから抜ける elif key == ord('q'): break #解説4 # キャプチャをリリースし、ウィンドウを閉じる cap.release() cv2.destroyAllWindows()

解説

解説1: 必要なライブラリのインポート

import cv2

PythonのOpenCVライブラリをインポートしています。OpenCVは、画像処理やコンピュータビジョンに関する機能を提供するオープンソースのライブラリです。このライブラリをインポートすることで、後のコードでOpenCVの機能を使うことができます。例えば、画像の読み込み、変換、保存等、画像処理に関連する多くの機能を利用することができます。

産業用UVCのすすめ

解説2: ビデオキャプチャの開始

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: フレームのキャプチャと保存

frame_index = 0 while True: ret, frame = cap.read() if not ret: break cv2.imshow('Live', frame) key = cv2.waitKey(1) & 0xFF if key == ord('s'): cv2.imwrite(f'frame_{frame_index}.png', frame) frame_index += 1 print(f'Frame {frame_index} captured and saved.') elif key == ord('q'): break

画像を読み込むためにwhile文のループ処理をしています。ループ処理の中で、cap.read()を使ってカメラからフレームを取得します。まず、 cap.read()でカメラから1フレームを読み込みます。この関数ではretにフレームの読み込みが成功したかどうかを示すTrue/FalseのBoolean値、frameは読み込んだフレームのデータが格納し、その後フレームを表示しています。cv2.waitKey(1)は、1ミリ秒間キーボード入力を待つ関数です。この間にユーザーが's'キーを押すと、現在のフレームがframe_{frame_index}.pngという名前のPNGファイルとして保存されます。ファイル名にはフレームのインデックスが含まれ、インデックスは各保存操作後に増加します。'q'キーが押されると、ループが終了します。

おまけ:各種トリガー対応SDK

この方法だとキーボードを押してから実際に画像が保存されるまでに遅延が生じます。そのためPLCや外部機器との連携ではメーカー製のSDKを使ってカメラ本体に外部トリガー信号を入力する方法が一般的です。TheImagingSource社のカメラのSDKでは下記のサンプルプログラムのように簡単に外部トリガー信号を入力されたタイミングで操作することができます。
https://www.argocorp.com/software/sdk/ICImagingControl/Sample_program/Python_34/trigger-callback.html

解説4: リソースの解放

cap.release() cv2.destroyAllWindows()

ここでは、使用が終わったリソースを適切に解放しています。 まず、 cap.release()はプログラムが終了した際にリソースのリークを防ぐためにカメラデバイスを解放します。この呼び出しを忘れると、カメラが他のプログラムから使用できなくなる可能性があります。 最後にcv2.destroyAllWindows()は、OpenCVで開かれた全てのウィンドウを閉じます。