C#のWinFormsで画像加工アプリ12「Cannyフィルタで境界線抽出」

コンピュータ

Cannyフィルタで境界線抽出してみます。

ソースコード

ファイル名:Form1.cs(前回の記事のソースコードに追加)

    // Canny(Form1のメンバーとして追加)
    readonly ToolStripMenuItem cannyMenuItem = new()
    {
        Text = "Cannyフィルタ",
    };
        // Cannyフィルタ(Form1のコンストラクタに追加)
        filterMenuItem.DropDownItems.Add(cannyMenuItem);
        cannyMenuItem.Click += (s, e) =>
        {
            if (_buffBmp is null) return;
            Bitmap? bmp = CannyDialog(_buffBmp);
            if (bmp is not null)
            {
                this.Bmp = bmp;
                mainPicbox.Image = this.Bmp;
            }
        };

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

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace GazouKakou01;
public partial class Form1 : Form
{
    public static Bitmap? CannyDialog(Bitmap src)
    {
        const string filterName = "Cannyフィルタ";

        Form frm = new Form
        {
            FormBorderStyle = FormBorderStyle.FixedDialog,
            ClientSize = new System.Drawing.Size(640, 480),
            Text = filterName,
        };
        Label lbl = new Label
        {
            Size = new System.Drawing.Size(600, 20),
            Location = new System.Drawing.Point(10, 4),
            Text = filterName,
            Parent = frm,
        };
        Panel panel = new()
        {
            Size = new System.Drawing.Size(600, 250),
            Location = new System.Drawing.Point(10, 30),
            AutoScroll = true,
            Parent = frm,
        };
        PictureBox picbox = new()
        {
            SizeMode = PictureBoxSizeMode.AutoSize,
            Parent = panel,
        };
        Button okBtn = new Button
        {
            Size = new System.Drawing.Size(80,40),
            Location = new System.Drawing.Point(10, 290),
            Text = "OK",
            DialogResult = DialogResult.OK,
        };
        okBtn.Parent = frm;
        Button cancelBtn = new Button
        {
            Size = new System.Drawing.Size(80,40),
            Location = new System.Drawing.Point(100, 290),
            Text = "Cancel",
            DialogResult = DialogResult.Cancel,
        };
        cancelBtn.Parent = frm;

        frm.AcceptButton = okBtn;
        frm.CancelButton = cancelBtn;

        Label label1 = new()
        {
            Size = new System.Drawing.Size(100,40),
            Location = new System.Drawing.Point(190, 290),
            Parent = frm,
        };
        TrackBar track1 = new()
        {
            Minimum = 1,
            Maximum = 2000,
            Value = 1,
            Size = new System.Drawing.Size(200,40),
            Location = new System.Drawing.Point(300, 290),
            Parent = frm,
        };

        // mat変換
        var srcMat = BitmapConverter.ToMat(src);

        // Cannyフィルタ
        bool filterExecFlag = false;
        Func<Mat, double, double, Mat> filter = new((src, threshold1, threshold2)=>
        {
            filterExecFlag = true;
            Mat dst = new();

            Cv2.Canny(src, dst, threshold1, threshold2);
            filterExecFlag = false;
            return dst;
        });
        track1.ValueChanged += async (s, e) =>
        {
            Mat? dstMat = null;
            double threshold1 = (double)track1.Value / 10;
            double threshold2 = (double)track1.Value / 10;

            label1.Text = String.Format("th:{0}", threshold1);

            if (filterExecFlag) return;

            double backupValue;
            do {
                backupValue = threshold1;
                dstMat?.Dispose();
                dstMat = await Task.Run(()=> filter(srcMat, threshold1, threshold2));
                threshold1 = (double)track1.Value / 10;
                threshold2 = (double)track1.Value / 10;
            } while (backupValue != threshold1);
            
            picbox.Image?.Dispose();
            picbox.Image = BitmapConverter.ToBitmap(dstMat);
            dstMat?.Dispose();
        };

        frm.Load += (s, e) =>
        {
            track1.Value = 1000;
        };

        if (frm.ShowDialog() == DialogResult.Cancel)
        {
            return null;
        } else {
            return (Bitmap)picbox.Image;
        }
    }
}

実行

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

コメント