Fork me on GitHub

opencv之鼠标响应函数

背景

  • setMouseCallback()函数
void setMouseCallback(const string& winname,     //图像视窗名称
MouseCallback onMouse,     //鼠标响应函数,监视到鼠标操作后调用并处理相应动作
void* userdata = 0        //鼠标响应处理函数的ID,识别号
);
  • OnMouseAction()响应函数
void OnMouseAction(int event,int x,int y,int flags,void *user_data)
{
  // 自定义
}
  • x, y
x - x coordinate of the mouse event
y - y coordinate of the mouse event
  • Event
#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         //中键双击
  • flags
#define CV_EVENT_FLAG_LBUTTON 1       //左鍵拖曳
#define CV_EVENT_FLAG_RBUTTON 2       //右鍵拖曳
#define CV_EVENT_FLAG_MBUTTON 4       //中鍵拖曳
#define CV_EVENT_FLAG_CTRLKEY 8       //(8~15)按Ctrl不放事件
#define CV_EVENT_FLAG_SHIFTKEY 16     //(16~31)按Shift不放事件
#define CV_EVENT_FLAG_ALTKEY 32       //(32~39)按Alt不放事件
  • userdata
Any pointer passes to the "**setMouseCallback"** function as the 3rd parameter (see below)

示例1

捕捉光标在图像中的移动实践, 并返回光标在图像中的坐标, 同时捕捉鼠标的左键, 中建和右键的响应实践.

#include <opencv2/opencv.hpp>

void CallBackFunc(int event, int x, int y, int flags, void* userdata)
{
  if  ( event == CV_EVENT_LBUTTONDOWN )
  {
    std::cout << "Left button of the mouse is clicked - position (" << x << ", " << y << ")" << std::endl;
  }
  else if  ( event == CV_EVENT_RBUTTONDOWN )
  {
    std::cout << "Right button of the mouse is clicked - position (" << x << ", " << y << ")" << std::endl;
  }
  else if  ( event == CV_EVENT_MBUTTONDOWN )
  {
    std::cout << "Middle button of the mouse is clicked - position (" << x << ", " << y << ")" << std::endl;
  }
  else if ( event == CV_EVENT_MOUSEMOVE )
  {
    std::cout << "Mouse move over the window - position (" << x << ", " << y << ")" << std::endl;
  }    
}
 
int main()
{
  // Read image from file 
  cv::Mat img(480, 640, CV_8S, cv::Scalar(0));

  //if fail to read the image
  if ( img.empty() ) 
  { 
    std::cout << "Error loading the image" << std::endl;
    return -1; 
  }

  cv::namedWindow("ImageDisplay", 1);
  cv::imshow("ImageDisplay", img);
  cv::setMouseCallback("ImageDisplay", CallBackFunc, NULL);
  cv::waitKey(0);

  return 0; 
}

示例2

捕捉按下ctrl按键, 同时点击鼠标左键.....

#include <opencv2/opencv.hpp>
 
void CallBackFunc(int event, int x, int y, int flags, void* userdata)
{
  if ( flags == (CV_EVENT_FLAG_CTRLKEY + CV_EVENT_FLAG_LBUTTON) )
  {
    std::cout << "Left mouse button is clicked while pressing CTRL key - position (" << x << ", " << y << ")" << std::endl;
  }
  else if ( flags == (CV_EVENT_FLAG_RBUTTON + CV_EVENT_FLAG_SHIFTKEY) )
  {
    std::cout << "Right mouse button is clicked while pressing SHIFT key - position (" << x << ", " << y << ")" << std::endl;
  }
  else if ( event == CV_EVENT_MOUSEMOVE && flags == CV_EVENT_FLAG_ALTKEY)
  {
    std::cout << "Mouse is moved over the window while pressing ALT key - position (" << x << ", " << y << ")" << std::endl;
  }
}
 
int main(int argc, char** argv)
{
  // Read image from file 
  cv::Mat img(480, 640, CV_8S, cv::Scalar(0));

  //if fail to read the image
  if ( img.empty() ) 
  { 
      std::cout << "Error loading the image" << std::endl;
      return -1; 
  }

  cv::namedWindow("My Window", 1);
  cv::setMouseCallback("My Window", CallBackFunc, NULL);
  cv::imshow("My Window", img);
  cv::waitKey(0);

  return 0;
}

示例3

捕捉鼠标左键点击时间, 同时返回该光标的像素强度.

#include "opencv2/highgui/highgui.hpp"
#include <iostream>
 
using namespace std;
using namespace cv;
 
void mouseEvent(int evt, int x, int y, int flags, void* param) 
{                    
    Mat* rgb = (Mat*) param;
    if (evt == CV_EVENT_LBUTTONDOWN) 
    { 
        printf("%d %d: %d, %d, %d\n", 
        x, y, 
        (int)(*rgb).at<Vec3b>(y, x)[0], 
        (int)(*rgb).at<Vec3b>(y, x)[1], 
        (int)(*rgb).at<Vec3b>(y, x)[2]); 
    }         
}
 
int main(int argc, char** argv)
{
    // Read image from file
    Mat img = imread("lena.JPG");
 
    //if fail to read the image
    if ( img.empty() )
    {
        cout << "Error loading the image" << endl;
        return -1;
    }
 
    //Create a window
    namedWindow("My Window", 1);
 
    //set the callback function for any mouse event
    setMouseCallback("My Window", mouseEvent, &img);
 
    //show the image
    imshow("My Window", img);
 
    // Wait until user press some key
    waitKey(0);
 
    return 0;
}

示例4

捕捉鼠标左键点击时间, 同时捕捉鼠标拖动框选时间,

void onMouseAction(int event, int x, int y, int flag, void* g)
{
  CalibEva* pthis = (CalibEva*)g;
  cv::Point& begin_point = pthis->begin_point_;
  cv::Point& end_point = pthis->end_point_;
  bool& is_mouse_move = pthis->is_mouse_move_;

  if (event == CV_EVENT_LBUTTONDOWN)
  {
    // INFO << "CV_EVENT_LBUTTONDOWN" << REND;
    begin_point = cv::Point(x, y);
  }
  else if (event == CV_EVENT_LBUTTONUP)
  {
    // INFO << "CV_EVENT_LBUTTONUP" << REND;
    end_point = cv::Point(x, y);
  }
  else if (event == CV_EVENT_MOUSEMOVE && (flag & CV_EVENT_FLAG_LBUTTON))
  {
    // INFO << "CV_EVENT_MOUSEMOVE" << REND;
    is_mouse_move = true;
  }
}
  • 点击时间
// pick one corner point
cv::namedWindow("input_image", cv::WINDOW_NORMAL);
INFO << "Please pick the board corner in input image window!" << REND;
cv::imshow("input_image", input_image);
cv::setMouseCallback("input_image", onMouseAction, this);
cv::waitKey(0);
image_corner_point = end_point_;
  • 拖动事件
cv::namedWindow("edge_cloud", cv::WINDOW_NORMAL);
INFO << "Please pick the " << select_line_num << " rectangle in edge cloud windows!" << REND;
cv::imshow("edge_cloud", edge_image);
cv::setMouseCallback("edge_cloud", onMouseAction, this);
cv::waitKey(0);
cv::rectangle(edge_image, cv::Rect(begin_point_, end_point_), cv::Scalar(255));

备注: 将类的this指针传递给callback函数, 其中用到的成员数据需要为public的, 有个判断是否有拖动的flag的.

参考

posted @ 2021-06-28 09:07  chrislzy  阅读(196)  评论(0编辑  收藏  举报