OpenCVの画像フィルターを並べて実行するWPFアプリを作る「ノンローカルミーンフィルタ」

コンピュータ

ノンローカルミーン(Non-Local Means)フィルタは、画像内のノイズを除去する手法の一つで
画像全体の広い範囲から似たようなパターン(テクスチャ)を探し、それらを平均化してノイズを消します。
エッジや細かい模様を「画像内の別の場所にある似た構造」から復元するため、鮮明さを維持しやすいのが特徴です。
高品質な結果が得られる反面、画像全体を探索するため計算量が非常に多く、処理に時間がかかるという側面があります。


NonLocalMeansFilter.cs

using OpenCvSharp;
using Reactive.Bindings;
using Reactive.Bindings.Extensions;
using System.Reactive.Linq;
using Cv = OpenCvSharp;

namespace OpenCvFilterMaker2;

public class NonLocalMeansFilter : CvFilterBase
{
    public ReactivePropertySlim<float> H{ get; set; }
        = new ReactivePropertySlim<float>(10.0f);

    public ReactivePropertySlim<int> TemplateWindowSize { get; set; }
        = new ReactivePropertySlim<int>(7);
    public ReactivePropertySlim<int> SearchWindowSize { get; set; }
        = new ReactivePropertySlim<int>(21);
    public NonLocalMeansFilter()
    {
        MenuHeader = "ノンローカルミーン";
        IsEnabled.Value = true;

        H.Subscribe(_ => UpdateName())
        .AddTo(Disposable);

        TemplateWindowSize
            .Subscribe(value =>
            {
                TemplateWindowSize.Value = value < 3 ? 3 : value;
                UpdateName();
            })
            .AddTo(Disposable);

        SearchWindowSize
            .Subscribe(value =>
            {
                SearchWindowSize.Value = value < 7 ? 7 : value;
                UpdateName();
            })
            .AddTo(Disposable);

        UpdateName();
    }

    private void UpdateName()
    {
        Name.Value = $"NonLocalMeansFilter(H={H.Value} Teamp={TemplateWindowSize.Value}) Search={SearchWindowSize.Value}";

    }
    protected override Cv.Mat Apply(Cv.Mat input)
    {
        if (input.Depth() != Cv.MatType.CV_8U)
            throw new InvalidOperationException("NLMeans requires CV_8U image.");

        Cv.Mat dst = new Cv.Mat();

        if (input.Channels() == 1)
        {
            Cv2.FastNlMeansDenoising(
                input,
                dst,
                H.Value,
                TemplateWindowSize.Value,
                SearchWindowSize.Value);
        }
        else
        {
            Cv2.FastNlMeansDenoisingColored(
                input,
                dst,
                H.Value,
                H.Value,
                TemplateWindowSize.Value,
                SearchWindowSize.Value);
        }

        return dst;

    }
}

NonLocalMeansFilter.xaml

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:OpenCvFilterMaker2">

    <!-- NonLocalMeansFilter用テンプレート -->
    <DataTemplate DataType="{x:Type local:NonLocalMeansFilter}">
        <StackPanel Margin="10">
            <TextBlock Text="NonLocalMeansFilter Settings"
                       FontWeight="Bold"
                       Margin="0,0,0,10"/>

            <StackPanel Orientation="Horizontal">
                <TextBlock Text="H:"
                            VerticalAlignment="Center"
                            Margin="0,0,5,0"/>
                <TextBox Width="60"
                            Text="{Binding H.Value}"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="TemplateWindowSize:"
                            VerticalAlignment="Center"
                            Margin="0,0,5,0"/>
                <TextBox Width="60"
                            Text="{Binding TemplateWindowSize.Value}"/>
            </StackPanel>
            
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="SearchWindowSize:"
                            VerticalAlignment="Center"
                            Margin="0,0,5,0"/>
                <TextBox Width="60"
                            Text="{Binding SearchWindowSize.Value}"/>
            </StackPanel>
        </StackPanel>
    </DataTemplate>

</ResourceDictionary>

MainWindow.xaml

<ResourceDictionary Source="/Resources/NonLocalMeansFilter.xaml"/>

追加


コメント