C#のWinFormsで画像加工アプリ7「バイラテラルフィルタ」

コンピュータ

バイラテラルフィルタ機能を追加します。

ソースコード

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

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

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

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace GazouKakou01;
public partial class Form1 : Form
{
    public static Bitmap? BilateralDialog(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(120,40),
            Location = new System.Drawing.Point(190, 290),
            Parent = frm,
        };
        TrackBar track1 = new()
        {
            Minimum = 1,
            Maximum = 100,
            Value = 1,
            TickFrequency = 1,
            SmallChange = 1,
            LargeChange = 10,
            Size = new System.Drawing.Size(100,40),
            Location = new System.Drawing.Point(320, 290),
            Parent = frm,
        };

        Label label2 = new()
        {
            Size = new System.Drawing.Size(140,40),
            Location = new System.Drawing.Point(10, 360),
            Parent = frm,
        };
        TrackBar track2 = new()
        {
            Minimum = 1,
            Maximum = 300,
            Value = 1,
            TickFrequency = 1,
            SmallChange = 1,
            LargeChange = 10,
            Size = new System.Drawing.Size(100,40),
            Location = new System.Drawing.Point(160, 360),
            Parent = frm,
        };

        Label label3 = new()
        {
            Size = new System.Drawing.Size(150,40),
            Location = new System.Drawing.Point(270, 360),
            Parent = frm,
        };
        TrackBar track3 = new()
        {
            Minimum = 1,
            Maximum = 300,
            Value = 1,
            TickFrequency = 1,
            SmallChange = 1,
            LargeChange = 10,
            Size = new System.Drawing.Size(100,40),
            Location = new System.Drawing.Point(420, 360),
            Parent = frm,
        };

        // mat変換
        var srcMat = BitmapConverter.ToMat(src);
        int ch = srcMat.Channels();
        if (ch > 3)
            Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.BGRA2BGR);

        // バイラテラルフィルタ
        bool filterExecFlag = false;
        Func<Mat, int, double, double, Mat> filter = new((src, d, sigmaColor, sigmaSpace)=>
        {
            filterExecFlag = true;
            Mat dst = new();

            Cv2.BilateralFilter(src, dst, d, sigmaColor, sigmaSpace);
            filterExecFlag = false;
            return dst;
        });
        track1.ValueChanged += async (s, e) =>
        {
            Mat? dstMat = null;
            int d = track1.Value;
            double sigmaColor = track2.Value;
            double sigmaSpace = track3.Value;

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

            if (filterExecFlag) return;

            double backupValue;
            do {
                backupValue = d;
                dstMat?.Dispose();
                dstMat = await Task.Run(()=> filter(srcMat, d, sigmaColor, sigmaSpace));
                d = track1.Value;
            } while (backupValue != d);
            
            picbox.Image?.Dispose();
            picbox.Image = BitmapConverter.ToBitmap(dstMat);
            dstMat?.Dispose();
        };
        track2.ValueChanged += (s, e) =>
        {
            double sigmaColor = track2.Value;
            label2.Text = String.Format("sigmaColor:{0}", sigmaColor);
        };
        track3.ValueChanged += (s, e) =>
        {
            double sigmaSpace = track3.Value;
            label3.Text = String.Format("sigmaSpace:{0}", sigmaSpace);
        };

        frm.Load += (s, e) =>
        {
            track2.Value = 50;
            track3.Value = 20;
            track1.Value = 15;
        };

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

実行

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

dのトラックバーの変更でフィルターが実行されます。それ以外のトラックバーでは実行されません。

コメント