转载:如何用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. 超详细!mac flutter 创建过程及遇到的问题

    虽然网上有教程,但是过程中遇到些问题,这些问题教程里并没有,所以写这个文章记录一下. 1.打开终端 2.clone flutter 命令: git clone -b beta https://gith ...

  2. spring mvc: xml生成

    spring mvc: xml生成 准备: javax.xml.bind.annotation.XmlElement; javax.xml.bind.annotation.XmlRootElement ...

  3. 在 Ubuntu 里如何下载、安装和配置 Plank Dock

    一个众所周知的事实就是,Linux 是一个用户可以高度自定义的系统,有很多选项可以选择 —— 作为操作系统,有各种各样的发行版,而对于单个发行版来说,又有很多桌面环境可以选择.与其他操作系统的用户一样 ...

  4. MongoDB.Driver 2.4以上版本 在.NET中的基本操作

    MongoDB.Driver是操作mongo数据库的驱动,最近2.0以下版本已经从GitHub和Nuget中移除了,也就是说.NET Framework4.0不再能从官方获取到MongoDB的驱动了, ...

  5. UVA-10972 RevolC FaeLoN (边双连通+缩点)

    题目大意:将n个点,m条边的无向图变成强连通图,最少需要加几条有向边. 题目分析:所谓强连通,就是无向图中任意两点可互达.找出所有的边连通分量,每一个边连通分量都是强连通的,那么缩点得到bcc图,只需 ...

  6. nyoj20——有向无环图深搜模板

    吝啬的国度 时间限制:1000 ms  |  内存限制:65535 KB 难度:3   描述 在一个吝啬的国度里有N个城市,这N个城市间只有N-1条路把这个N个城市连接起来.现在,Tom在第S号城市, ...

  7. GlusterFS原创资源

    学习博客: GlusterFS原创资源

  8. 【Error】SSL InsecurePlatform error when using Requests package

    使用requests时会出席SSL InsecurePlatform error when using Requests package的错误,一般情况下python2.7.10以下的环境会出现此错误 ...

  9. 优化JDBC封装

    可重用性较强的JDBC封装 以下为代码,注释中写了主要思想 主类 com.util.JDBCUtil.java package com.util; import java.lang.reflect.F ...

  10. qml 带时钟效果

    qt 自带源码样例:在样例中输入clock,找到名叫Qt Quick Demo Clocks. 这个样例写的不错,还是带时差的.不过我们其实不需要这么复杂的功能. timer启动这个就不用说了: Ti ...