備忘録

備忘録

C#でテンプレートマッチを行う

Ⅰ. はじめに

OpenCV3 のラッパーである OpenCvSharp の MatchTemplate メソッドを使ってテンプレートマッチを行います。

Ⅱ. サンプル

スクリーンショットを取り、メモ帳のアイコンを探すサンプルです。

NuGet から OpenCV3 のラッパーをインストールする。

f:id:kagasu:20170609192018p:plain

template.png

f:id:kagasu:20170609191705p:plain

Program.cs
class Program
{
  /// <summary>
  /// スクリーン全体のスクリーンショットを撮る
  /// </summary>
  static Bitmap TakeFullScreenScreenShot(int width, int height)
  {
    var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);
    //var bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
    using (var g = Graphics.FromImage(bmp))
    {
      g.CopyFromScreen(0, 0, 0, 0, bmp.Size);
    }

    return bmp;
  }

  /// <summary>
  /// テンプレートマッチを行う
  /// </summary>
  static (OpenCvSharp.Point minPoint, OpenCvSharp.Point maxPoint) MatchTemplate()
  {
    var screen = BitmapConverter.ToMat(TakeFullScreenScreenShot(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height));
    var template = BitmapConverter.ToMat(new Bitmap("template.png"));

    var result = new Mat();
    Cv2.MatchTemplate(screen, template, result, TemplateMatchModes.CCoeffNormed);
    Cv2.Threshold(result, result, 0.8, 1.0, ThresholdTypes.Binary);
    Cv2.MinMaxLoc(result, out OpenCvSharp.Point minPoint, out OpenCvSharp.Point maxPoint);

    //screen.Rectangle(maxPoint, new OpenCvSharp.Point(maxPoint.X + template.Width, maxPoint.Y + template.Height), Scalar.Red);
    //screen.SaveImage("out.bmp");
    
    return (minPoint, maxPoint);
  }

  static void Main(string[] args)
  {
    MatchTemplate();
  }
}

Ⅲ. 実行結果

メモ帳ウィンドウの左上のアイコンのテンプレートマッチに成功し、四角い枠が付いています。
f:id:kagasu:20170609191434p:plain

Ⅳ. エラー対策

ハンドルされていない例外:
OpenCvSharp.OpenCVException:
(depth == CV_8U || depth == CV_32F) && type == _templ.type() && _img.dims() <= 2

Windowsに標準でインストールされているペイントで画像をpng形式で保存した場合、
アルファ値の有無が変わる場合があります。(なぜ変わるか、詳細はよく分かってないです)
PixelFormat を適切に設定すると解決します。