1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

OpenCVSharpでマウスを使う

Posted at

#概要
ちょっとした操作をマウスで行いたかった。さらに線や円などのプリミティブな図形も描きたかったので、OpenCVSharpを使ってみることにした。そこで引っ掛かったことを記す。
###不具合例

Program.cs
using OpenCvSharp;
  class Program
  {
    public static Mat img;
    static Point mousepos = new Point();
    static Scalar color = new Scalar(0, 255, 255);
    static void Main(string[] args)
    {
      img = new Mat(new Size(640, 480), MatType.CV_8UC3);
      using (Window win = new Window("OpenCV", img))
      {
        Cv2.SetMouseCallback("OpenCV", Win_OnMouseCallback);
        while(true)
        {
          Cv2.ImShow("OpenCV", img);
          int ret = Cv2.WaitKey(1);
          if (ret == 27) { break; }
        }
        Cv2.DestroyAllWindows();
      }
    }//End of Main

    private static void Win_OnMouseCallback(MouseEventTypes @event, int x, int y, MouseEventFlags flags, IntPtr userdata)
    {
      Console.WriteLine($"event: {@event}, (x, y)= ({x}, {y}), flags: {flags}");
      if (flags==MouseEventFlags.LButton)
      {
        mousepos.X = x; mousepos.Y = y;
        img.Circle(mousepos, 2, color);
      }
    }
  }

何の変哲もない。
しかしリリースモードでビルドして実行して、暫くすると
20200531_err1.png
これは何のことだろう?デバッグモードでは出てこないけど・・・
ググると、C#のリリースモードはいろいろ最適化されてるから別コードと考えた方がよいとか、Releaseでもデバッグ用にログを取るとかいろいろ出てきた。でもこんな簡単なものなのに・・
しかもアンマネージってOpenCVのところ??
###解決策
ようやく探し出せた
https://www.ipentec.com/document/csharp-error-delegate-must-be-kept-alive-by-the-managed-application
よく見るとWin_MouseCallBackはdelegate型になってない。staticで宣言されているけど、ガベージコレクタが回収してしまうようだ。ちゃんと確保して回収されないようにしてあげよう。差分だけ書かせてもらうと正しくは

Program.cs
    public static Mat img;
    static Point mousepos = new Point();
    static Scalar color = new Scalar(0, 255, 255);
    static MouseCallback mcb;  //追加
    static void Main(string[] args)
    {
      img = new Mat(new Size(640, 480), MatType.CV_8UC3);
      mcb=new MouseCallback(Win_OnMouseCallback); //追加
      using (Window win = new Window("OpenCV", img))
      {
        Cv2.SetMouseCallback("OpenCV", mcb);//変更 
        while(true)
        //以下略

この「ガベージコレクタが回収する」エラーは、IDEでデバッグしているときは出てこず、使い始めてしばらくすると出てくるのと、再現するのに時間がかかるので、だいぶ厄介だった。わかってみれば「型を合わせてメモリを確保する」をちゃんとするだけなのだが。C++のDLLを使うプログラムでは気を付けよう。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?