OpenCV C++ : 画面鼠标操作

背景

在日常使用opencv中,需要使用鼠标进行一些操作。如使用鼠标绘制矩形、画圆、鼠标点击触发特定事件等。下面对OpenCV-C++中如何使用鼠标进行学习记录

使用的API以及参数介绍

API介绍

opencv中使用鼠标事件使用的是鼠标操作相关的回调函数:

cv::setMouseCallback(const string& windowname, MouseCallback onMouse, void* userdata=0)
// windowname: 要操作的窗口名称
// onMouse: 鼠标事件函数,鼠标事件发生以后,要执行的回调函数。函数原型是 
// void onMouse(int event, int x, int y, int flags, void * para)
// userdata: 回调函数的参数

下面是回调函数 " onMouse "

void onMouse(int event, int x, int y, int flags, void *para)
// int event: 鼠标事件,见后续说明
// x, y 是鼠标在图像坐标系中的坐标
// flags :
// para: 是用户传递到回调函数中的参数

其他项目使用涉及到的函数代码:

cv::selectROIs("MultiTracker", frame, bboxes_, showCrosshair, fromCenter);
// “MultiTracker” : windowsName
// frame: 当前画面;格式为cv::Mat
// bboxes: 要存储的框框格式为:std::vector<cv::Rect>
// showCrosshair:默认为True
// fromCenter:从中心点还是从对角点,默认为false,为true时,选框从中心点开始

参数定义:

EVENT:

// EVENT的参数定义
enum
{
	CV_EVENT_MOUSEMOVE =0,//滑动
	CV_EVENT_LBUTTONDOWN =1,//左键点击
	CV_EVENT_RBUTTONDOWN =2,//右键点击
	CV_EVENT_MBUTTONDOWN =3,//中键点击
	CV_EVENT_LBUTTONUP =4,//左键放开
	CV_EVENT_RBUTTONUP =5,//右键放开
	CV_EVENT_MBUTTONUP =6,//中键放开
	CV_EVENT_LBUTTONDBLCLK =7,//左键双击
	CV_EVENT_RBUTTONDBLCLK =8,//右键双击
	CV_EVENT_MBUTTONDBLCLK =9//中键双击
};

flags:

enum
{
CV_EVENT_FLAG_LBUTTON =1,//左键拖拽
CV_EVENT_FLAG_RBUTTON =2,//右键拖拽
CV_EVENT_FLAG_MBUTTON =4,//中键拖拽
CV_EVENT_FLAG_CTRLKEY =8,//按CTRL不放
CV_EVENT_FLAG_SHIFTKEY =16,//按SHIFT不放
CV_EVENT_FLAG_ALTKEY =32//按ALT不放
};

使用案例:

在画面中右击鼠标时,进行ROI选取绘制的工作,即调用selectROIS()函数。
此处的实现在鼠标事件函数onMouse()中实现,selectROIS() 需要传入’frame’, 'bboxes’两个参数,而setMouseCallback()中我们只能传递一个函数"void*paragram" ,并且,鼠标事件函数是无返回函数,我们可以通过全局变量或者类/结构体来实现参数赋值传递,, 所以我们在这里可以将frame和bboxes封装成一个类或者一个结构体。

当传入的是结构体或者类时,由于形参类型时void *类型,我们需要在onMouse()代码块中,对传入的形参para进行格式转换。使用中,我使用mousepara *p = (mousepara*)para;实现。

// 编译时提示我onMouse()重定义,opnecv中已经有在用的onMouse()函数。所以我在这里重新定义了下函数名。
void MouseEvent(int event, int x,int y, int flags, void *para)
{
	mousepara *p = (mousepara*)para;	
	switch (event)
	{
		case cv::EVENT_RBUTTONDOWN:
			cv::selectROIs("MultiTracker",p->frame, p->bboxes);
		default:
			break;
	}
}

实际代码中,该设想并没有实现。在上述代码中设断点调试时,地址显示没有变化,而且在此处的参数值都做了对应的改变。但是返回调用处时,值又变回成0,或者说时值又没了。目前没找到原因。
上述问题通过使用全局变量代替要修改的变量参数成功

TODO: 打个标记,弄明白了回来补上

–>补充:
上面的问题解决了,原因是我imshow()之后,对参数进行了重置处理,最后才是waitKey(), 把等待延时写在imshow()之后,再对数值进行处理,问题就解决了。具体更细节的原因没有完全理解。不过在其他的代码中没有出现该问题。

指针传值测试成功的小程序:

#pragma once
#include <iostream>
using namespace std;

typedef struct teststruct
{
	int a;
	int b;
	std::vector<int> c;
};

void func(void * para)
{
	teststruct *c = (teststruct*)para;
	c->a = 3;
	c->b = 4;
	for (int i = 0;i < 4;i++)
	{
		c->c.push_back(i);
	}
	cout << "id -->c:" << c << endl;
	cout << "id-->para:" << para << endl;
}
int main()
{
	teststruct a;
	teststruct *p = &a;
	p->a = 1;
	p->b = 2;
	func(p);
	cout << "id -->p:" << p << endl;
	cout << p->b << endl;
	cout << p->c.back() << endl;
	system("pause");
	return 0;	
}

代码跳转链接:基于KCF的多目标跟踪实现。

水平有限,仅作为自己的学习记录,如有错误还请不吝赐教。谢谢!

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值