如何用OpenCV跟踪鼠标操作

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

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

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

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

  

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

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

onMouse响应函数的声明为:

1 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声明为类的成员函数。

时间: 2024-10-24 22:54:05

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

OpenCV Example(鼠标操作)

1 #include "opencv2/opencv.hpp" 2 3 #define WINDOW_NAME "[程序窗口]" 4 5 6 void on_MouseHandle(int event, int x, int y, int flags, void* param); 7 void DrawRectangle(cv::Mat& img, cv::Rect box); 8 9 cv::Rect g_rectangle; 10 bool g_bDra

opencv实现跟踪鼠标选取的目标

简介 本篇讲解opencv video鼠标选中的物体跟踪,使用的是opencv提供的calcOpticalFlowPyrLK. calcOpticalFlowPyrLK介绍 void calcOpticalFlowPyrLK(InputArray prevImg, InputArray nextImg, InputArray prevPts, InputOutputArray nextPts, OutputArray status, OutputArray err, Size winSize=S

鼠标操作

一.鼠标操作SetMouseCallback() 1 #include<opencv2\opencv.hpp> 2 #include<iostream> 3 #include<vector> 4 using namespace cv; 5 using namespace std; 6 7 #define WINDOW_NAME "[程序窗口]" 8 9 void on_MouseHandle(int event, int x, int y, int

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

/*=========================================================================*/ // 阵列操作 /*=========================================================================*/ 基本矩阵和图像运算符 ———————————————————————————————————————————————————————————————————————————

win7休眠的开启与关闭方法命令行操作和图文结合的鼠标操作

win7休眠的开启与关闭方法 从开始菜单中找到"附件→命令提示符",手工输入如下命令:powercfg -a,从这里可以清楚的看到,计算机是支持休眠的,显示"尚未启用休眠".仍然在命令提示符下进行操作,     开始休眠方法:手工键入如下命令: powercfg -hibernate on(关闭则为powercfg -hibernate off) 命令执行之后立即就可以生效,无需要重新启动系统,再次执行"powercfg -a"命令,这里会提示当

教你ZBrush快捷键与鼠标操作

ZBrush是一款3D图形绘制软件,功能十分强大,且比较复杂,除了菜单栏功能按钮,ZBrush®还提供了一系列快捷键与鼠标操作,熟练掌握ZBrush®快捷键与鼠标操作,可以帮助您大大节省图形创作时间.下面是快捷键与鼠标操作的具体指令及其对应的作用: 基础 工具 Tools                                                 F1 笔刷 Brushes                                               F2 笔触

用Mouse_event()来模拟鼠标操作(转载)

在自动化测试的开发中,有一些控件的ID是很难找到的,所以有些时候,我们直接设置鼠标的位置,然后是用click事件,会收到很好的效果.在Windows API中有个mouse_event函数为我们准备好了这一切. 这个函数在user32.dll这个库文件里面.我们可以在C:\WINDOWS\system32(XP系统)这个目录下找到这个文件,他是系统自带的. 我们以C#直接调用这个文件中的API为例子来说下怎么进行鼠标操作,首先在我们C#中声明引用,如果是一个基于From的程序,这个声明的位置写在

OpenCV &mdash;&mdash; 跟踪与运动

理解物体运动主要包含两个部分:识别和建模 识别在视频流后续的帧中找出之前某帧镇南关的感兴趣物体   寻找角点 可跟踪的特征点都称为角点,从直观上讲,角点(而非边缘)是一类含有足够信息且能从当前帧和下一帧中都能提取出来的点 Harris 角点位于图像二阶导数的自相关矩阵有两个最大特征值的地方,这在本质上表示以此点为中心周围存在至少两个不同方向的纹理,正如实际的角点是由至少两个边缘相交于一点而产生 cvGoodFeaturesToTrack 采用Shi 和Tomasi提出的方法,先计算二阶导数,在计

OpenCV视频序列操作基础

 从视频序列中抓取一帧 OpenCV支持从摄像头或视频文件(AVI)中抓取图像. 从摄像头获取初始化: CvCapture* capture = cvCaptureFromCAM(0); // capture from video device #0 从视频文件获取初始化: CvCapture* capture = cvCaptureFromAVI("infile.avi"); 抓取帧: IplImage* img = 0; if(!cvGrabFrame(capture)){