第六回-03 [おまけ] スライダによる閾値の調節

前回の課題 2において、画像処理アプリケーションを変更し、「画像を読み込み、輝度 128 を閾値として二値化を行うプログラム」を作成してもらった。
この二値化の閾値を 100 や 200 に変更すると、また違った二値化画像が得られるのは 想像できると思うが、
ここまでの知識では閾値を変更するたびに再コンパイルの必要があり不便である。

ここではアプリケーションを実行中にこの閾値を変更し、二値化画像の変化を即座にチェックできるよう プログラムを変更してみよう。

このページの内容は、C/C++ の解説というよりは Visual C++ の解説である。


二値化プログラムの完成

まずは出発点の二値化プログラムを完成させねばならない。以下のようになる。
コピーおよび貼り付け後、タブを挿入して字下げを調整してビルドし、動作を確認しておこう。

そして、動作を確認したらメニューから「ビルド」→「ソリューションのクリーン」を実行しておこう。

int gray = (int)(0.114*inImage[index(i,j) + 0] + 0.587*inImage[index(i,j) + 1] + 0.299*inImage[index(i,j) + 2]);
if(gray>=128){
	outImage[index(i,j) + 0] = 255;  // Blue
	outImage[index(i,j) + 1] = 255;  // Green
	outImage[index(i,j) + 2] = 255;  // Red
}else{
	outImage[index(i,j) + 0] = 0;  // Blue
	outImage[index(i,j) + 1] = 0;  // Green
	outImage[index(i,j) + 2] = 0;  // Red
}




スライダの追加

では順を追って解説する。まずは、閾値を調節するためのスライダーを追加しよう。

まず、ソリューションエクスプローラー上で「リソースファイル」→「ImageOpen.rc」をダブルクリックする。すると、「リソースビュー」が開く。
現れたリソースビューから「ImageOpen.rc」→「Dialog」→「IDD_IMAGEOPEN_DIALOG」をダブルクリックする。

すると、アプリケーションの画面をデザインするウインドウが現われる。



次に、Visual Studio のウインドウの左端に折り畳まれているツールボックスを表示する。
下図は古い Visual Studio の図なので右端にツールボックスが見えるが、現在は左端にあることが多い。

現れたツールボックスで「ダイアログエディタ」→「Slider Control」を選択し、 スライダを置きたい位置でマウスをドラッグするよう操作する。
すると、以下のようにスライダが現われる。

ツールボックスが見つからない場合は、メニューから「表示」→「ツールボックス」で表示させても良いかもしれない。



次に、追加したスライダ上で右クリックし、「変数の追加」を選択。



下記のようなダイアログが現われるはずだが、「変数名」または「名前」に例えば 「th_slider」と記入して「完了」。
余談だが th は threshold (閾値) の意味で用いた。



次に、アプリケーションのデザインを行うウインドウにおいて、 最上部のバーのところで右クリックしてプロパティを選択。



以下のように赤い四角の「メッセージボタン」をクリックし、WM_HSCROLL という箇所を探す。
そして、右側の矢印部をクリックして「<Add>OnHScroll」または「<追加>OnHScroll」を選択。



もしここで以下のように「読み取り専用である」というようなエラーが出た場合、 などをすることでエラーが出なくなることが多い。



「<Add>OnHScroll」または「<追加>OnHScroll」がうまく行くと、
「スライダを動かしたときに呼ばれる関数 (メッセージハンドラ)」が追加され、その箇所が編集できるようになる。



そこに上記のような行を追加。以下をコピー&貼り付けで良い。
これは、スライダを動かしたら画面を再描画する、という命令である。

if((CSliderCtrl *)pScrollBar == &th_slider){
	setupOutImage();
	OnPaint();
}

次に、同じコード編集画面 (ImageOpenDlg.cpp) にて、「初期化」という文字列で検索すると
以下のように「TODO: 初期化をここに追加します。」という箇所が見付かる。



ここに上記のような2行を追加。以下をコピー&貼り付けで良い。
これは「スライダの取り得る範囲を 0~255 にし、初期値を 128 に設定」という意味である。

th_slider.SetRange(0, 255);
th_slider.SetPos(128);

最後に、画像処理の本質部で「 gray>=128 」だった部分を

gray>= th_slider.GetPos()

に変更。 これは、128 という値の替わりにスライダの値を利用する、ということを意味する。



以上の元、ビルドして実行すると、以下のようにスライダにより閾値を変更できる 二値化アプリケーションが完成する。

ビルド後のアプリケーション実行時にエラーが出る場合、
一度メニューから「ビルド」→「ソリューションのクリーン」を実行してから 再度ビルドするとエラーが消える可能性がある。



なお、このアプリケーションは「スライダを動かすたびに画像を開き直す」ような処理になっているので、動作はやや遅い。
本質的に動作を高速にするには、画像の入出力部を見直す必要があろう。

なお、下記の Debug を Release にしてからビルド→実行をすると、 最適化が行われるので動作は若干高速になる。
(Debug では最適化は行われない)

ただし、本質的に動作速度を改善するにはアルゴリズムを見直す必要がある。







←第六回-02 配列の実用例第六回課題→

非情報系学生のための C/C++ 入門に戻る