今回は【画像の二値化】をしたいと思います。
二値化(2値化)と言うのは、『画像を白と黒の2色に変換する処理の事』を言います。
この処理で白黒はっきりした画像にすることが出来ます。
今回使用する関数
HOperatorSet.Threshold(HObject, out HObject, HTuple, HTuple)
今回はThreshold()と言う関数を使います。
引数はの説明は下記の通り
第1引数:入力画像
第2引数:出力領域 ※画像ではないので注意
第3引数:グレイ閾値下限(0~255)
第4引数:グレイ閾値上限(0~255)
注意:第4引数は第3引数以上の数字ではないといけません。
逆を言うと、第3引数は、第4引数以下ではないといけません。
第3引数が第4引数より大きいと例外が発生します。
注意:第2引数で出力されるデータは画像ではありません。
サンプルを作ってみる
出力されるデータが画像ではないのが少し分かりづらいですよね。
ただ、出力されるデータが画像ではないので、画像サイズを取得する事は出来ません。
表示する時は少し工夫しました。
操作画面
簡単にコントロールの説明をします。
■btnReadImg :画像指定+hWindowControl1に表示 ■hWindowControl1 :読み込んだ画像表示用 ■btnThreshold :二値化処理+hWindowControl2に表示 ■hWindowControl1 :二値化された画像表示用 ■nudLowerLimit :二値化処理時のグレー閾値下限 ■nudUpperLimit :二値化処理時のグレー閾値上限
定義
まずはnamespaceの定義から
using HalconDotNet;
そして、フォーム内で使用する変数を定義
HObject DispOrgImg = null; //読み込んだ画像
const double DEF_W = 640.0;
const double DEF_H = 480.0;
処理
では、btnThresholdのクリック処理を紹介します。
private void btnThreshold_Click(object sender, EventArgs e)
{
if (DispOrgImg == null) return; //読み込んでいるかどうか
int lo = (int)nudLowerLimit.Value;
int hi = (int)nudUpperLimit.Value;
HOperatorSet.Threshold(DispOrgImg, out HObject _region, lo, hi);
//表示削除
HTuple hwnd = hWindowControl2.HalconWindow;
HOperatorSet.ClearWindow(hwnd);
//ImagePartをhWindowControl1と同じにする
HOperatorSet.SetPart(hwnd,
hWindowControl1.ImagePart.Top,
hWindowControl1.ImagePart.Left,
hWindowControl1.ImagePart.Bottom,
hWindowControl1.ImagePart.Right);
HOperatorSet.DispObj(_region, hwnd);
}
出力された領域(リージョン)は、DispObj()で表示する事は出来ます。
ただ画像ではない為、ImagePart()の設定は計算できないので、hWindowControl1の設定をコピーします。
実行結果
条件が一致していいるグレー閾値の場合、白色になります。
まとめ
今回は、Threshold()という関数を紹介させていただきました。
これを使用する事で、あるエリアの明るさだけを抽出する事が出来ます。
ただこの後どうすればいいか分かりませんよね?
次回は、出力されたデータ(region)を画像に変換してみたいと思います。
補足
ユーザーにファイル指定してもらう関数
private DialogResult SelectImageFile(out string fp)
{
fp = "";
OpenFileDialog ofd = new OpenFileDialog();
ofd.FileName = "";
ofd.InitialDirectory = @"C:\";
ofd.Filter = "画像ファイル(*.png;*.jpg)|*.png;*.jpg";
ofd.Title = "開くファイルを選択してください";
DialogResult res = ofd.ShowDialog();
if (res == DialogResult.OK) fp = ofd.FileName;
return res;
}
画像サイズの比率を変えずに表示枠いっぱいに表示する関数
private void DispZoom(HTuple windowhandle, HObject img)
{
//Zoom方式で表示
HOperatorSet.GetImageSize(img, out HTuple w, out HTuple h);
double rateR = DEF_H / h, rateC = DEF_W / w;
double rate = (rateR < rateC) ? rateR : rateC;
double c1 = -((DEF_W / rate) - w) / 2;
double c2 = c1 + (DEF_W / rate);
double r1 = -((DEF_H / rate) - h) / 2;
double r2 = r1 + (DEF_H / rate);
HOperatorSet.SetPart(windowhandle, r1, c1, r2, c2);
HOperatorSet.DispObj(img, windowhandle);
}
読込ボタンをクリックされた時の処理
private void btnReadImg_Click(object sender, EventArgs e)
{
//初期化
DispOrgImg = null;
//表示削除
HTuple hwndOrg = hWindowControl1.HalconWindow;
HOperatorSet.ClearWindow(hwndOrg);
//画像を選択してもらう
if (SelectImageFile(out string fp) == DialogResult.OK)
{
//画像読込
HOperatorSet.ReadImage(out HObject img, fp);
DispOrgImg = img;
//Zoom方式で表示
DispZoom(hwndOrg, img);
}
}
上限下限の入力制限
NumericUpDownに数値変更時のイベント(ValueChanged)を追加して、上限下限の制限を付けました。
private void nudLowerLimit_ValueChanged(object sender, EventArgs e)
{
NumericUpDown nud = (NumericUpDown)sender;
//値を更新
if (nudUpperLimit.Value < nud.Value) nudUpperLimit.Value = nud.Value;
nudUpperLimit.Minimum = nud.Value;
}
private void nudUpperLimit_ValueChanged(object sender, EventArgs e)
{
NumericUpDown nud = (NumericUpDown)sender;
//値を更新
if (nud.Value < nudLowerLimit.Value) nudLowerLimit.Value = nud.Value;
nudLowerLimit.Maximum = nud.Value;
}
業務でプログラミング(C#/VB/Python)を作っている。
挫折を何回も繰り返し、幾度の壁を乗り越えてきた。
乗り越えてきた事を忘れないように記録に残す。
同じ思いをしている人への情報提供になれたらと思う。
基本は初心者に向けたプログラムの情報を提供する。
コメント