OpenCvSharp でお絵かきをします。

OpenCvSharp.CPlusPlus.Window クラスの OnMouseCallback にイベントハンドラを登録する形でマウスクリックを取得します。Polylines メソッドを利用することで、連続したなめらかな線を描くことができます。

目次

ソースコード


using OpenCvSharp;
using OpenCvSharp.CPlusPlus;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenCvSharpSample.Samples
{
public class MethodTest
{
public static void MouseClickPolylinesCanvasWindow()
{
using (var window = new Window("canvas"))
{
var pointList = new List<List<Point>>();
bool moving = false;
var color = new Scalar(100, 100, 0);
var mat = new Mat(new Size(640, 480), MatType.CV_8UC3);
mat.SetTo(new Scalar(255, 255, 255));
window.ShowImage(mat);
window.OnMouseCallback += (e, x, y, flags) =>
{
if (e == MouseEvent.LButtonDown)
{
if (moving)
{
pointList.Last().Add(new Point(x, y));
}
else
{
pointList.Add(new List<Point>() { new Point(x, y) });
}
moving = true;
mat.Circle(x, y, 1, color, 3, LineType.AntiAlias);
window.ShowImage(mat);
}
else if (e == MouseEvent.MouseMove && flags == MouseEvent.FlagLButton)
{
if (moving)
{
pointList.Last().Add(new Point(x, y));
// 点を削除
pointList.RemoveAll(list => list.Count <= 1);
mat.Polylines(pointList, false, color, 3, LineType.AntiAlias);
}
else
{
pointList.Add(new List<Point>() { new Point(x, y) });
}
moving = true;
window.ShowImage(mat);
}
else if (e == MouseEvent.LButtonUp)
{
moving = false;
}
};
bool notEscDown = true;
while (notEscDown)
{
switch (Cv2.WaitKey(1))
{
case 3014656: //Delete #Clear
pointList.Clear();
pointList.Add(new List<Point>());
mat.SetTo(new Scalar(255, 255, 255));
window.ShowImage(mat);
break;
case 27: //Esc #Exit
notEscDown = false;
break;
case 32: //SpaceBar #Save
mat.SaveImage(DateTime.Now.ToString("yyyyMMdd-HHmmss") + ".jpg");
break;
default:
break;
}
}
}
}
}
}

キーバインド

  • Delete キー: クリア
  • SpaceBar(スペース)キー: 保存
  • Esc キー: 終了

少しだけ解説

取得した座標を格納するリスト

var pointList = new List<List<Point>>();

  
ドラッグ中かを示す。これが true の間、pointList コレクション内の同じ List に座標を登録し続け、それらを連続する点として扱う。false になった時点で次の List に移る。

bool moving = false;

  
コールバックを登録

window.OnMouseCallback += (e, x, y, flags) =>
{
    if (e == MouseEvent.LButtonDown)
    {
      // クリック時の処理
    }
    else if(e == MouseEvent.MouseMove && flags == MouseEvent.FlagLButton)
    {
      // ドラッグ時の処理
    }
    else if (e == MouseEvent.LButtonUp)
    {
      // クリック(ドラッグ)終了時の処理
    }
};

こんな感じで描ける

妖精さんっぽいなにか
人類は衰退しましたの妖精さんっぽいなにか