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;
}
}
}
コメント