外部トリガーで録画の開始
概要
カメラに外部トリガー信号が入力されたタイミングで録画の開始をします。
ソフトウェア側からカメラの外部トリガー端子に外部トリガーが入力されたかどうかを定期的にポーリングで監視し、ソフトウェアが入力を認識したタイミングで録画を開始します。このサンプルは外部トリガー入力を10ms毎に監視しているので、トリガー入力のパルス幅が10ms以上の長さであればトリガーを検知し録画を開始します。
サンプルプログラム
Software | IC Imaging Control 3.5, Visual Studio™ 2019 |
---|---|
サンプル(C#) | save_movie_with_trigger_start_cs_3.5.zip |
exeファイル | save_movie_with_trigger_start_app.zip ※カメラドライバとIC Imaging Control3.5(Python, C#, VB.NET)をインストールし、上記のexeファイルを実行するだけでご利用いただけます。Visual Studioの環境は必要ありません。 |
パルス幅について | カメラに入力する録画開始&終了のトリガーパルス幅は、パルス幅は26~125msで設定してください。 詳細については下記を参照ください。 パルス幅とポーリングの間隔について検証結果.xlsx |
実行結果
右クリックからプロパティやデバイス選択のダイアログ画面を呼び出すことも可能です。
また、Ctrlキーを押しながらマウスのホイールを回すことでズームイン・ズームアウトすることができます。
Form Loadでインターフェース割り当てとコントロール初期化
//グローバル変数
private VCDRangeProperty _gpioIn;
private VCDRangeProperty _gpioOut;
private VCDButtonProperty _gpioRead;
private VCDButtonProperty _gpioWrite;
private BaseSink _oldsink;
private void Form1_Load(object sender, System.EventArgs e)
{
icImagingControl1.MouseWheel += new System.Windows.Forms.MouseEventHandler(this.icImagingControl1_MouseWheel);
//xmlファイルを読み込む
if (!icImagingControl1.LoadShowSaveDeviceState("lastSelectedDeviceState.xml"))
{
MessageBox.Show("デバイスが見つかりませんでした。", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Close();
return;
}
//VCDプロパティのクラスを初期化して、ICImagingControl オブジェクトのプロパティにアクセスします。
_gpioIn = icImagingControl1.VCDPropertyItems.Find<VCDRangeProperty>(VCDGUIDs.VCDID_GPIO, VCDGUIDs.VCDElement_GPIOIn);
_gpioOut = icImagingControl1.VCDPropertyItems.Find<VCDRangeProperty>(VCDGUIDs.VCDID_GPIO, VCDGUIDs.VCDElement_GPIOOut);
_gpioRead = icImagingControl1.VCDPropertyItems.Find<VCDRangeProperty>(VCDGUIDs.VCDID_GPIO, VCDGUIDs.VCDElement_GPIORead);
_gpioWrite = icImagingControl1.VCDPropertyItems.Find<VCDRangeProperty>(VCDGUIDs.VCDID_GPIO, VCDGUIDs.VCDElement_GPIOWrite);
//sinkの設定を保存
_oldsink = icImagingControl1.Sink;
//表示するサイズを変更するのでfalseにする
icImagingControl1.LiveDisplayDefault = false;
//ライブスタート
if (icImagingControl1.DeviceValid) icImagingControl1.LiveStart();
//アスペクト比固定
intsldZoom = icImagingControl1.Height*100/ icImagingControl1.LiveDisplayOutputHeight;
icImagingControl1.LiveDisplayZoomFactor = (float)intsldZoom / 100f ;
//cboMediaStreamContainerのコンボボックスに対応するビデオフォーマットを入れる
cboMediaStreamContainer.DataSource = TIS.Imaging.MediaStreamContainer.MediaStreamContainers;
//初期のファイル名称
txtFileName.Text = "video.avi";
txtFileName.Text = System.IO.Path.ChangeExtension(txtFileName.Text, CurrentMediaStreamContainer.PreferredFileExtension);
//cboVideoCodecのコンボボックスに対応するコンテナを入れる
fillCodecListItems();
//右クリック可能
this.ContextMenuStrip = this.contextMenuStrip1;
}
まず、System.Windows.Forms.MouseEventHandlerでマウスのホイールを回したときにイベントが発火するように宣言します。
次に、LoadShowSaveDeviceStateを使って、保存したデバイスの設定"lastSelectedDeviceState.xml"を呼び出し、その後デバイス選択ダイアログを開きます。
そして、VCDプロパティのGPIOの「GP IN」「Read」「GP Out」「Write」を有効化するために下記のとおりインターフェースの呼び出しとコントロールの初期化を行います。
_gpioIn = icImagingControl1.VCDPropertyItems.Find<VCDRangeProperty>(VCDGUIDs.VCDID_GPIO, VCDGUIDs.VCDElement_GPIOIn);
プロパティ項目のVCDPropertyItem.Findメソッドを使って、「GP IN」「Read」「GP Out」「Write」のVCDPropertyElementとVCDPorpertyInterfaceに対応したものを探します。なお、VCDPropertyElementとVCDPorpertyInterfaceは下図の通り「VCD Property Inspector」から分かります。「VCD Property Inspector」はIC Imaging Controlをインストールした時に一緒にインストールされています。
VCDプロパティの基本的な使い方は下記を参照ください。
VCDプロパティの基本機能
IC Imaging Control_Ver3.5(C#/VB.NET) APIリファレンスマニュアル
その後、「_oldsink = icImagingControl1.Sink」で初期設定のFrameHandlerSinkをいつでもMediaStreamSinkに戻せるように保存しておきます。次のステップで、LiveStartにて撮影を開始し、【フォームの高さ(icImagingControl1.Height)】と【カメラから送られてくる画像の高さ(icImagingControl1.LiveDisplayOutputHeight)】から拡大率を計算し、LiveDisplayZoomFactorを使って倍率を指定し、画像サイズをフォームの大きさに合わせます。最後に、フォーム画面の下にあるコンボボックスに動画保存するためのコンテナやコーデックをセットしています。
[Ctrl]キー押しながらスクロールでズームイン・ズームアウト機能
private void icImagingControl1_MouseWheel(object sender, MouseEventArgs e)
{
//Ctrl キーが押された状態であるか確認
if ((Control.ModifierKeys & Keys.Control) == Keys.Control)
{
if (icImagingControl1.LiveDisplayDefault == false)
{
int value = (e.Delta * SystemInformation.MouseWheelScrollLines / 360) + intsldZoom;
if (30 >= value && 1 <= value)
{
intsldZoom = value;
icImagingControl1.LiveDisplayZoomFactor = (float)intsldZoom / 10.0f;
}
}
}
}
Ctrlキー押しながらズームするためには、Ctrlキーが押されてなおかつ、画像のサイズの変更(LiveDisplayDefault:false)が許可する必要がありますので、if文で条件分岐させます。 スクロール分だけ拡大するように、マウスホイールを1行分回すときには360(PCの設定にもよります)として計算し、スクロールした分だけズームイン・ズームアウトできるようにスクロールした値をLiveDisplayZoomFactorにセットします。
ポーリング監視の間隔について
private void GPIOtimer_Tick(object sender, EventArgs e)
{
if (_gpioRead != null)
{
// ビデオ キャプチャ デバイスからデジタル入力を読み取ります。
_gpioRead.Push();
if (_gpioIn.Value == 1)
{
if (blnRecordFlg == false)
{
blnRecordFlg = true;
record();
lblRecord.Text = "録画中";
btnStartCapture.Text = "録画停止";
}
else
{
blnRecordFlg = false;
lblRecord.Text = "録画停止";
icImagingControl1.LiveStop();
icImagingControl1.Sink = _oldsink;
icImagingControl1.LiveStart();
btnStartCapture.Text = "録画開始";
}
}
}
}
Windows FormにあるTimerツールを使って10msごとに下記のプログラムを動作するようにしています。
_gpioRead.Push()メソッドを使って外部トリガー信号から信号があるか読み込みます。_gpioRead.Push()の結果は_gpioInに入力されます。
_gpioIn.Valueが1になっていれば外部トリガーを入力した状態、_gpioIn.Valueが0になっていれば外部トリガーを入力されていない状態です。
blnRecordFlgのフラグを使って録画中なのか録画停止中なのか判断するようにしています。
10msごとに外部トリガーが送られているか確認していますので10ms以下のトリガーパルス幅(デュレーション)の場合、検知できないことがあります。必ず、トリガーパルス幅はポーリングのインターバル値(10ms)よりも長くなるようにしてください。
なお、ポーリング間隔は下記のWindows Formのプロパティから設定を変更することができます。
録画を開始する関数
void record()
{
//拡張子なしのファイル名を取得
string fileNameFromWithoutExt = System.IO.Path.GetFileNameWithoutExtension(txtFileName.Text);
//拡張子を取得
string ext = System.IO.Path.GetExtension(txtFileName.Text);
//日付を取得
DateTime dt = DateTime.Now;
//txtFileName.Textのファイル名の後ろ側に"yyyyMMdd_HH_mm_ss"形式の名前をつける
string newFileName = fileNameFromWithoutExt + "_" + dt.ToString("yyyyMMdd_HH_mm_ss") + ext; //←C# 5.0(VS2013)以前の場合
string newFileFullName = "";
if (System.IO.Path.GetDirectoryName(txtFileName.Text) != "")
{
newFileFullName = System.IO.Path.GetDirectoryName(txtFileName.Text) + "\\" + newFileName;
}
else
{
newFileFullName = newFileName;
}
string newFileFullNameText = System.IO.Path.ChangeExtension(newFileFullName, CurrentMediaStreamContainer.PreferredFileExtension);
//FrameHandlerSinkからMediaStreamSinkにつなぎなおす
TIS.Imaging.MediaStreamSink aviSink = new TIS.Imaging.MediaStreamSink(CurrentMediaStreamContainer, CurrentVideoCodec, newFileFullNameText);
//FrameHandlerSinkを停止する
icImagingControl1.LiveStop();
//シンクの設定をする
icImagingControl1.Sink = aviSink;
recordedTime = 0;
//MediaStreamSinkで開始する
icImagingControl1.LiveStart();
}
この関数では動画のファイル名を指定し、SinkをMediaStreamSinkに切り替えて録画を開始しています。
動画のファイル名にはファイル名の最後に日付と時間が"yyyyMMdd_HH_mm_ss"形式で付くようにしています。例えば、2022年5月17日の11時54分58秒にvideo.aviファイルを保存を実行した場合、「video_20220517_11_54_58.avi」のように保存されます。
最後に、デフォルトのSinkはフレームを取り込むのに特化したタイプのFrameHandlerSinkとなっていますので、高度なビデオファイルの録画に特化したタイプのMediaStreamSinkを使用するように宣言します。MediaStreamSinkを使うことでLiveStartをするだけで録画が開始されます。
なお、詳細については下記を参考にしてください。
動画保存(MediaStreamSink)
IC Imaging Control_Ver3.5(C#/VB.NET) サンプルプログラム
※おまけ※ [外部トリガーシミュレーション]ボタン
private void btnStartCapture_Click(object sender, System.EventArgs e)
{
if (blnRecordFlg == false)
{
blnRecordFlg = true;
record();
lblRecord.Text = "録画中";
btnStartCapture.Text = "録画停止";
}
else
{
blnRecordFlg = false;
lblRecord.Text = "録画停止";
icImagingControl1.LiveStop();
icImagingControl1.Sink = _oldsink;
icImagingControl1.LiveStart();
btnStartCapture.Text = "録画開始";
}
}
[外部トリガーシミュレーション]ボタンをクリックすることで、外部トリガーのシミュレーションができます。ボタンをクリックした場合の処理は、"ポーリング監視の間隔について"で記載した「GPIOtimer_Tick」関数と同じです。