コールバック関数を使ってバッファを表示させる
概要
通常、IC Imaging Controlでカメラからの画像を表示するにはWindowosFormにIC imaging Controlをフォームを張り付け、LiveStartメソッドを使うことでライブストリームを開始することができますが、カメラから取得した画像毎に処理をしなければならないことがあります。(例えば画像を取得したら静止画保存する等)ICImagingContorlクラスのLiveDisplayプロパティを無効にすることで、コントロールウィンドウに変更されたバッファを表示しながら処理を行うことができます。
サンプルプログラム
Software | IC Imaging Control 3.5, Visual Studio™ 2019 |
---|---|
サンプル(C#) | display_buffer_cs_3.5.zip |
サンプル(VB.NET) | display_buffer_vb_3.5.zip |
実行結果
Visual Studioのプログラム上ではすでにボタンの設置や関数は定義済ですので、IC Imaging Contorl3.5をインストールされていれば、実行ボタンだけですぐにデバッグで動作確認することができます。画面にあるそれぞれのボタンなどのコントローラの機能は下記の通りです。
[Start]ボタン | クリックすることでライブストリームを開始します。 |
---|---|
[Stop]ボタン | クリックすることでライブストリームを停止します。 |
Form Load起動時のイベント
private void Form1_Load( object sender, EventArgs e )
{
if( !icImagingControl1.LoadShowSaveDeviceState("lastSelectedDeviceState.xml") )
{
MessageBox.Show("No device was selected.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Close();
return;
}
// カメラの設定した解像度に合わせて表示画面を変更
icImagingControl1.LiveDisplayDefault = false;
icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
cmdStop.Enabled = false;
icImagingControl1.LiveDisplay = false;
// バッファの量を指定
InitSink();
}
// フォームのサイズを変更した時にもカメラの設定した解像度に合わせて表示画面を変更
private void Form1_SizeChanged( object sender, EventArgs e )
{
if( icImagingControl1.DeviceValid )
{
icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
}
}
// バッファの量を指定
private void InitSink()
{
icImagingControl1.Sink = new FrameQueueSink(ShowBuffer, MediaSubtypes.RGB32, 5);
}
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If Not IcImagingControl1.DeviceValid Then
IcImagingControl1.ShowDeviceSettingsDialog()
If Not IcImagingControl1.DeviceValid Then
MessageBox.Show("No device was selected.", "Display Buffer Sample")
Me.Close()
Exit Sub
End If
End If
'カメラの設定した解像度に合わせて表示画面を変更
IcImagingControl1.LiveDisplayDefault = False
IcImagingControl1.LiveDisplaySize = IcImagingControl1.Size
cmdStop.Enabled = False
IcImagingControl1.LiveDisplay = False
'バッファの量を指定
IcImagingControl1.Sink = New TIS.Imaging.FrameQueueSink(Function(img)
Return ShowImage(img)
End Function, New TIS.Imaging.FrameType(TIS.Imaging.MediaSubtypes.RGB32), 5)
End Sub
フォームロードするタイミングで最後に読み込んだデバイスの情報をxmlファイルから読み出します。
LiveDisplaySizeとWindowosFormnのサイズを一致させることで取得したイメージ全体をフォーム全体に表示することができます。
これはForm1_SizeChangedのイベントハンドラー(フォームのサイズを変更した際に起きるイベント)にも同様の処理を追加しています。
LiveDisplayを無効にすることで、コントロールウィンドウに変更されたバッファを表示することができます。
C#ではInitSinkではSinkを初期化しFrameQueueSinkを定義します。下記のように定義することで新しいフレーム毎にコールバックス関数としてShowBufferがコールされます。FrameQueueSinkはカメラから画像を受け取ると、入力キューからリングバッファを受け取り、画像データをコピーして出力キューに配置します。Sinkが画像を受け取った時点で入力キューがない場合、フレーム落ちします。Sinkがコピーしたフレーム数やドロップされたフレームの情報は下記をご覧ください。
デバイスの再接続方法とフレーム落ちの確認
IC Imaging Control Ver3.5(C#/VB.NET) サンプルプログラム
このSinkは、5フレームのQueueサイズを持ち、MediaSubtypes.RGB32イメージバッファのみ受け付けます。
FrameQueueSink クラス
IC Imaging Control_Ver3.5(C#/VB.NET) APIリファレンスマニュアル
コールバック関数の定義
private FrameQueuedResult ShowBuffer( IFrameQueueBuffer buffer )
{
icImagingControl1.DisplayImageBuffer( buffer );
return FrameQueuedResult.ReQueue;
}
Function ShowImage(img As TIS.Imaging.IFrameQueueBuffer)
IcImagingControl1.DisplayImageBuffer(img)
Return TIS.Imaging.FrameQueuedResult.ReQueue
End Function
フレームが入力され、出力キューにコピーされたあと、ShowBufferが毎回コールされます。コールバック実行中に次のフレームが出力キューに追加された場合は、コールバックが戻った直後に再度コールされます。
FrameQueuedResultは新しい画像が到着した際にコールされる関数オブジェクトで、IFrameQueueBufferを受け取ります。バッファカウントを保持するために、sinkに毎回キューされる必要があります。コールされるFrameQueueSinkの中で、ライブ画像を取得し続けるためにIFrameQueueBufferが自動的に再キューをえるためにFrameQueuedResult.ReQueueを返す必要があります。
ちなみにFrameQueuedResult.SkipReQueueにした場合にはIFrameQueueBufferを返さないので一度しかコールされずライブが更新されることはありません。
下記のAPIリファレンスマニュアルにもその他関数などの説明があります。
プログラマーズガイド:イベントを使ってバッファを表示させる
IC Imaging Control_Ver3.5(C#/VB.NET) APIリファレンスマニュアル