C#のWinFormsで画像加工アプリ8「直線検出」

コンピュータ

直線検出を行います。

ソースコード

ファイル名:Form1.Hough.cs(新規追加)

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace GazouKakou02;
public partial class Form1 : Form
{
    // メニュー項目
    readonly ToolStripMenuItem houghMenuItem = new()
    {
        Text = "直線検出",
    };
    
    /// <summary>
    /// 直線検出の初期化
    /// </summary>
    public void Init_Hough()
    {
        // メニューの登録
        filterMenuItem.DropDownItems.Add(houghMenuItem);

        // フィルター(直線検出)
        Func<Bitmap, int, double, double, Task<Bitmap>> filter = new(async (src, hough, minlen, maxgap) =>
        {
            return await Task.Run(()=>
            {
                using Mat srcMat = BitmapConverter.ToMat(src);
                using Mat dstMat = new(srcMat.Size(), MatType.CV_8UC1);
                if (srcMat.Channels() > 1)
                {
                    Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.BGR2GRAY);
                }
                Cv2.Threshold(srcMat, srcMat, 127.0d, 255.0d, ThresholdTypes.BinaryInv);

                var lines = Cv2.HoughLinesP(srcMat, 1, Math.PI/360, hough, minlen, maxgap);
                foreach(var line in lines)
                {
                    Cv2.Line(dstMat, line.P1.X, line.P1.Y, line.P2.X, line.P2.Y, new Scalar(255), 1);
                }     

                return BitmapConverter.ToBitmap(dstMat);
            });
        });

        // メニューアイテムのクリックイベント
        houghMenuItem.Click += (s, e) =>
        {
            if (_buffBmp is null) return;

            var dialog = new FilterDialog();

            Label Track2Label = new()
            {
                Location = new(10, 380),
                Size = new(120, 40),
                Parent = dialog,
            };
            TrackBar Track2 = new()
            {
                Location = new (140, 380),
                Size = new (200, 40),
                Parent = dialog,
            };

            Label Track3Label = new()
            {
                Location = new(10, 440),
                Size = new(120, 40),
                Parent = dialog,
            };
            TrackBar Track3 = new()
            {
                Location = new (140, 440),
                Size = new (200, 40),
                Parent = dialog,
            };

            dialog.Load += (s, e) =>
            {
                Track3.Maximum = 300;
                Track3.Value = 2;
                Track3.Minimum = 0;
                Track2.Maximum = 300;
                Track2.Value = 100;
                Track2.Minimum = 1;
                dialog.Track1.Maximum = 100;
                dialog.Track1.Value = 8;
                dialog.Track1.Minimum = 1;
            };

            bool filterFlag = false;
            Bitmap? bmp = null;

            dialog.Track1.ValueChanged += async (s, e) =>
            {
                dialog.Track1Label.Text = string.Format("閾値:{0}", dialog.Track1.Value);
                if (filterFlag)
                {
                    // フィルター実行中につきキャンセル
                    return;
                }

                filterFlag = true;
                dialog.OkBtn.Enabled = !filterFlag;
                var backupValue1 = dialog.Track1.Value;
                var currentValue1 = backupValue1;
                do
                {
                    backupValue1 = currentValue1;

                    int hough = currentValue1;
                    double minlen = Track2.Value;
                    double maxgap = Track3.Value;

                    bmp = await filter(_buffBmp, hough, minlen, maxgap);
                    dialog.Picbox.Image?.Dispose();
                    dialog.Picbox.Image = bmp;

                    currentValue1 = dialog.Track1.Value;
                } while( currentValue1 != backupValue1 );

                filterFlag = false;
                dialog.OkBtn.Enabled = !filterFlag;
            };

            Track2.ValueChanged += (s, e) =>
            {
                Track2Label.Text = string.Format("最小線長:{0}", Track2.Value);
            };
            Track3.ValueChanged += (s, e) =>
            {
                Track3Label.Text = string.Format("ギャップ:{0}", Track3.Value);
            };

            if (dialog.ShowDialog() == DialogResult.OK)
            {
                // OK
                this.Bmp = bmp;
            } else {
                // Cancel
                bmp?.Dispose();
            }
        };
    }
}

実行

画像が表示されている状態でメインメニュー「フィルター」→「直線検出」を選ぶ

フィルター実行はハフ閾値のトラックバーのみ

パラメタを調整

コメント