在OpenCV中使用MouseCallback绘图

时间:2013-09-11 15:27:53

标签: c++ opencv callback

使用OpenCV 2.4.3,当用户移动鼠标时,我试图在以鼠标(x,y)位置为中心的图像上绘制一个圆圈,一旦鼠标停止,该圆圈应该在那里移动(只有那个时刻只显示一个圆圈的原始图像)。我认为这很容易,但是,我一直在研究和尝试几个小时,并且不能像我描述的那样使它工作。

我在下面附上我的代码。如果有人能帮忙我真的很感激。

void my_mouse_callback( int event, int x, int y, int flags, void* param );
bool moving_mouse = false;

int main()
{
const char* name = "Circle Example";

IplImage* image_circle = cvLoadImage( "../data/lena.png" );
IplImage* image = cvLoadImage( "../data/lena.png" );

namedWindow(name, CV_WINDOW_AUTOSIZE );

// Set up the callback
cvSetMouseCallback( name, my_mouse_callback, (void*) image_circle);

//Main Loop
while(cvWaitKey(15) != 27){ 

    //If mouse is moving draw circle on top of image
    if(moving_mouse){
        cvShowImage(name, image_circle);
        moving_mouse = false;
    }
    //If mouse stops moving draw original image and reset image_cicle
    else{
        cvShowImage(name, image);
        image_circle = cvCloneImage(image);
    }
}

cvReleaseImage(&image_circle);
cvReleaseImage(&image);
cvDestroyWindow(name);
return 0;
}


// Mouse callback
void my_mouse_callback( int event, int x, int y, int flags, void* param ){

switch( event ){
    case CV_EVENT_MOUSEMOVE: 
        //Drawing a Circle
        cvCircle(param,cvPoint(x,y),25,CV_RGB(0,255,0),1);
        moving_mouse = true;
        break;

          }
    }

1 个答案:

答案 0 :(得分:2)

我向您展示了一种方法。我稍后会解释并告诉你一个难点:

static int mouse_x = -1;
static int mouse_y = -1;

void my_mouse_callback( int event, int x, int y, int flags, void* param )
{
  if(event == CV_EVENT_MOUSEMOVE)
  {
    mouse_x = x;
    mouse_y = y;
  }
}

int main()
{
  IplImage* image;
  IplImage* image_circle = NULL;

  ... // load image, create window, initiate callback, etc

  int x = -1;
  int y = -1;
  while(cvWaitKey(15) != 27)
  { 
    if(x != mouse_x || y != mouse_y)
    {
      x = mouse_x;
      y = mouse_y;

      cvReleaseImage(&image_circle);
      image_circle = cvCloneImage(image);
      cvCircle(image_circle,cvPoint(x,y),25,CV_RGB(0,255,0),1);
      cvShowImage(name, image_circle);
    }
  }

  ... // destroy image
}

<强>解释

这里,在鼠标事件中,您只需存储鼠标指针的坐标。当事件发生时,主程序将检查鼠标是否移动以再次重绘整个图像。由于您要删除前一个圆圈,因此必须先复制原始图像以便稍后绘制新圆圈。你可以通过复制原始图像中前一个圆圈的部分而不是整个图像来使这更聪明。

<强>问题

在OpenCV中执行此类操作时出现的问题是,无法检测到鼠标何时离开窗口,以便始终在图像中绘制圆圈。我不认为你可以用OpenCV解决这个问题,因为我不认为有一种MOUSE_OUT事件。您需要查找一些Qt回调或系统函数。