博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
OpenCV C++ : 画面鼠标操作
阅读量:4298 次
发布时间:2019-05-27

本文共 2823 字,大约阅读时间需要 9 分钟。

背景

在日常使用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
// 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 
using namespace std;typedef struct teststruct{
int a; int b; std::vector
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; }

代码跳转链接:

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

转载地址:http://ttnws.baihongyu.com/

你可能感兴趣的文章
删远端分支报错remote refs do not exist或git: refusing to delete the current branch解决方法
查看>>
python multiprocessing遇到Can’t pickle instancemethod问题
查看>>
APP真机测试及发布
查看>>
iOS学习之 plist文件的读写
查看>>
通知机制 (Notifications)
查看>>
10 Things You Need To Know About Cocoa Auto Layout
查看>>
C指针声明解读之左右法则
查看>>
一个异步网络请求的坑:关于NSURLConnection和NSRunLoopCommonModes
查看>>
iOS 如何放大按钮点击热区
查看>>
ios设备唯一标识获取策略
查看>>
获取推送通知的DeviceToken
查看>>
Could not find a storyboard named 'Main' in bundle NSBundle
查看>>
CocoaPods安装和使用教程
查看>>
Beginning Auto Layout Tutorial
查看>>
block使用小结、在arc中使用block、如何防止循环引用
查看>>
iPhone开发学习笔记002——Xib设计UITableViewCell然后动态加载
查看>>
iOS开发中遇到的问题整理 (一)
查看>>
Swift code into Object-C 出现 ***-swift have not found this file 的问题
查看>>
为什么你的App介绍写得像一坨翔?
查看>>
RTImageAssets插件--@3x可自动生成@2x图片
查看>>