当前位置: 首页 > news >正文

2.10鼠标事件

目录

实验原理

实验代码

运行结果

文章参考


实验原理

在 OpenCV 中存在鼠标的操作,比如左键单击、双击等。对于 OpenCV 来讲,用户的鼠标操作被认为发生了一个鼠标事件,需要对这个鼠标事件进行处理,这就是事件的响应。下面我们来介绍一下鼠标事件。 
鼠标事件包括左键按下、左键松开、左键双击、鼠标移动等。当鼠标事件发生时,OpenCV 会让一个鼠标响应函数自动被调用,相当于一个回调函数,这个回调函数就是鼠标事件处理函数。 OpenCV 提供了 setMousecallback 来预先设置回调函数(相当于告诉系统鼠标处理的回调函数已经设置好了,有鼠标事件发生时,系统调用这个回调函数即可),注意是系统调用,而不是开发者调用,因此称为回调函数。函数 setMousecallback 声明如下: 

void setMousecallback(const string& winname, MouseCallback onMouse, void*userdata=0);
其中参数
winname 表示窗口的名字,
onMouse 是鼠标事件响应的回调函数指针,
userdate 是传给回调函数的参数。
这个函数名也比较形象,一看就知道是用来设置鼠标回调函数的。 

鼠标事件回调函数类型 MouseCallback 定义如下:

typedef void(* cv::MouseCallback)(int event,int x,int y,int flags,void*useradata);
其中参数 
event 表示鼠标事件,
x 表示鼠标事件的 x 坐标,
y 表示鼠标事件的 y 坐标,
flags 表示鼠标事件的标志,
userdata 是可选的参数。 

鼠标事件 event 主要有以下几种:

enum
{
EVENT_MOUSEMOVE =0, //滑动
EVENT_LBUTTONDOWN =1, //左键单击
EVENT_RBUTTONDOWN=2,//右键单击
EVENT_MBUTTONDOWN=3,//中键单击
EVENT_LBUTTONUP=4,//左键放开
EVENT_RBUTTONUP=5,//右键放开
EVENT_MBUTTONUP=6,//中键放开
EVENT_LBUTTONDBLCLK=7,//左键双击
EVENT_RBUTTONDBLCLK=8,//右键双击
EVENT_MBUTTONDBLCLK=9,//中键双击
EVENT_MOUSEWHEEL=10,//正值表示向前滚动,负值表示向后滚动
EVENT_MOUSEHWHEEL=11//正值表示向左滚动,负值表示向右滚动
};

鼠标事件标志 flags 主要有以下几种:

enum {
EVENT_FLAG_LBUTTON = 1,//按住左键拖曳
EVENT_FLAG_RBUTTON = 2,//按住右键拖曳
EVENT_FLAG_MBUTTON = 4,//按住中键拖曳
EVENT_FLAG_CTRLKEY = 8,//按 Ctrl
EVENT_FLAG_SHIFTKEY = 16,//按 Shift
EVENT_FLAG_ALTKEY = 32//按 Alt
};

通过 event 和 flags 就能清楚地了解当前鼠标发生了哪种操作。

https://cloud.tencent.com/developer/article/1553511icon-default.png?t=N7T8https://cloud.tencent.com/developer/article/1553511

line()函数来对直线的绘制。

//https://www.opencv.org.cn/opencvdoc/2.3.2/html/modules/core/doc/drawing_functions.html?highlight=line#cv.Line
void line(Mat& img, Point pt1, Point pt2, const Scalar& color, int thickness=1, int lineType=8, int shift=0);参数:
img: 要绘制线段的图像。
pt1: 线段的起点。
pt2: 线段的终点。
color: 线段的颜色,通过一个Scalar对象定义。
thickness: 线条的宽度。
lineType: 线段的类型。可以取值8, 4, 和CV_AA, 
分别代表8邻接连接线,4邻接连接线和反锯齿连接线。
默认值为8邻接。为了获得更好地效果可以选用CV_AA(采用了高斯滤波)。
shift: 坐标点小数点位数。

实验代码


#include "pch.h"
#include <opencv2/highgui/highgui_c.h>
#include <opencv2\opencv.hpp>
//#pragma comment(lib, "opencv_world450d.lib")  //引用引入库 
using namespace cv;
#include<iostream>
using namespace std;#define WINDOW "原图"
Mat g_srcImage, g_dstImage;
Point previousPoint;
bool P = false;
void on_mouse(int event, int x, int y, int flags, void*);
int main()
{g_srcImage = imread("200.jpg", 1);imshow(WINDOW, g_srcImage);setMouseCallback(WINDOW, on_mouse, 0);waitKey(0);return 0;
}
void on_mouse(int event, int x, int y, int flags, void*)
{if (event == EVENT_LBUTTONDOWN){previousPoint = Point(x, y);}else if (event == EVENT_MOUSEMOVE && (flags&EVENT_FLAG_LBUTTON)){Point pt(x, y);line(g_srcImage, previousPoint, pt, Scalar(0, 0, 255), 2, 5, 0);//https://blog.csdn.net/hk121/article/details/81085213previousPoint = pt;imshow(WINDOW, g_srcImage);}
}

在代码中,on_mouse 就是用来处理鼠标事件的回调函数,当鼠标有动作产生时,on_mouse 会被系统调用,然后在 on_mouse 中,判断发生了哪种动作,进而进行相应的处理。本例我们关心的是按下鼠标左键,然后按住左键时的鼠标移动。一旦按下鼠标左键,就记录下当时的位置(也就是画线的开始点),位置记录在 previousPoint 中,接着如果继续有鼠标移动事件发生,我们就开始调用函数 line 画线。最后把画了线的图像数据 g_srcImage 用函数 imshow 显示出来。

运行结果

文章参考

程序中如果鼠标右键被按下,则会提示“点击鼠标左键才可以绘制轨迹”,点击左键会输出当前鼠标的坐标,并将该点坐标定义为某段轨迹的起始位置。之后按住左键移动鼠标,会进入到第三个逻辑判断,绘制鼠标的移动轨迹。

示例程序中提供了两种绘制轨迹的方法,

第一种是每次调用回调函数获得鼠标位置时更改周围的图像像素值,这种方式比较直观,但是由于回调函数有一定的执行时间,因此当鼠标移动较快时绘制的图像轨迹会出现断点

第二种绘制轨迹的方式是在前一时刻和当前时刻鼠标位置间绘制直线,这种方式可以避免因鼠标移动过快而带来的轨迹出现断点的问题。

https://cloud.tencent.com/developer/article/1553511

// myMouse.cpp绘制鼠标移动轨迹
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>using namespace std;
using namespace cv;Mat img, imgPoint; //全局的图像
Point prePoint; //前一时刻鼠标的坐标,用于绘制直线
void mouse(int event, int x, int y, int flags, void*);int main()
{img = imread("200.jpg");if (!img.data){cout << "请确认输入图像名称是否正确!" << endl;system("pause");return -1;}img.copyTo(imgPoint);imshow("图像窗口1", img);imshow("图像窗口2", imgPoint);setMouseCallback("图像窗口1", mouse, 0); //鼠标事件waitKey(0);system("pause");return 0;}void mouse(int event, int x, int y, int flags, void*)
{if (event == EVENT_RBUTTONDOWN) //单击右键{cout << "点击鼠标左键才可以绘制轨迹" << endl;}if (event == EVENT_LBUTTONDOWN) //单击左键,输出坐标{prePoint = Point(x, y);cout << "轨迹起使坐标" << prePoint << endl;}if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON)) //鼠标按住左键移动{//通过改变图像像素显示鼠标移动轨迹imgPoint.at<Vec3b>(y, x) = Vec3b(0, 0, 255);imgPoint.at<Vec3b>(y, x - 1) = Vec3b(0, 0, 255);imgPoint.at<Vec3b>(y, x + 1) = Vec3b(0, 0, 255);imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);imgPoint.at<Vec3b>(y + 1, x) = Vec3b(0, 0, 255);imshow("图像窗口2", imgPoint);//通过绘制直线显示鼠标移动轨迹Point pt(x, y);line(img, prePoint, pt, Scalar(0, 0, 255), 2, 5, 0);prePoint = pt;imshow("图像窗口1", img);}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • malloc中的mmap是如何分配内存的
  • Leetcode第414周赛第二题:3281. 范围内整数的最大得分
  • 两种常用损失函数:nn.CrossEntropyLoss 与 nn.TripletMarginLoss
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • 解决 Python IDLE 横向显示文字的方法
  • JavaWeb笔记整理14——公共字段自动填充技术实现
  • 比特币网络和支付
  • Linux网络编程IO管理
  • 使用Docker快速启动Nacos集群
  • 微信小程序页面制作——个人信息
  • 探究:为什么JavaScript要在body标签尾部引入?
  • 韦季李输入法_屏幕键盘第二个选择
  • 社群空间站9.9付费入群系统二开源码 易支付版全套搭建教程
  • 2024上学期--实验室学习计划
  • Android终端如何快速接入GB28181平台实现实时音视频回传
  • SegmentFault for Android 3.0 发布
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 《微软的软件测试之道》成书始末、出版宣告、补充致谢名单及相关信息
  • 78. Subsets
  • css的样式优先级
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JWT究竟是什么呢?
  • MobX
  • ng6--错误信息小结(持续更新)
  • vue从创建到完整的饿了么(11)组件的使用(svg图标及watch的简单使用)
  • 分布式事物理论与实践
  • 基于HAProxy的高性能缓存服务器nuster
  • 基于游标的分页接口实现
  • 突破自己的技术思维
  • 3月7日云栖精选夜读 | RSA 2019安全大会:企业资产管理成行业新风向标,云上安全占绝对优势 ...
  • ​Distil-Whisper:比Whisper快6倍,体积小50%的语音识别模型
  • !!java web学习笔记(一到五)
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (接口封装)
  • (离散数学)逻辑连接词
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (十二)python网络爬虫(理论+实战)——实战:使用BeautfulSoup解析baidu热搜新闻数据
  • (十一)c52学习之旅-动态数码管
  • (一)Linux+Windows下安装ffmpeg
  • (转)Android学习笔记 --- android任务栈和启动模式
  • (转)总结使用Unity 3D优化游戏运行性能的经验
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .Mobi域名介绍
  • .NET Core使用NPOI导出复杂,美观的Excel详解
  • .net 简单实现MD5
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • .py文件应该怎样打开?
  • /bin/bash^M: bad interpreter: No such file ordirectory
  • @RequestBody与@RequestParam:Spring MVC中的参数接收差异解析
  • @SuppressLint(NewApi)和@TargetApi()的区别
  • [ vulhub漏洞复现篇 ] ECShop 2.x / 3.x SQL注入/远程执行代码漏洞 xianzhi-2017-02-82239600
  • [ 渗透测试面试篇 ] 渗透测试面试题大集合(详解)(十)RCE (远程代码/命令执行漏洞)相关面试题
  • [c++] 什么是平凡类型,标准布局类型,POD类型,聚合体
  • [Debugger]调试Arm设备