2013年4月3日水曜日

opencv2.4.4をcygwinでつかってみる(3コマ目) マウス+KBDイベント

今日は、OpenCVでマウスとKBDのイベントを採取するお勉強をしました.参考にしたのはこちらのページです.   http://opencv.jp/sample/simple_gui.html

サンプルプログラムの機能はこうなってます.
●起動すると400x400のwindowが開き、ランダムな図形が描画されます
●KBDを押すと再描画されます   (ただしESCを押すとexitします)
●windows内でマウスを操作すると文字でeventが表示されます
プログラムを以下に示しますが、特徴的なのは、マウス操作で呼ばれる関数をwindowにヒモづけするところです.
  cvSetMouseCallback ("Drawing", on_mouse, 0);
という関数で、windows名Drawingに対して、on_mouse()という関数をヒモづけしています.
関数名はon_mouseじゃなくても良いのですが、同関数の引数は必ずつぎのようにしなければならないと決まっています.
  on_mouse (int event, int x, int y, int flags, void *param);
eventとflagはどんなイベントが発生したか?  x,yはマウスカーソル位置    paramはユーザーに開放された変数

もひとつ特徴的なのは、KBDが押されるまで待つ関数です.cvWaitKey(0)という関数です.KBDが押されると、asciiコードを返しつつreturnします.

opencvのバグだと思うんですが、常にCV_EVENT_FLAG_ALTKEYがアサートされっぱなしであるようで、「+ALT」が常に表示されてしまいます.

プログラム    cv_mouse.c
#include <cv.h>
#include <highgui.h>
#include <time.h>
#include <stdio.h>

void on_mouse (int event, int x, int y, int flags, void *param);
IplImage *img = 0;
CvPoint pt1, pt2;
CvFont font;

int main (int argc, char **argv)
{
  int i;
  char c;
  CvRNG rng = cvRNG (time (NULL));
  CvScalar rcolor;
  int irandom;

  img = cvCreateImage (cvSize (400, 400), IPL_DEPTH_8U, 3);
  cvZero (img);
  cvNamedWindow ("Drawing", CV_WINDOW_AUTOSIZE);
  cvSetMouseCallback ("Drawing", on_mouse, 0);
  cvInitFont (&font, CV_FONT_HERSHEY_DUPLEX, 0.4, 0.4, 0, 1, 8);

  while(1){
    // clear window area
    pt1.x = 0;
    pt1.y = 0;
    pt2.x = 399;
    pt2.y = 399;
    rcolor = CV_RGB (0, 0, 0);
    cvRectangle (img, pt1, pt2, rcolor, CV_FILLED, CV_AA, 0);
 
    // draw lines
    for (i = 0; i < 5; i++) {
      pt1.x = cvRandInt (&rng) % (img->width);
      pt1.y = cvRandInt (&rng) % (img->height);
      pt2.x = cvRandInt (&rng) % (img->width);
      pt2.y = cvRandInt (&rng) % (img->height);
      irandom = cvRandInt (&rng);
      rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255);
      cvLine (img, pt1, pt2, rcolor, cvRandInt (&rng) % 4, CV_AA, 0);
    }
 
    // draw rectangles
    for (i = 0; i < 5; i++) {
      pt1.x = cvRandInt (&rng) % (img->width);
      pt1.y = cvRandInt (&rng) % (img->height);
      pt2.x = cvRandInt (&rng) % (img->width);
      pt2.y = cvRandInt (&rng) % (img->height);
      irandom = cvRandInt (&rng);
      rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255);
      cvRectangle (img, pt1, pt2, rcolor, cvRandInt (&rng) % 5 - 1, CV_AA, 0);
    }
 
    // draw circles
    for (i = 0; i < 5; i++) {
      pt1.x = cvRandInt (&rng) % (img->width);
      pt1.y = cvRandInt (&rng) % (img->height);
      irandom = cvRandInt (&rng);
      rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255);
      cvCircle (img, pt1, cvRandInt (&rng) % (img->width / 4) + img->width / 4, rcolor,
cvRandInt (&rng) % 5 - 1, CV_AA, 0);
    }
 
    // draw ellipses
    for (i = 0; i < 5; i++) {
      pt1.x = cvRandInt (&rng) % (img->width);
      pt1.y = cvRandInt (&rng) % (img->height);
      irandom = cvRandInt (&rng);
      rcolor = CV_RGB (irandom & 255, (irandom >> 8) & 255, (irandom >> 16) & 255);
      cvEllipse (img, pt1, cvSize (img->width / 2, img->height / 2), irandom % 180, irandom % 90, irandom % 90 + 90,
rcolor, cvRandInt (&rng) % 5 - 1, 8, 0);
    }
 
    // display a window
    cvShowImage ("Drawing", img);
 
    // check KBD
    c = cvWaitKey (0);
    if(c==27) break;  // ESC exit
  }
  // exit
  cvDestroyWindow ("Drawing");
  cvReleaseImage (&img);

  return 0;
}

// マウスイベント処理関数
void on_mouse (int event, int x, int y, int flags, void *param)
{
  char str[64];
  // check events
  switch (event) {
  case CV_EVENT_MOUSEMOVE:
    snprintf (str, 64, "(%d,%d) %s", x, y, "MOUSE_MOVE");    break;
  case CV_EVENT_LBUTTONDOWN:
    snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_DOWN");    break;
  case CV_EVENT_RBUTTONDOWN:
    snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_DOWN");    break;
  case CV_EVENT_MBUTTONDOWN:
    snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_DOWN");    break;
  case CV_EVENT_LBUTTONUP:
    snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_UP");    break;
  case CV_EVENT_RBUTTONUP:
    snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_UP");    break;
  case CV_EVENT_MBUTTONUP:
    snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_UP");    break;
  case CV_EVENT_LBUTTONDBLCLK:
    snprintf (str, 64, "(%d,%d) %s", x, y, "LBUTTON_DOUBLE_CLICK");    break;
  case CV_EVENT_RBUTTONDBLCLK:
    snprintf (str, 64, "(%d,%d) %s", x, y, "RBUTTON_DOUBLE_CLICK");    break;
  case CV_EVENT_MBUTTONDBLCLK:
    snprintf (str, 64, "(%d,%d) %s", x, y, "MBUTTON_DOUBLE_CLICK");    break;
  }

  // check mouse buttons
  if (flags & CV_EVENT_FLAG_LBUTTON)   strncat (str, " + LBUTTON", 64);
  if (flags & CV_EVENT_FLAG_RBUTTON)   strncat (str, " + RBUTTON", 64);
  if (flags & CV_EVENT_FLAG_MBUTTON)   strncat (str, " + MBUTTON", 64);
  if (flags & CV_EVENT_FLAG_CTRLKEY)   strncat (str, " + CTRL"   , 64);
  if (flags & CV_EVENT_FLAG_SHIFTKEY)  strncat (str, " + SHIFT"  , 64);
  if (flags & CV_EVENT_FLAG_ALTKEY)    strncat (str, " + ALT"    , 64);

  // display mouse parameters
  pt1.x = 0;  pt1.y = 0;
  pt2.x = 399;  pt2.y = 20;
  cvRectangle (img, pt1, pt2, CV_RGB(0,0,0), CV_FILLED, CV_AA, 0); // 文字を消す
  cvPutText (img, str, cvPoint (0, 10), &font, CV_RGB (0, 200, 100)); // 文字表示
  cvShowImage ("Drawing", img); // window描画
}

Makefile
INC  = -I/usr/local/include/opencv
LIB  = -L/usr/local/lib
OPT  =  -llibopencv_calib3d \
        -llibopencv_contrib \
        -llibopencv_core \
        -llibopencv_features2d \
        -llibopencv_flann \
        -llibopencv_gpu \
        -llibopencv_highgui \
        -llibopencv_imgproc \
        -llibopencv_legacy \
        -llibopencv_ml \
        -llibopencv_nonfree \
        -llibopencv_objdetect \
        -llibopencv_photo \
        -llibopencv_stitching \
        -llibopencv_ts \
        -llibopencv_video \
        -llibopencv_videostab \
        -lstdc++
ccmouse:
        gcc cv_mouse.c $(INC) $(LIB) $(OPT) -o cv_mouse.exe


人気ブログランキングへ

2 件のコメント:

  1. こんばんは STM33 お本家サイトがこのごろ素っ気なくなり、上手くデータが落とせません。

    最近はLPCも始めてたんですがLPC1789を切り離して、LPC-LINKに、応用しようとしたんですが、スキルが無く、上手く繋がってくれず、目的デバイスすら出てきません。フラッシュマジックでは繋げるんですがデバッグが出来無いので応用が利きません。

    返信削除
  2. しばらく悩んでいた LPC-LINK が LPC1114/302 でやっと動きました。
    英語力がないのと、ドライバーの設定などが間違っていたようです。

    LPC1114FN28/102はMPU側の接続がまだ解けていません。
    LPCXpresso_5.1.2_2065 は eclipse\eclipse を 使っているらしいですが、
    LINK のプログラムは各種違うようです。

    http://den-nekonoko2.blog.so-net.ne.jp/

    返信削除