2

使用 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;

          }
    }
4

1 回答 1

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 回调或系统函数。

于 2013-09-11T18:19:57.763 回答