C#のWinFormsで画像加工アプリ13「オープニング」

コンピュータ

モルフォロジー変換のオープニング処理を行います。

ソースコード

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

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

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

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace GazouKakou01;
public partial class Form1 : Form
{
    public static Bitmap? OpeningDialog(Bitmap src)
    {
        const string filterName = "オープニング";

        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 = 0,
            Maximum = 255,
            Value = 0,
            Size = new System.Drawing.Size(200,40),
            Location = new System.Drawing.Point(300, 290),
            Parent = frm,
        };


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

        // オープニング
        bool filterExecFlag = false;
        Func<Mat, int, Mat> filter = new((src, th)=>
        {
            filterExecFlag = true;
            Mat dst = new();

            if (src.Channels() > 1)
                Cv2.CvtColor(src, src, ColorConversionCodes.BGR2GRAY);
            Cv2.Threshold(src, dst, th, 255.0d, ThresholdTypes.Binary);
            var kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5,5));
            Cv2.MorphologyEx(dst, dst, MorphTypes.Open, kernel);

            filterExecFlag = false;
            return dst;
        });

        track1.ValueChanged += async (s, e) =>
        {
            Mat? dstMat = null;
            int th = track1.Value;

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

            if (filterExecFlag) return;

            int backupValue;
            do {
                backupValue = th;
                dstMat?.Dispose();
                dstMat = await Task.Run(()=> filter(srcMat, th));
                th = track1.Value;
            } while (backupValue != th);
            
            picbox.Image?.Dispose();
            picbox.Image = BitmapConverter.ToBitmap(dstMat);
            dstMat?.Dispose();
        };

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

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

実行

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

コメント