【C#】HALCON de 画像処理(二値化)

スポンサーリンク

今回は【画像の二値化】をしたいと思います。
二値化(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;
}

コメント

タイトルとURLをコピーしました