转载:如何用OpenCV跟踪鼠标操作

http://blog.skyoung.org/2014/05/01/how-to-track-mouse/

在视频第一帧手动标记出目标的位置是在线视觉跟踪中最基本的一个操作,实现这个操作需要检测鼠标的移动和点击事件。OpenCV提供了setMouseCallback这个函数来响应鼠标的动作,并返回鼠标在绑定窗口上的坐标位置。下面就这个函数的使用做一个简单的介绍。

首先,setMouseCallback的C++函数声明如下:

  

 void onMouse(int event, int x, int y, int flag, void *param)
  • winname是窗口的名称
  • onMouse是响应事件的函数
  • userdata可选项,是用户提供给onMouse响应函数的指针。

这个函数是负责绑定鼠标响应的窗口,这样函数就只会响应关于该窗口的鼠标操作。onMouse定义的针对鼠标不同操作,用户需要做出的操作。

onMouse响应函数的声明为:

 void onMouse(int event, int x, int y, int flag, void *param)
  • event是鼠标响应事件,分别是:

    • EVENT_MOUSEMOVE 滑动
    • EVENT_LBUTTONDOWN 左击
    • EVENT_RBUTTONDOWN 右击
    • EVENT_MBUTTONDOWN 中键点击
    • EVENT_LBUTTONUP 左键放开
    • EVENT_RBUTTONUP 右键放开
    • EVENT_MBUTTONUP 中键放开
    • EVENT_LBUTTONDBLCLK 左键双击
    • EVENT_RBUTTONDBLCLK 右键双击
    • EVENT_MBUTTONDBLCLK 中键双击
  • x是鼠标在图像上的横坐标
  • y是鼠标在图像上的纵坐标
  • flag是标记鼠标某一event下,其附加的状态,比如EVENT_MOUSEMOVE下,flag为EVENT_FLAG_LBUTTON,左键拖拽状态。flag的状态有:
    • EVENT_FLAG_LBUTTON 左键拖拽
    • EVENT_FLAG_RBUTTON 右键拖拽
    • EVENT_FLAG_MBUTTON 中键拖拽
    • EVENT_FLAG_CTRLKEY 按住Ctrl不放
    • EVENT_FLAG_SHIFTKEY 按住Shift不放
    • EVENT_FLAG_ALTKEY 按住Alt不放
  • param是用户传入的指针, 即setMouseCallback中的userdata

下面给出一个画矩形框的代码实例来详细讲解。首先定义了一个MouseCapture的类,存放在MouseCapture.h中。定义的私有成员有存储的图像img,窗口的名称winName,所画方框rect的以及是否结束画框的标志符isMarked。成员函数分别是读取图像的函数loadImg(),画方框函数drawRect()以及鼠标响应事件函数onMouse(),注意这里onMouse定义为static成员函数,是因为setMouseCallBack()不是MouseCapture类的成员函数,如果onMouse为普通成员函数,则会因为函数声明不同而无法使用,而声明为static成员函数后,就可以直接在MouseCapture::作用域里直接访问该静态成员函数onMouse

MouseCapture.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef MOUSECAPTURE_H
#define MOUSECAPTURE_H #include "opencv2/highgui/highgui.hpp"
#include "opencv2/core/core.hpp"
#include <string> class MouseCapture
{
public:
MouseCapture();
void loadImg(std::string imgFile);
void drawRect();
static void onMouse(int event, int x, int y, int flag, void *parma); private:
cv::Mat img;
std::string winName;
cv::Rect rect;
bool isMarked; }; #endif // MOUSECAPTURE_H

接下面列出类MouseCapture的具体定义,在文件MouseCapture.cpp中。onMouse定义了当鼠标左击时,记录下矩形左上角的点,当鼠标抬起时,记录下矩形的宽高,当鼠标滑动且左击拖拽的时候,记录下矩形的宽高。注意这里flag的使用。指针paramsetMouseCallBack()调用的时候传入的this指针(参见50行),这个参数的传入负责把跟踪鼠标所画矩形的框的位置大小信息写入类的成员rect中。

MouseCapture.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "MouseCapture.h"
#include <iostream> using namespace cv;
using namespace std; void MouseCapture::onMouse(int event, int x, int y, int flag, void *param)
{
MouseCapture *MC = (MouseCapture *)param;
switch(event)
{
case EVENT_LBUTTONDOWN:
MC->rect.x = x;
MC->rect.y = y;
break; case EVENT_LBUTTONUP:
MC->rect.width = x - MC->rect.x;
MC->rect.height = y - MC->rect.y;
break; case EVENT_RBUTTONDOWN:
MC->isMarked = true;
break; case EVENT_MOUSEMOVE:
if(flag & EVENT_FLAG_LBUTTON)
{
MC->rect.width = x - MC->rect.x;
MC->rect.height = y - MC->rect.y;
}
break;
default:
break;
} } MouseCapture::MouseCapture():winName("MouseControl"),rect(Rect(0,0,0,0)),isMarked(false)
{} void MouseCapture::loadImg(string imgFile)
{
img = imread(imgFile);
} void MouseCapture::drawRect()
{
namedWindow(winName);
setMouseCallback(winName, onMouse, this);
Mat tmpImg;
while(!isMarked)
{
tmpImg = img.clone();
rectangle(tmpImg, rect, Scalar(0,0,255), 2); string str;
stringstream strStream;
strStream<<"Marked Region:"<<rect.x<<":"<<rect.y<<":"<<rect.width<<":"<<rect.height;
str = strStream.str();
putText(tmpImg, str, Point(20,20), CV_FONT_HERSHEY_COMPLEX, .8,Scalar(0,255,0),2); imshow(winName, tmpImg);
if(waitKey(10) == 'q')
break;
}
cout<<"Mark finished!"<<endl;
}

最后是主函数的调用:

main.cpp

1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include "MouseCapture.h" int main()
{
MouseCapture MC;
MC.loadImg("lena.jpg");
MC.drawRect();
return 0;
}

最后,对于onMouse()鼠标响应事件函数的声明问题还有另外一种解决方案,就是把onMouse()声明为类MouseCapture的友函数,而不把onMouse声明为类的成员函数。

如何用OpenCV跟踪鼠标操作的更多相关文章

  1. windows7如何用键盘模拟鼠标操作

    windows7如何用键盘模拟鼠标操作 https://jingyan.baidu.com/article/6dad5075104907a123e36e38.html 听语音 37453人看了这个视频 ...

  2. opencv鼠标操作及GUI矩形绘画

    OpenCV的鼠标操作是通过一个中介函数配合回调函数来实现的.指定鼠标操作消息回调函数的函数为SetMouseCallback. void setMouseCallback(const string& ...

  3. opencv:鼠标操作

    示例程序: #include <opencv.hpp> using namespace cv; #define WINDOW_NAME "程序窗口" // ------ ...

  4. opencv —— setMouseCallback 响应鼠标操作事件

    鼠标操作:setMouseCallback 函数 借助回调函数,实现对鼠标每次操作的相应,即每进行一步鼠标操作,都会执行一次回调函数. void setMouseCallback(const stri ...

  5. OpenCV——图像的载入、显示、输出到文件和滑动条、鼠标操作

    图像的载入.显示.输出到文件和滑动条 滑动条 示例: 鼠标操作

  6. HighGUI图形图像界面初步——鼠标操作

    OpenCV中的鼠标操作和滑动条的消息映射方式很类似,都是通过一个中介函数配合一个回调函数来实现的,创建和指定滑动条回调函数为createTrackbar, 而指定鼠标操作消息回调函数的函数为setM ...

  7. OpenCV学习笔记(2)——如何用OpenCV处理视频

    如何用OpenCV处理视频 读取视频文件,显示视频,保存视频文件 从摄像头获取并显示视频 1.用摄像头捕获视频 为了获取视频,需要创建一个VideoCapature对象.其参数可以是设备的索引号,也可 ...

  8. [opencv]常用阵列操作函数总结

    /*=========================================================================*/ // 阵列操作 /*============ ...

  9. Python模拟键盘输入和鼠标操作

    Python模拟键盘输入和鼠标操作 一.Python键盘输入模拟: import win32api import win32con win32api.keybd_event(17,0,0,0)  #c ...

随机推荐

  1. vue下个兄弟节点

    checkOne(e) { e.currentTarget.nextElementSibling.style.background = 'red' }

  2. 第八章:部署Tornado

    到目前为止,为了简单起见,在我们的例子中都是使用单一的Tornado进程运行的.这使得测试应用和快速变更非常简单,但是这不是一个合适的部署策略.部署一个应用到生产环境面临着新的挑战,既包括最优化性能, ...

  3. 互联网公司面试必问的Redis题目

    Redis是一个非常火的非关系型数据库,火到什么程度呢?只要是一个互联网公司都会使用到.Redis相关的问题可以说是面试必问的,下面我从个人当面试官的经验,总结几个必须要掌握的知识点. 介绍:Redi ...

  4. 最新Dubbo-admin+Zookeeper搭建

    Zookeeper搭建: 下载zookeeper压缩包并解压,下载地址:http://www.apache.org/dyn/closer.cgi/zookeeper/进入conf目录下将 zoo_sa ...

  5. 网络编程之socketserver初识

    网络编程之socketserver初识 Server #!/usr/bin/env python # @Author : "Wjl" # @Date : 2017/12/22 # ...

  6. ClassPathXmlApplicationContext类

    org.springframework.context.support Class ClassPathXmlApplicationContext java.lang.Objectorg.springf ...

  7. New Concept English three (23)

    31w 45 People become quite illogical when they try to decide what can be eaten and what cannot be ea ...

  8. Android.mk编译的写法

    更多Android.mk的 用法见 :http://blog.csdn.net/fengbingchun/article/details/38705519 如何修改Android.mk 为Androi ...

  9. Git 配置ssh key的步骤

    First start by setting up your own public/private key pair set. This can use either DSA or RSA, so b ...

  10. TCP 初步认识

    TCP连接的建立---三次握手 第一次握手:客户端TCP首先给服务器端TCP发送一个特殊的TCP数据段. 该数据段不包含应用层数据,并将头部中的SYN位设置为1,所以该数据段被称为SYN数据段. 另外 ...