【C#】HALCON de 画像処理(ブロブ処理)

スポンサーリンク

今回はブロブ処理(ブロブ解析)を紹介します。
ブロブ(=Blob)とは、『塊』のことです。
ブロブ処理では、塊の数や大きさや位置などの情報を取得していきます。

今回使用する関数

2つの関数を使います。

HOperatorSet.Regiongrowing(HObject, out HObject, HTuple, HTuple, HTuple, HTuple)
   Regionをグループ分けする
■HOperatorSet.AreaCenter(HObject, out HTuple, out HTuple, out HTuple)
   Regionのグループ分けされた結果を取得する

引数の内容は下記の通り

HOperatorSet.Regiongrowing(HObject, out HObject, HTuple, HTuple, HTuple, HTuple)
  第1引数:入力画像
  第2引数:グループ分けされたRegion
  第3引数:垂直距離(Def:3)
  第4引数:水平距離(Def:3)
  第5引数:グレー値の許容値(Def:6)
  第6引数:最小サイズ(指定サイズ以上を抽出)
■HOperatorSet.AreaCenter(HObject, out HTuple, out HTuple, out HTuple)
  第1引数:入力Resion(グループ分けされているRegion)
  第2引数:[出力]面積の大きさ
  第3引数:[出力]重心位置(垂直方向[y方向])
  第4引数:[出力]重心位置(水平方向[x方向])

流れとしては
画像をRegion分けして、そのRegionのデータの重心位置を取得する流れになります。

サンプルを作ってみる

まずは分かりやすくサンプル画像を作りました。
この画像を検証してみたいと思います。

操作画面

簡単に配置したコントロールの説明です。

[Button]btnReadImg        :入力画像の読み込み
[HWindowControl]HWindowControl1 :入力画像の表示
[Button]btnBlog         :ブロブ(Blob)の実行
[DataGridView]dgvResult     :ブロブ(Blog)の結果表示

定義

NameSpaceを定義します。

using HalconDotNet;

サンプル内で使用する変数を定義します。

HObject DispOrgImg = null;      //読み込んだ画像
const double DEF_W = 640.0;
const double DEF_H = 480.0;

処理

btnBlobをクリックされた時の処理を紹介します。
サンプル画像が複雑ではないので、デフォルト値で実施しています。

private void btnBlob_Click(object sender, EventArgs e)
{
    if (DispOrgImg == null) return;    //読み込んでいるかどうか

    //グループ分けして、取得する
    HOperatorSet.Regiongrowing(DispOrgImg, out HObject regions,3, 3, 6, 100);
    HOperatorSet.AreaCenter(regions, out HTuple area, out HTuple y, out HTuple x);

    //検出個数分行を追加する。
    dgvResult.Rows.Clear();
    dgvResult.Rows.Add(area.Length);

    //検出結果を表示する
    HTuple hwnd = hWindowControl1.HalconWindow;
    for(int n = 0;n < area.Length;n++)
    {
        dgvResult[0, n].Value = x[n].D.ToString("F3");
        dgvResult[1, n].Value = y[n].D.ToString("F3"); 
        dgvResult[2, n].Value = area[n].D.ToString("F3");

        //取得位置にマーク
        HOperatorSet.SetColor(hwnd, "red");
        HOperatorSet.DispCross(hwnd, y[n], x[n], 10, 0.0);
    }
}

取得したデータをDataGridViewに表示しています。
ただ取得した位置が分かるようにクロス線を描くように処理を追加しました。
取得したデータは、配列のようにして値を取得する事が出来ます。

実行結果

最初の1つ目の結果は、全体の結果です。その為、無視してもいいかもしれません。
最初をスキップすれば、問題なさそうな気がしますね。
当たり前なのですが、三角は、他の図形に比べて、重心が下がります。(白のエリアが上下対象ではないので。)

まとめ

今回はブロブ解析の方法を紹介しました。
関数名が分からなくて、めっちゃサンプルを探しまくりました。
どうやって出会ったかも覚えてないくらいですww
人の目で見た時の「この白があるやん!」とか「この青をみつけてな!」などといった場面に使用できます。

補足

ユーザーにファイル指定してもらう関数

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;
    dgvResult.Rows.Clear();

    //表示削除
    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);
    }
}

コメント

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