OpenCVSharpソーベルフィルタでエッジ検出

コンピュータ

ソーベルフィルタによるエッジ検出を試してみました。

namespace SobelTest;

using System.Diagnostics;
using OpenCvSharp;
using OpenCvSharp.Extensions;
public partial class Form1 : Form
{
    Mat? _org = null;
    public Form1()
    {
        InitializeComponent();
        var ud = new SplitContainer {
            Dock = DockStyle.Fill,
            Orientation = Orientation.Horizontal,   // 上下
            Panel1MinSize = 120,
        };
        var picboxV = new PictureBox {
            SizeMode = PictureBoxSizeMode.Zoom,
            Dock = DockStyle.Fill,
            AllowDrop = true,
        };
        var execBtn = new RadioButton {
            Text = "OFF",
            Appearance = Appearance.Button,
            AutoCheck = false,
            Size = new System.Drawing.Size(180, 50),
        };
        var flowPanel = new FlowLayoutPanel {
            Dock = DockStyle.Fill,
            AllowDrop = true,
        };        
        Load += (sender, e) => {
            ud.Panel1.Controls.Add(picboxV);
            flowPanel.Controls.AddRange(new Control[]{
                execBtn,});
            ud.Panel2.Controls.Add(flowPanel);
            Controls.Add(ud);
        };
        picboxV.DragEnter += (sender, e) => {
            e.Effect = DragDropEffects.Copy;
        };
        picboxV.DragDrop += async (sender, e) => {
            if (e.Data == null) return;
            var fd = e.Data.GetData(DataFormats.FileDrop);
            if (fd == null) return;
            string? path = ((string[])fd)[0];
            if (path == null) return;
            Text = path;

            _org?.Dispose();
            _org = await Task.Run<Mat>(()=>{
                return Cv2.ImRead(path, ImreadModes.Grayscale);
            });
            picboxV.Image?.Dispose();
            picboxV.Image = await Task.Run<Bitmap>(()=>{
                return BitmapConverter.ToBitmap(_org);
            });
            execBtn.Checked = false;
        };        
        execBtn.Click += async (sender, e) => {
            if (_org == null) return;

            if (execBtn.Checked == true) {
                execBtn.Text = "Off";
                picboxV.Image?.Dispose();
                picboxV.Image = await Task.Run<Bitmap>(()=>{
                    return BitmapConverter.ToBitmap(_org);
                });
                execBtn.Checked = false;

            } else {
                execBtn.Text = "ON";
                picboxV.Image?.Dispose();
                picboxV.Image = await Task.Run<Bitmap>(()=>{
                    
                    using Mat sobel_x = new Mat();
                    using Mat sobel_y = new Mat();
                    using Mat sobel_xx = new Mat();
                    using Mat sobel_yy = new Mat();
                    using Mat sobel_xy = new Mat();
                    using Mat sobel_xy8 = new Mat();

                    Cv2.Sobel(_org, sobel_x, MatType.CV_32F, 1, 0);
                    Cv2.Sobel(_org, sobel_y, MatType.CV_32F, 0, 1);
                    Cv2.ConvertScaleAbs(sobel_x, sobel_xx, 0.5);
                    Cv2.ConvertScaleAbs(sobel_y, sobel_yy, 0.5);
                    Cv2.Add(sobel_xx, sobel_yy, sobel_xy);
                    sobel_xy.ConvertTo(sobel_xy8, MatType.CV_8U);

                    return BitmapConverter.ToBitmap(sobel_xy8);
                });
                
                // コピー                
                if (picboxV.Image is null) return;
                var ms = new MemoryStream();
                picboxV.Image.Save(ms, System.Drawing.Imaging.ImageFormat.Png);
                Clipboard.SetData("PNG", ms);

                execBtn.Checked = true;
            }
        };
    }
}

元絵

ドラッグアンドドロップするとグレースケールで表示される。

ボタン(OFF)を押す。エッジ検出されます。

フィルターが適用された画像はクリップボードにコピーされます。

以上

コメント