WPFでOpenCVSharpのインペイントツールを作る「フィルター部分」

コンピュータ

ソースコード

using OpenCvSharp;

namespace Maywork.WPF.Helpers;
public static class OpenCvInpaintProcessor
{
    public static Mat ConvertAlphaToMask(Mat src)
    {
        
        if (src.Empty())
            throw new ArgumentException("Mat is empty.");

        if (src.Type() != MatType.CV_8UC4)
            throw new ArgumentException(
                $"Expected CV_8UC4 (BGRA). Actual={src.Type()}");
        
        // アルファチャンネル抽出
        using var alpha = new Mat();
        Cv2.ExtractChannel(src, alpha, 3); // index 3 = A

        // 反転
        var mask = new Mat();
        Cv2.BitwiseNot(alpha, mask);

        return mask;
    }

    public static Mat Apply(
        Mat src,
        Mat mask,
        double radius = 3.0,
        InpaintTypes method = InpaintTypes.Telea)
    {
        if (src.Empty())
            throw new ArgumentException("src is empty");

        if (mask.Empty())
            throw new ArgumentException("mask is empty");

        if (mask.Channels() != 1)
            throw new ArgumentException("mask must be single channel");

        if (src.Size() != mask.Size())
            throw new ArgumentException("src and mask size must match");

        Mat work = src;

        // α対応
        if (src.Channels() == 4)
        {
            work = new Mat();
            Cv2.CvtColor(src, work, ColorConversionCodes.BGRA2BGR);
        }

        var dst = new Mat();

        Cv2.Inpaint(work, mask, dst, radius, method);

        return dst;
    }
}

using System.Windows;
using System.Windows.Media.Imaging;

using OpenCvSharp.WpfExtensions;

using Maywork.WPF.Helpers;
using OpenCvSharp;

namespace InpaintGuiTool;

public partial class MainWindow : System.Windows.Window
{
public MainWindow()
{
    InitializeComponent();
}
private void CopyButton_Click(object sender, RoutedEventArgs e)
{
    if (Image1.Source is null) return;

    var bmp = (BitmapSource)Image1.Source;
    ClipboardImageHelper.SetImage(bmp);

    StatusBar1.Text = "画像をクリップボードへコピーしました。";

}
private void PasteButton_Click(object sender, RoutedEventArgs e)
{
    var bmp = ClipboardImageHelper.GetImage();
    if (bmp is null) return;

    Image1.Source = bmp;

    StatusBar1.Text = $"画像を貼り付けました。{bmp.Format}";
}
private void ApplyButton_Click(object sender, RoutedEventArgs e)
{
    if (Image1.Source is null) return;

    // フィルター処理の呼び出しを、ここに書く
    var bmp = (BitmapSource)Image1.Source;
    using Mat src = BitmapSourceConverter.ToMat(bmp);

    using Mat mask = OpenCvInpaintProcessor.ConvertAlphaToMask(src);

    using Mat dst = OpenCvInpaintProcessor.Apply(src, mask);

    Image1.Source = BitmapSourceConverter.ToBitmapSource(dst);

    StatusBar1.Text = $"画像フィルター処理を実行しました。";
}

}

OpenCVSharpを使うのでパッケージの登録

dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.runtime.win
dotnet add package OpenCvSharp4.WpfExtensions

実行例

画像を貼り付ける。

左側の白色の矩形部分(透明)がインペイント対象

Applyボタンを押す→フィルター実行

Ctrl+マウスホイールで拡大

インペイントされていることが確認出来る。

コメント