2値化
概要
ImagingControlには標準でFrameFilterメソッドが用意されています。
フィルタインターフェイスを提供するクラスでフィルタのパラメータにアクセスしたり、設定ダイアログを表示したり、フィルタの設定を保存したりするためのメソッドが含まれていますがFrameFilterでは2値化処理などは用意されておりません。
ここでは2値化処理をフィルタ機能として拡張するための方法について説明しています。このサンプルはデバイスから取得した輝度値に対して、Thresholdスライダーで設定した閾値よりも下回っていたら白色に、上回っていたら黒色にリアルタイムで変換するプログラムコードです。
Visual Studioのプログラム上ではすでにボタンの設置や関数は定義済ですので、IC Imaging Contorl3.5をインストールされていれば、実行ボタンだけですぐにデバッグで動作確認することができます。
画面にあるそれぞれのボタンなどのコントローラの機能は下記の通りです。
サンプルプログラム
Software | IC Imaging Control 3.5, Visual Studio™ 2019 |
---|---|
サンプル(C#) | binarization_cs_3.5.zip |
実行結果
[Properties]ボタン | デバイスプロパティのダイアログ画面を表示 |
---|---|
[Device]ボタン | デバイスを選択するダイアログ画面を表示 |
[Threshold]スライダー | 閾値の設定 |
[Binarization]チェックボックス | ライブ画像にフィルタをかける |
2値化フィルタのクラスの定義
フレームフィルタを作成するためには、以下の3つのメソッドを最低限実装する必要があります。FrameFilterImplインターフェースを継承したBinarizationFilterクラスを定義し、下記の3つのメソッドをオーバーライドして2値化処理を実装していきます。
Transform | ソースにあるフレームを変換、または送り先のIFrameにコピーする際に呼び出されます。 |
---|---|
GetSupportedInputTypes | 変換フィルタが入力タイプとして何をサポートしているかを取得するのに呼び出されます。 |
GetTransformOutputTypes | 利用可能な出力タイプをリクエストするために呼び出されます。変換出力タイプは優先順位をつけた上で並べられます。その機能や次のフィルタの入力タイプに合わせて選択されます。 |
public class BinarizationFilter : FrameFilterImpl
変換フィルタを実装するために必要なFrameFilterImplの基底クラスを継承したクラスBinarizationFilter を定義します。
カラーフォーマットをチェックするオーバーライド関数
public override void GetSupportedInputTypes( System.Collections.ArrayList frameTypes )
{
// このフィルタは Y800 (8bitのグレースケール画像)にのみ作用
frameTypes.Add( new FrameType(MediaSubtypes.Y800 ) );
}
GetSupportedInputTypesメソッド内のArrayListにはFrameTypeオブジェクトが格納されていて、フレームの高さや幅などがすでに存在します。
FrameTypeクラス
IC Imaging Control_Ver3.5(C#/VB.NET) APIリファレンスマニュアル
2値化フィルタを適用する前に、フレームフィルタでカラーフォーマットをチェックするために、FrameTypeを追加しています。この処理によって、画像取り込みデバイスのビデオフォーマットが変更された時、その画像データはフレームフィルタに渡される前の段階で自動的に変換されます。
フレームタイプを格納するオーバーライド関数
public override bool GetTransformOutputTypes( FrameType inType, System.Collections.ArrayList outTypes )
{
// 画像タイプの変更はしない output = input
outTypes.Add( inType );
return true;
}
GetTransformOutputTypesメソッドはArrayList outTypesにフレームタイプを格納していきます。指定したフレームタイプによって指定された入力フレームタイプからフィルタが作り出せます。2値化フィルタはフレームタイプやサイズを変えることはしないため、リストには単に入力タイプを挿入します。
2値化処理するためのオーバーライド関数
public override bool Transform( IFrame src, IFrame dest )
{
//c#でポインタを使うためブロックの宣言
unsafe
{
// 送り先のフレームが利用可能かどうかをチェック
if ( dest.Ptr == null ) return false;
//
// ユーザーはbeginParamTransfer/endParamTransferにも
// パラメータアクセスを入れる必要があるため
// beginParamTransfer/endParamTransfer が各メンバ変数からの
// 値に矛盾がないことを確認。
BeginParameterTransfer();
// メンバ変数を関数のスタックにコピーしてsetThreshold()等への
// 並行呼び出しによる上書きを防ぐ
int threshold = _threshold;
bool enabled = _enabled;
EndParameterTransfer();
byte* pIn = src.Ptr;
byte* pOut = dest.Ptr;
// 2値化が有効化どうかをのチェック
if ( enabled )
{
// 入力バッファ内の各バイトに対してしきい値以上かどうかをチェック
// 画像データの1フレームを保持するのに必要なバイト数を取得
int bufferSize = src.FrameType.BufferSize;
while ( bufferSize-- > 0 )
{
if (*pIn++ >= threshold)
{
*pOut++ = 255;
}
else
{
*pOut++ = 0;
}
}
}
else
{
// 2値化は無効: 画像データをそのままコピー
dest.CopyFrom( src );
}
}
return true;
}
フレームごとに2値化処理するための関数です。 Transformメソッドはユーザーインターフェースとは別のスレッドで実行されるので、m_bEnabledと m_thresholdのメンバ変数へのアクセスするために、アプリケーションプログラムによる並行処理が起こらないようにローカル変数を定義しておく必要があります。BeginParameterTransferでパラメータにアクセス開始し、閾値の変数(threshold)と有効無効化の変数(enabled)の取得し、EndParameterTransferでアクセス終了の宣言をすることで、フィルタのパラメータにアクセスすることができます。その後、2値化処理は各ピクセルの輝度値を閾値と比較し、輝度値が設定した閾値よりも大きければそのピクセルの値を黒(輝度値:255)に設定し、逆であれば白(輝度値:0)に設定するようにします。
コンストラクタの実装
public BinarizationFilter()
{
//フィルタ機能(2値化処理)をオン、オフ
AddBoolParam( "enable", new SetBoolParam( setEnable ), new GetBoolParam( getEnable ) );
//フィルタ機能(2値化処理)に閾値を反映・調整
AddIntParam( "threshold", new SetIntParam( setThreshold ), new GetIntParam( getThreshold ) );
}
上記で設定したGetSupportedInputTypesメソッド, GetTransformOutputTypesメソッド, Transformメソッドの3つのオーバーライトしたフィルタメソッドにアクセスするために、SetBoolParameterやGetIntParameterなどFrameFilterの汎用的機能を使ってコンストラクタ(クラスインスタンス生成時に実行されるメソッド)を実装していきます。
SetBoolParam | 2値化を有効化・無効化を設定する関数 |
---|---|
GetBoolParameter | 2値化を有効化・無効化の値Bool値を取得する関数 |
SetIntParameter | 2値化で使用する閾値を設定する関数 |
GetIntParameter | 値化で使用する閾値を取得する関数 |
AddBoolParam、AddIntParamに対してパラメータ変換を有効化させるためにデリゲートを下記のように定義する必要があります。
void setEnable( bool enable )
{
_enabled = enable;
}
bool getEnable()
{
return _enabled;
}
void setThreshold( int threshold )
{
_threshold = threshold;
}
int getThreshold()
{
return _threshold;
}
BinarizationFilterの実装
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;
}
// overlay bitmap を無効にする
icImagingControl1.OverlayBitmapPosition = TIS.Imaging.PathPositions.None;
// フレームフィルタ実装のインスタンスを作成
BinarizationFilter binFilterImpl = new BinarizationFilter();
// 新しくクラス実装をしたFrameFilter オブジェクトを作成
_frameFilter = TIS.Imaging.FrameFilter.Create( binFilterImpl );
// FrameFilterをディスプレイフレームフィルタとしてセット
icImagingControl1.DisplayFrameFilters.Add( _frameFilter );
// ライブモードの開始
icImagingControl1.LiveStart();
//フィルタパラメータを変更処理開始する
_frameFilter.BeginParameterTransfer();
//パラメータの設定 Bool型
chkEnable.Checked = _frameFilter.GetBoolParameter( "enable" );
//閾値のパラメータの設定
sldThreshold.Minimum = 0;
sldThreshold.Maximum = 255;
sldThreshold.Value = _frameFilter.GetIntParameter( "threshold" );
lblThreshold.Text = sldThreshold.Value.ToString();
sldThreshold.Enabled = chkEnable.Checked;
lblThreshold.Enabled = chkEnable.Checked;
//フィルタパラメータを変更終了する
_frameFilter.EndParameterTransfer();
}
上記はFormが起動したときに呼び出されるイベント関数です。BinarizationFilterを使うためにフィルタを使う前準備としてインスタンスを作成し、FrameFilter.Createに渡します。その後、先に設定したオーバーロードを呼び出すため、FrameFilterImplオブジェクトを継承したFrameFilterオブジェクトを作成します。これによって、ダイアログクラスのメンバ変数内にFrameFilterオブジェクトへの参照し、フィルタのパラメータにアクセスすることができますので、ICImagingControl.DeviceFrameFilters, ICImagingControl.DisplayFrameFiltersに拡張した機能である2値化処理を適用させることができます。
シンクタイプで定義したFrameFilterをディスプレイパスに設定するために、ICImagingControl.DisplayFrameFilters.Addで2値化処理の実装をラッピングしたFrameFilter オブジェクトをDisplayFrameFiltersのFrameFilters コレクションに追加します。
上記のように設定することでライブモードが開始されると、IC Imaging Controlによってライブ表示される前の画像が2値化されるようになります。
チェックボックスへの実装
private void chkEnable_CheckedChanged( object sender, EventArgs e )
{
//フレームフィルタのパラメータへアクセス開始
_frameFilter.BeginParameterTransfer();
//パラメータセットする
_frameFilter.SetBoolParameter( "enable", chkEnable.Checked );
sldThreshold.Enabled = _frameFilter.GetBoolParameter( "enable" );
lblThreshold.Enabled = _frameFilter.GetBoolParameter( "enable" );
//フレームフィルタのパラメータへアクセス終了
_frameFilter.EndParameterTransfer();
}
チェックボックスにチェックを入れた時のイベント関数です。フレームフィルタのパラメータへアクセスするためにBeginParameterTransferメソッドでフレームフィルタのパラメータへアクセス開始し、BinarizationFilterクラスで定義したSetBoolParameterメソッドで2値化処理を適用し、フレームフィルタのパラメータへアクセス終了することで2値化処理を適用することができます。
下記のAPIリファレンスマニュアルにもその他関数などの説明があります。
プログラマーズガイド:フレームフィルタの記述: 2値化処理
IC Imaging Control_Ver3.5(C#/VB.NET) APIリファレンスマニュアル