以前に同様のサンプルプログラムを書きましたが今回は対象の図形サイズをパラメータとして調整出来るようにしてみました。
WPF学習中「OpenCvSharpで指定サイズより小さい図形を消す」
プロジェクトの作成mkdir プロジェクト名cd プロジェクト名dotnet new wpfdotnet add package OpenCvSharp4.Windowscode .ソースコードファイル名:MainWindow.xaml<W...
実行環境構築
プロジェクトの作成
mkdir プロジェクト名
cd プロジェクト名
dotnet new winforms
dotnet add package OpenCvSharp4.Windows -v 4.6.0.20220608
dotnet add package OpenCvSharp4.Extensions -v 4.6.0.20220608
code .
ソースプログラム
using OpenCvSharp;
using OpenCvSharp.Extensions;
namespace EraseShape;
public partial class Form1 : Form
{
Mat? _view = null;
public Form1()
{
InitializeComponent();
Text = "指定サイズより小さい図形を塗潰す";
Size = new System.Drawing.Size(800, 600);
// ベース画像
var fnt = new Font("MS UI Gothic", 24);
var bmp = new Bitmap(800, 600);
using (var g = Graphics.FromImage(bmp))
{
g.FillRectangle(Brushes.White, 0, 0, bmp.Width, bmp.Height);
g.DrawString("こちらにD&D", fnt, Brushes.Green, 0.0f, 0.0f);
}
// スプリットコンテナ(上下)
var ud = new SplitContainer
{
Dock = DockStyle.Fill,
Orientation = Orientation.Horizontal, // 上下
Panel1MinSize = 120,
};
// ピクチャボックス
var picbox = new PictureBox
{
SizeMode = PictureBoxSizeMode.Zoom,
Dock = DockStyle.Fill,
AllowDrop = true,
Image = bmp,
};
// 実行ボタン
var execBtn = new RadioButton
{
Text = "フィルターOFF",
Appearance = Appearance.Button,
AutoCheck = false,
Size = new System.Drawing.Size(180, 50),
};
// ドットサイズ
var dotSizeLabel = new Label
{
Text = "ドットサイズ:50"
};
var dotSizeTrac = new TrackBar
{
Minimum = 1,
Maximum = 500,
Value = 50,
LargeChange = 50,
};
// パネル
var flowPanel = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
};
// ドラッグエンターイベント
picbox.DragEnter += (sender, e) =>
{
if (e.Data == null) return;
if(!e.Data.GetDataPresent(DataFormats.FileDrop)) return;
e.Effect = DragDropEffects.Copy;
};
// ドラッグアンドドロップイベント
picbox.DragDrop += (sender, e) =>
{
if (e.Data == null) return;
var fd = e.Data.GetData(DataFormats.FileDrop);
if (fd == null) return;
string? path = ((string[])fd)[0];
_view?.Dispose();
_view = Cv2.ImRead(path);
picbox.Image?.Dispose();
picbox.Image = BitmapConverter.ToBitmap(_view);
execBtn.Checked = false;
};
// ボタンクリックイベント
execBtn.Click += (sender, e) =>
{
if (_view is null) return;
picbox.Image?.Dispose();
if (execBtn.Checked == true)
{
picbox.Image = BitmapConverter.ToBitmap(_view);
execBtn.Text = "フィルターOff";
execBtn.Checked = false;
} else {
using (var img = (Mat)_view.Clone())
using (var dst = (Mat)_view.Clone())
{
int dotSize = dotSizeTrac.Value;
if (_view.Channels() > 1)
{
// RGB=>グレースケール
Cv2.CvtColor(_view, img, ColorConversionCodes.RGB2GRAY);
}
// 2値化
Cv2.Threshold(img, img, 127, 255, ThresholdTypes.Binary);
// 図形の検出
OpenCvSharp.Point[][] contours;
OpenCvSharp.HierarchyIndex[] hierarchy;
Cv2.FindContours(img, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxNone);
//Cv2.FindContours(img, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);
List<List<OpenCvSharp.Point>> targets = new();
foreach(var c in contours)
{
if (Math.Abs(Cv2.ContourArea(c)) <= dotSize)
{
var lc = new List<OpenCvSharp.Point>(c);
targets.Add(lc);
}
}
// 検出図形を塗りつぶし
Cv2.DrawContours(dst, targets, -1, new Scalar(255,0,255), -1);
picbox.Image?.Dispose();
picbox.Image = BitmapConverter.ToBitmap(dst);
}
execBtn.Text = "フィルターOn";
execBtn.Checked = true;
}
};
// ドットサイズ変更イベント
dotSizeTrac.ValueChanged += (s, e) =>
{
dotSizeLabel.Text = string.Format("ドットサイズ:{0}", dotSizeTrac.Value);
};
// コントロールの追加
ud.Panel1.Controls.Add(picbox);
flowPanel.Controls.AddRange(new Control[]
{
execBtn,
dotSizeLabel,
dotSizeTrac,
});
ud.Panel2.Controls.Add(flowPanel);
Controls.Add(ud);
}
}
実行
dotnet run
フィルターOFF
ドットサイズ:5
ドットサイズ:250
ドットサイズ:500
GIMPのスクリーンショットを対象にしてみたところ、アイコンやメニューの文字が検出されています。ドットサイズを大きくすると塗りつぶされる対象が拡大されています。
図形検出の為、画像を2値化処理で白黒にしているのですが、こちらの閾値や処理方法によっても結果が異なると思われます。
コメント