WPF + OpenCVSharpで画像の表示と切り出しを行う

タイトルの通り、OpenCVSharpを使用して画像の読み取りと、画像の部分的な切り出しを行います。

パッケージと導入方法

今回使用するのはWPFで利用性の高い以下のパッケージを使用します。

github.com

VisualStudio上でパッケージマネージャを開いて以下を入力します。バージョンは自機で変わると思うので

PM > Install-Package OpenCvSharp3-AnyCPU -Version 3.3.1.20171117

実行例

ちょうどdアニメストアで見ていた怪獣娘のキャプチャを切り抜いてみました。

f:id:Takachan:20180306225748p:plain

ps: 上の画像は半分の大きさに縮小表示しています。下の画像は原寸大なのでスケールが違います。

コード

XAMLはこんな感じ。普通にスタックパネルにImageコントロールを縦に2つ並べているだけです。

<Window x:Class="OpenCV.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:OpenCV"
        mc:Ignorable="d"
        Title="MainWindow" Height="480" Width="711">
    <StackPanel Margin="14">
        <Image x:Name="BigImage" Width="544" Height="306" Source="{Binding BigImgae}"/>
        <Image x:Name="ClipedImage" Margin="0 16 0 0" Width="100" Height="100" Source="{Binding SmallImgae}"/>
    </StackPanel>
</Window>

C#のコードは以下の通り。

using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace OpenCV
{
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        public MainWindow()
        {
            this.InitializeComponent();
            this.LoadImage();
        }

        public void LoadImage()
        {
            // ファイルから画像を読み取ってWPFへ張り付け
            var bigImageMat = new Mat(@"D:\img.png");
            this.BigImage.Source = bigImageMat.ToWriteableBitmap();

            // 部分的に切り取ってWPFへ張り付け
            Mat clipedMat = bigImageMat.Clone(new OpenCvSharp.Rect(180, 220, 100, 100));
            this.ClipedImage.Source = clipedMat.ToWriteableBitmap();
        }
    }
}

補足

画像を切り出すときに使うメソッドはMat.Clone(Rect)です。例えば以下のようにインデクサをしていすると画像が真っ暗になって処理失敗になります。

// よい例
Mat clipedMat = bigImageMat.Clone(new OpenCvSharp.Rect(180, 220, 100, 100));

// ダメな例(切り出した画像が真っ暗になる)
Mat clipedMat = bigImageMat[new OpenCvSharp.Rect(180, 220, 100, 100)];

↓ こんな感じになります。

f:id:Takachan:20180306230242p:plain

簡単ですが、今回は以上です。