録画しながら任意のタイミングで静止画保存
概要
ICImagingControlを使用してTheImagingSourceのデバイスで取得できる映像をリアルタイムに表示しながら、任意のタイミングで録画を開始し、任意のタイミングで静止画保存をするためのサンプルプログラムです。MediaStreamSinkがメインのAPIです。
処理内容とタイミング | 1.ライブ表示のみ | 2.静止画保存 | 3.任意のタイミングで画像処理と静止画保存を同時に処理 | 4.録画しながら任意のタイミングで静止画保存 | 5.全フレームリアルタイム画像処理しながら、NG判定を静止画保存 | 6.全フレームリアルタイム画像処理しながらNG判定を静止画保存、同時に録画 | |
---|---|---|---|---|---|---|---|
処理タイミング
|
ライブ 表示 |
〇 LiveDisplay | 〇 LiveDisplay | 〇 LiveDisplay | 〇 LiveDisplay | - | - |
画像 処理 |
× | × | 〇 SnapSingle | × | - | - | |
静止画 保存 |
× | 〇 SnapSingle | 〇 SnapSingle |
〇
SetStringParameter (FrameFilter) |
- | - | |
動画 保存 |
× | × | × |
〇
LiveStart (MediaStreamSink) |
- | - | |
処理タイミング
|
ライブ 表示 |
- | - | - | - | 〇 DisplayImageBuffer | 〇 DisplayImageBuffer |
画像 処理 |
- | - | - | - | 〇 FrameQueueSinkQueueSink | 〇 FrameQueueSinkQueueSink | |
静止画 保存 |
- | - | - | - |
〇
SaveAsBitmap (コールバック関数内で定義) |
〇
SaveAsBitmap (コールバック関数内で定義) |
|
動画 保存 |
- | - | - | - | × | 〇 Windows API | |
メインになる ICImagingControl Sinkクラス |
FrameNotificationSink | FrameSnapsink | FrameSnapsink | MediaStreamSink | FrameQueueSink | FrameQueueSink | |
使用例 | 拡大観察してモニター表示しているものを作業者がモニターで目視チェック。 | モニター表示による拡大観察と作業者による画像保存操作。 | オフラインでの寸法測定と測定画像の保存。 | オフラインでの寸法測定と測定画像の保存と作業内容の録画。 | インラインの画像検査。NG判定画像保存でトレサビ管理。 | インラインの画像検査。NG判定画像保存でトレサビ管理と、録画によるラインの監視。 | |
sinkのオブジェクトが用意している コールバック関数 |
有り (コールバック関数はあるが全フレーム取得は保証されていない) |
無し | 無し | 無し | 有り | 有り | |
Sinkの切り替え | 無し | 無し | 無し | 有り | 無し | 無し |
サンプルプログラム
Software | IC Imaging Control 3.5, Visual Studio™ 2019 |
---|---|
サンプル(C#) | multi_process4_cs_3.5.zip |
サンプルツールの外観
フォームを立ち上げたときのイベント
private void Form1_Load(object sender, EventArgs e)
{
// ディスプレイのサイズを調整
icImagingControl1.LiveDisplayDefault = false;
icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
icImagingControl1.Sink = new TIS.Imaging.FrameSnapSink();
//静止画保存するための準備(フレームフィルタの定義)
_saveImageFrameFilter = FrameFilter.Create(""Save Image"");
if (_saveImageFrameFilter == null)
{
MessageBox.Show($""Failed to load the \""Save Image\"" frame filter!"", ""Error"", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
icImagingControl1.DeviceFrameFilters.Add(_saveImageFrameFilter);
}
まず、ICImagingControlのコントロールパネルのサイズを合わせるためにLiveDisplayDefault プロパティで false に設定しています。
次にicImagingControl1コントロールのSinkプロパティに、画面上にライブ表示をさせるために新しいTIS.Imaging.FrameSnapSinkオブジェクトを設定します(MediaStreamSinkは動画開始直前に設定します)。
動画保存中に静止画像保存ができるように、FrameFilter.Createメソッドを使用してSave Imageフレームフィルターを作成し、icImagingControl1.DeviceFrameFiltersコレクションに追加します。
※補足 フレームフィルターとは:
通常は、SnapSingleメソッドで静止画保存をします。しかし、動画保存をしながらSnapSingleメソッドを使う事はできないので、動画保存しながら静止画保存をするためにフレームフィルターを用いる必要があります。フレームフィルターは様々な種類があり、レンズの歪曲収差補正、デノイズ処理、画像の回転などがあります。ここでは、Save Imageフレームフィルターを用いています。Save Imageフィルターを使う為に、以下のファイルを実行ファイルと同じディレクトリに配置する必要があります。
SaveImageFrameFilter32.ftf | Save Imageのフィルター画像処理で画像保存するための設定情報が定義されたXML形式のファイル(32bitアプリケーション向け) |
---|---|
SaveImageFrameFilter64.ftf | Save Imageのフィルター画像処理で画像保存するための設定情報が定義されたXML形式のファイル(64bitアプリケーション向け) |
tis_udshl12.dll | ftfファイルの読み込む時に必要となるファイル(32bitアプリケーション向け) |
tis_udshl12_x64.dll | ftfファイルの読み込む時に必要となるファイル(64bitアプリケーション向け) |
[デバイス選択 ShowDeviceSettingsDialog]ボタンをクリックしたときの処理
private void cmdSelectDevice_Click(object sender, EventArgs e)
{
if (icImagingControl1.LiveVideoRunning)
{
icImagingControl1.LiveStop();
}
// MediaStreamSinkからFrameSnapSinkに切り替えている
icImagingControl1.Sink = new TIS.Imaging.FrameSnapSink();
// デバイスダイアログを表示する
icImagingControl1.ShowDeviceSettingsDialog();
icImagingControl1.LiveStart();
}
[デバイス選択 ShowDeviceSettingsDialog]ボタンをクリックしたときのイベントです。最初にライブモードが停止していること(LiveStartメソッドを呼んでいないこと)を確認するために、LiveVideoRunningプロパティを確認しています。ShowDeviceSettingsDialogメソッドを呼び出して、下図のようなデバイス設定ダイアログを表示し、ダイアログにてカメラの選択、ビデオフォーマットの設定、フレームレートの設定を行い、OKを押下してデバイス設定ダイアログを閉じます。その後、icImagingControl1.LiveStart();にてカメラのリアルタイムの映像を画面に表示します。
[プロパティ ShowPropertyDialog]ボタンをクリックしたときの処理
private void cmdShowOriginalDialog_Click(object sender, EventArgs e)
{
icImagingControl1.ShowPropertyDialog();
}
[プロパティ ShowPropertyDialog]ボタンをクリックしたときのイベントです。下図のようなIC Imaging Controlのプロパティダイアログを表示します。プロパティダイアログには、カメラのゲイン、露光時間、ホワイトバランス、明るさ、コントラストなどのカメラの機能に関する設定が含まれており、それらの設定をプロパティダイアログ上で変更することができます。
[画面表示ON LiveDisplay=True]ボタンをクリックしたときの処理
private void cmdDisplayON_Click(object sender, EventArgs e)
{
icImagingControl1.LiveStop();
icImagingControl1.LiveDisplay = true;
icImagingControl1.LiveStart();
}
[画面表示ON LiveDisplay=True]ボタンを押下したときのイベントです。フォーム上のICImagingControlのコントロール(画面上)にカメラの映像を表示させるか、または非表示にするか切り替えるために使用されます。LiveStartの呼び出し中は画面表示のON/OFFを切り替えることができないので、上記のようにまずLiveStopをしてライブストリーミングを停止し、LiveDisplayのプロパティにTrue/Falseを変更した後、LiveStartを再度呼び出しています。
[画面表示OFF LiveDisplay=False]ボタンをクリックしたときの処理
private void cmdDisplayOFF_Click(object sender, EventArgs e)
{
icImagingControl1.LiveStop();
icImagingControl1.LiveDisplay = false;
icImagingControl1.LiveStart();
}
[画面表示OFF LiveDisplay=False]ボタンを押下したときのイベントです。フォーム上のICImagingControlのコントロール(画面上)にカメラの映像を表示させるか、または非表示にするか切り替えるために使用されます。LiveStartの呼び出し中は画面表示のON/OFFを切り替えることができないので、上記のようにまずLiveStopをしてライブストリーミングを停止し、LiveDisplayのプロパティにTrue/Falseを変更した後、LiveStartを再度呼び出しています。
[ライブスタート LiveStart(FrameSnapSink)]ボタンをクリックしたときの処理
private void cmdLiveStartMediaStreamSink_Click(object sender, EventArgs e)
{
if (icImagingControl1.LiveVideoRunning)
icImagingControl1.LiveStop();
icImagingControl1.Sink = new TIS.Imaging.FrameSnapSink();
icImagingControl1.LiveStart();
}
上記はIC Imaging ControlのLiveStartを定義したものです。cmdLiveStartMediaStreamSink_Clickメソッドは、[ライブスタート LiveStart(FrameSnapSink)]ボタンがクリックされたときに呼び出されます。デバイスのSinkがMediaStreamSinkだと録画を再開してしまうので、LiveStartメソッドを呼び出す前に、MediaStreamSinkを終了し、FrameSnapSinkに切り替えています。なお、LiveDisplay = falseの場合には画面上に映像が映りませんが、カメラからは画像フレームをPCに出力するという動作を開始しています。
[録画開始 MediaStreamSink]ボタンをクリックしたときの処理
private void cmdCaptureStartMediaStreamSink_Click(object sender, EventArgs e)
{
if (icImagingControl1.LiveVideoRunning)
icImagingControl1.LiveStop();
TIS.Imaging.MediaStreamSink _aviSink = new TIS.Imaging.MediaStreamSink();
MediaStreamContainer _currentMediaStreamContainer=null;
foreach (MediaStreamContainer container in MediaStreamContainer.MediaStreamContainers)
{
if (container.Name == ""MP4"")
{
_aviSink.StreamContainer = container;
_currentMediaStreamContainer = container;
}
}
AviCompressor _currentVideoCodec=null;
foreach (AviCompressor codec in AviCompressor.AviCompressors)
{
if (codec.Name == ""MediaFoundation h.264"")
{
_aviSink.Codec = codec;
_currentVideoCodec = codec;
}
}
_aviSink = new TIS.Imaging.MediaStreamSink(_currentMediaStreamContainer, _currentVideoCodec, System.IO.Path.ChangeExtension($""{icImagingControl1.Device.ToString()}.avi"", _currentMediaStreamContainer.PreferredFileExtension));
_aviSink.SinkModeRunning = !checkBoxCapturePauseMediaStreamSink.Checked;
icImagingControl1.Sink = _aviSink;
icImagingControl1.LiveStart();
}
このコードは、ボタンをクリックしたときにIC Imaging Controlでの動画キャプチャを開始するための関数です。
最初に、もしすでにライブ映像が実行中であれば、MediaStreamSinkのsinkに切り替えるためにいったんLiveStop()関数を呼び出してライブ映像を停止させ、動画を保存するためのMediaStreamSinkオブジェクトである_aviSinkを作成します。_aviSinkは、CurrentMediaStreamContainerとCurrentVideoCodecの2つの引数をとり、それぞれ動画形式(AVI、MP4、WMVなど)と動画コーデックを指定し、System.IO.Path.ChangeExtension()関数を使って、保存する動画ファイル名を設定します。
その後、_aviSinkをicImagingControl1.Sinkに設定してLiveStartを呼び出すことで、動画保存処理が実行されます。MediaStreamSinkのsinkになっていたら、動画保存するためのメソッドはLiveStartです。動画保存するためのメソッドが別に用意されているわけではありませんので注意してください。
[録画の中断・再開]チェックボックスを変更したときの処理
private void checkBoxCapturePauseMediaStreamSink_CheckedChanged(object sender, EventArgs e)
{
icImagingControl1.Sink.SinkModeRunning = !icImagingControl1.Sink.SinkModeRunning;
}
MediaStreamSinkで録画中に、SinkModeRunning プロパティをFalse/Trueにすると録画の一時停止/再開になります。ただしSinkModeRunning プロパティをFalseにしても、デバイスからのライブストリーミング自体は動いていますので、[画面表示ON LiveDisplay=True]ボタンをクリックした場合はライブ表示され、右上のカウンターもカウントアップされます。SinkModeRunning プロパティをFalseにした後にTrueに戻すと、録画ファイルに継続して録画をし続けることができます。
[録画停止 MediaStereamSink→FrameSnapSink]ボタンをクリックしたときの処理
private void cmdCaptureStopMediaStreamSink_Click(object sender, EventArgs e)
{
if (icImagingControl1.LiveVideoRunning)
icImagingControl1.LiveStop();
icImagingControl1.Sink = new TIS.Imaging.FrameSnapSink();
icImagingControl1.LiveStart();
}
MediaStreamSinkでのライブストリーミング(動画保存)を停止し、FrameSnapSinkでライブストリーミングを開始しています。MediaStreamSinkのままだとLiveStartで録画を再開してしまうので、FrameSnapSinkに切り替えています。
[静止画保存 FrameFilter]ボタンをクリックしたときの処理
private void cmdSnapMediaStreamSink_Click(object sender, EventArgs e)
{
if (_saveImageFrameFilter != null && icImagingControl1.DeviceValid && icImagingControl1.LiveVideoRunning)
{
imageCounter++;
string imageFileName = String.Format(""Image{0}.jpg"", imageCounter);
_saveImageFrameFilter.SetStringParameter(""ImageName"", imageFileName);
}
}
ICImagingControlのFrameFilterを使用して、静止画をキャプチャして保存しています。Form_Loadの関数内で画像保存するためのFrameFilterインスタンスを_saveImageFrameFilterで作成していますので、saveImageFrameFilterのパラメータにアクセスするだけで、フィルタの設定(画像保存)を呼び出すことができます。フィルタの設定(画像保存)を呼び出すにはSetStringParameterメソッドの引数に有効なパラメーター「ImageName」を指定することでフィルターを使用することができます。FrameFilterを使うことでMediaStreamSinkを使いながらでも静止画保存の処理を割り込んで処理することができます。
[ライブストップ LiveStop]ボタンをクリックしたときの処理
private void cmdLiveStopMediaStreamSink_Click(object sender, EventArgs e)
{
icImagingControl1.LiveStop();
icImagingControl1.Sink = new TIS.Imaging.FrameSnapSink();
}
上記はIC Imaging ControlのLiveStopを定義したものです。cmdLiveStopMediaStreamSink_Clickメソッドは、[ライブストップ LiveStop]ボタンがクリックされたときに呼び出されます。LiveStopメソッドは、カメラからのライブストリーミングを停止します。
また、カメラのSinkがMediaStreamSinkの場合、次のLiveStartで再度録画が再開してしまうため、FrameSnapSinkに切り替えています。
フレームカウントやフレームレートを記載する処理
画面右上にあるカメラから送られてくるフレーム数のカウントアップやフレーム落ちのカウントはDriverFrameDropInformationのプロパティを使っています。詳細については別のサンプルページにて解説を行っておりますので下記を参照ください。