【C#】HALCON de 画像処理(表示画像の拡大/縮小)

スポンサーリンク

今回はちょっとユーザー目線の機能を作ろうと考えます。
やりたい内容としては、表示している画像の拡大縮小です。
最終目標としては、【マウスポイントの位置を基準にスクロールで表示している画像の拡大縮小】を目指したいと思います。
やりたい内容を分けると下記2つになります。
  ■マウスポイントの位置の取得方法
  ■表示してい画像を拡大縮小方法
今回は表示している画像の拡大/縮小の表示をピックアップして説明します。

今回使用する関数

今回使用する関数は、今までに使っているものを使用する。

HOperatorSet.SetPart(HTuple, HTuple, HTuple, HTuple, HTuple)

SetPart()では、hWindowControlのディスプレイ(表示サイズ)の大きさの設定を行います。

【引数の紹介】

■HOperatorSet.SetPart(HTuple, HTuple, HTuple, HTuple, HTuple)
  第1引数:hWindowControlのハンドル
  第2引数:Y座標の始点
  第3引数:X座標の始点
  第4引数:Y座標の終点
  第5引数:X座標の終点

サンプルを作ってみる

簡単なサンプルを作成して紹介していきたいと思う。
また、今回の拡大/縮小する時の【基準点は、画像中心】で算出する。

操作画面

簡単にコントロールの説明

■btnReadImg
  ⇒ 画像読込して、hWindowControl1に表示
■lblReadImgSize
  ⇒ 読み込んだ画像のサイズを表示
■hWindowControl1
  ⇒ 画像を表示
■lblCurrentImagePart
  ⇒ 現在のhWindowControl1のImagePartの数値を表示
    (SetPartで設定した値)
■btnZoomOut
  ⇒ 表示している画像を縮小表示
■btnZoomIn
  ⇒ 表示している画像を拡大表示

定義

今回は、読み込んだ時で表示した時のSetPart()で設定した数値と倍率の数値を保持したいため、フォーム内で使える構造体と変数を定義する。

//SetPartの表示の設定値
struct SetImagePart
{
    internal double Top;
    internal double Left;
    internal double Bottom;
    internal double Right;
}
private SetImagePart ImgPart;
private double ValueZoom = 1.0;  //拡大縮小の倍率

処理

今回のテーマは、拡大縮小なので、その他の部分は省略します。※最後に補足として、記載。

■拡大

private void btnZoomIn_Click(object sender, EventArgs e)
{
    if (DispOrgImg == null) return;    //読み込んでいるかどうか
    if (Math.Round(ValueZoom,2) <= 0) return;   //0なので処理しない

    //表示削除
    HTuple hwndOrg = hWindowControl1.HalconWindow;
    HOperatorSet.ClearWindow(hwndOrg);

    ValueZoom -= 0.1;

    //現在の中心位置を取得する。
    double w = Math.Abs(ImgPart.Left) + Math.Abs(ImgPart.Right);
    double h = Math.Abs(ImgPart.Top) + Math.Abs(ImgPart.Bottom);
    double centerw = (int)((ImgPart.Left + ImgPart.Right) / 2);
    double centerh = (int)((ImgPart.Top + ImgPart.Bottom) / 2);

    SetImagePart tmp = new SetImagePart()
    {
        Left = centerw - Math.Round(w * ValueZoom / 2,2),
        Top = centerh - Math.Round(h * ValueZoom / 2, 2),
        Right = centerw + Math.Round(w * ValueZoom / 2, 2),
        Bottom = centerh + Math.Round(h * ValueZoom / 2, 2),
    };

    lblCurrentImagePart.Text = 
        $"ImagePart  上: {tmp.Top}  左: {tmp.Left}  下: {tmp.Bottom}  右: {tmp.Right}";

    HOperatorSet.SetPart(hwndOrg, tmp.Top, tmp.Left, tmp.Bottom, tmp.Right);
    HOperatorSet.DispObj(DispOrgImg, hwndOrg);
}

■縮小

private void btnZoomOut_Click(object sender, EventArgs e)
{
    if (DispOrgImg == null) return;    //読み込んでいるかどうか
    if (4.0 <= Math.Round(ValueZoom, 2)) return;   //4倍まで

    //表示削除
    HTuple hwndOrg = hWindowControl1.HalconWindow;
    HOperatorSet.ClearWindow(hwndOrg);

    ValueZoom += 0.1;

    //現在の中心位置を取得する。
    double w = Math.Abs(ImgPart.Left) + Math.Abs(ImgPart.Right);
    double h = Math.Abs(ImgPart.Top) + Math.Abs(ImgPart.Bottom);
    double centerw = (int)((ImgPart.Left + ImgPart.Right) / 2);
    double centerh = (int)((ImgPart.Top + ImgPart.Bottom) / 2);

    SetImagePart tmp = new SetImagePart()
    {
        Left = centerw - Math.Round(w * ValueZoom / 2, 2),
        Top = centerh - Math.Round(h * ValueZoom / 2, 2),
        Right = centerw + Math.Round(w * ValueZoom / 2, 2),
        Bottom = centerh + Math.Round(h * ValueZoom / 2, 2),
    };

    lblCurrentImagePart.Text = 
        $"ImagePart  上: {tmp.Top}  左: {tmp.Left}  下: {tmp.Bottom}  右: {tmp.Right}";

    HOperatorSet.SetPart(hwndOrg, tmp.Top, tmp.Left, tmp.Bottom, tmp.Right);
    HOperatorSet.DispObj(DispOrgImg, hwndOrg);
}

処理としては、変数[ValueZoom] に入れる数値が違うだけである。
ImagePart()の設定値を変更する為に、SetPart()のを使用する。

画像を縮小したい時は、
ImagePart()の値が現在より大きくすることで、表示される画像は小さくなる。


画像を拡大した時は、
ImagePart()の値が現在より小さくすることで、表示される画像は大きくなる。

計算の考え方

計算の考え方を少し紹介します。
赤点は、設定した内容の為、わかっています。
設定した内容から、【ImagePartの中心】【Width】【Height】を算出します。

この図から、求めると下記のようになる。

実行結果

画像の中心(hWindowControl中心)で拡大縮小できていそうです。

まとめ

拡大縮小の表示だけなら、SetPart()を使用する事で実現可能です。
今回の内容はSetPart()の使い方としての計算方法がメインになってしまいました。
ともあれ、拡大縮小表示が出来るようになりましたね。
次は、マウスのポインタの位置を中心に拡大縮小できるように作っていきたいと思います。
まずは第1段階として完成です。

補足(作った関数の紹介)

Zoom表示で表示する関数[DispZoom]

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);
}

画像を選択してもらう関数[SelectImageFile]

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;
}

【読込】ボタンの処理[btnReadImg_Click]

private void btnReadImg_Click(object sender, EventArgs e)
{
    //初期化
    DispOrgImg = null;
    nudFixedPointX.Value = nudFixedPointX.Minimum;
    nudFixedPointY.Value = nudFixedPointY.Minimum;

    //表示削除
    HTuple hwndOrg = hWindowControl1.HalconWindow;
    HOperatorSet.ClearWindow(hwndOrg);

    //画像を選択してもらう
    if (SelectImageFile(out string fp) == DialogResult.OK)
    {
        //画像読込
        HOperatorSet.ReadImage(out HObject img, fp);
        DispOrgImg = img;

        //最大値を設定
        HOperatorSet.GetImageSize(DispOrgImg, out HTuple wb, out HTuple hb);

        //XYのNumericUpDownの設定
        nudFixedPointX.Maximum = wb.I;
        nudFixedPointY.Maximum = hb.I;

        //サイズ表示
        lblReadImgSize.Text = "X:" + wb.D.ToString() + "pixel  Y:" + hb.D.ToString() + "pixel";

        //Zoom方式で表示
        DispZoom(hwndOrg, img);
    }
}

コメント

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