マウスで線を引く cvLine

OpenCVだけの機能で線を引くことができる。glutかVC++かが必要かと思ったが、OpenCVにはマウスイベントをコールバックできるのでcvLine関数を使えば線は書ける。
マウスをクリックした座標からマウスをドラッグ中は暫定的な線を描き、左マウスを離した座標で直線を固定する。
標準出力には(クリック開始座標)-(クリック上げ時の座標) 距離を表示する。
C:\usr\lesson\opencv\simple\マウスでcvLine>main
(21,22)-(49,22) distance:28.000000
(132,21)-(40,220) distance:219.237314
(293,4)-(2,294) distance:410.829648
(3,3)-(296,297) distance:415.072283
(151,147)-(299,147) distance:148.000000

cvLine(IplImage,開始座標,終点座標,CV_RGB(255,255,255)で白,線の太さ,8連結とかスムーズとか,座標の小数点以下の桁を表すビット数)
4や8連結
cvLine
ソースコードのon_mouse関数のフォーマットはcvSetMouseCallback関数の説明文を参照
マウスイベント用コールバック関数の書式
コールバック関数は以下のように書くように説明されている。
void Foo(int event, int x, int y, int flags, void* param);
コールバック関数名をFooとしているが何でも構わない。ここではon_mouseとしたがabcでも何でもいい。ただし、関数の戻り値の型、引数の数とそれぞれの型は一致していること。(当然、仮引数の変数名も何でも構わない)

以下がソースコード
#include <stdio.h>
#include <math.h>
#include <cv.h>
#include <highgui.h>
/*  コードが読みやすいようにマウスイベント関係の定数を一覧しておく
#define CV_EVENT_MOUSEMOVE      0   移動
#define CV_EVENT_LBUTTONDOWN    1   左クリック下げ時
#define CV_EVENT_RBUTTONDOWN    2
#define CV_EVENT_MBUTTONDOWN    3
#define CV_EVENT_LBUTTONUP      4   左クリック上げ時
#define CV_EVENT_RBUTTONUP      5
#define CV_EVENT_MBUTTONUP      6
#define CV_EVENT_LBUTTONDBLCLK  7 左ダブルクリック時
#define CV_EVENT_RBUTTONDBLCLK  8
#define CV_EVENT_MBUTTONDBLCLK  9  中ボタンダブルクリック時
 
#define CV_EVENT_FLAG_LBUTTON   1
#define CV_EVENT_FLAG_RBUTTON   2
#define CV_EVENT_FLAG_MBUTTON   4
#define CV_EVENT_FLAG_CTRLKEY   8   Ctrlキー
#define CV_EVENT_FLAG_SHIFTKEY  16  Shiftキー
#define CV_EVENT_FLAG_ALTKEY    32  ALTキー
*/
 
IplImage *dsp_img, *src_img = 0;
 
/* マウスイベント用コールバック関数 この関数のフォーマットはcvSetMouseCallbackで決まっている */
void
on_mouse (int event, int x, int y, int flags, void *param)//マウスイベント毎に何度も再入してくる
{
  CvPoint pt = cvPoint (x, y);
  static CvPoint start_pt = { -1, -1 };//static この変数はこの関数を抜けてからも有効にしておく
  if (event == CV_EVENT_LBUTTONDOWN)
    {
      start_pt = cvPoint (x, y);
    }
  else if (event == CV_EVENT_MOUSEMOVE && (flags & CV_EVENT_FLAG_LBUTTON))
    {
      dsp_img = cvCloneImage (src_img);	//前の描画がクリアー これをコメントアウトすると面白い描画になる。
      if (start_pt.x < 0)
	{
	  start_pt = pt;
	}
      //                                        color thick
      cvLine (dsp_img, start_pt, pt, CV_RGB(255,255,255), 1, 0, 0);
      //cvLine (dsp_img, start_pt, pt, CV_RGB(255,255,255), 1, CV_AA, 0);//滑らか
      cvShowImage ("image", dsp_img);	//その都度線を引いて表示する
    }
  else if (event == CV_EVENT_LBUTTONUP)
    {
      src_img = cvCloneImage (dsp_img);	//書き込んだものを固定
      printf("(%d,%d)-(%d,%d)",start_pt.x,start_pt.y,pt.x,pt.y);
      double x=start_pt.x-pt.x;
      double y=start_pt.y-pt.y;
      printf(" distance:%f\n",sqrt(x*x+y*y));
    }
}
 
int
main (int argc, char **argv)
{
  CvSize window_size = { 300, 300 };
 
  src_img = cvCreateImage (window_size, IPL_DEPTH_8U, 3);
  dsp_img = cvCloneImage (src_img);
 
  cvNamedWindow ("image", CV_WINDOW_AUTOSIZE);
  cvShowImage ("image", src_img);
  cvSetMouseCallback ("image", on_mouse, 0);//イベントを受けるウィンドウタイトル名を指定し、コールバック関数名も指定
  cvWaitKey (0);
  cvReleaseImage (&src_img);
  cvReleaseImage (&dsp_img);
}
 
座標と距離の他に、角度が欲しいな。
「今日の訪問数: -
「昨日の訪問数: -
「今までの訪問数: -
名前:
コメント:
最終更新:2010年01月29日 14:10
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。
添付ファイル