问题背景
基于PyQt5开发了一个可以用于目标跟踪的软件,在开发过程中遇到一个问题,就是如何在PyQt5的组件QLable中自主选定目标框,这个在opencv里面有专门的函数完成这个工作:cv2.selectROI(),我的目的就是在QLabel的基础上,实现类似函数cv2.selectROI()的功能,这样在运行程序的过程中,就能在视频框里面直接选取感兴趣区域。直接贴出实现的最终效果:
上图中的红色框框就是在QLabel的基础上实现的功能。
实现思路
具体要实现的功能是,在视频显示区域,点击鼠标左键,开启选择,按照鼠标左键,移动游标,慢慢地绘制出红色的目标框。释放鼠标左键就停止选择目标框。最开始以为PyQt好歹也会提供这样的类来进行开发吧,后来发现其实是没有的,没办法只能写一个QLabel类的子类了。子类的命名为Label,继承自QLabel类,在子类中重写鼠标事件函数,接受鼠标在Label对象上位置信号。PyQt本来就有自己的事件循环,当鼠标落在视频显示区域的时候,触发到Label的鼠标事件,那么就可以开始绘制目标框了。
这里要记录的就是鼠标按下左键时候的起始坐标pos_1和移动坐标pos_2,pos_1=(x0,y0),pos_2=(x1,y1)。
重写按下鼠标事件 按下鼠标左键,触发事件函数mousePressEvent(),事件函数打开绘制标志位self.select_roi_flag,传入事件对象数据,初始化起始坐标x0,y0。
重写释放鼠标事件 按下鼠标左键,触发事件函数mousePressEvent(),关闭绘制标志位self.select_roi_flag。
绘制事件 继承鼠标事件绘制类,创建画笔类对象,在这可以设置画笔的颜色,画线的粗细,如果绘制标志位self.select_roi_flag是打开的,那么将事件对象的位置数据传给x1,y1。QRect类是是PyQt的内置数据结构,具体结构是这样的Rect=(x,y,w,h),之后就调用画笔对象方法动态绘制目标框。直到绘制标志位被关闭,就是释放鼠标,则停止绘画。
具体实现代码:
from PyQt5.QtWidgets import QLabel from PyQt5.QtCore import Qt,QRect from PyQt5.QtGui import QPainter,QPen class Label(QLabel): x0=0 y0=0 x1=0 y1=0 open_mouse_flag=False select_roi_flag=False draw_roi_flag=False clear_flag=False rect = QRect() #按下鼠标 def mousePressEvent(self, event): if self.open_mouse_flag is True: self.select_roi_flag=True self.x0=event.x() self.y0=event.y() #释放鼠标 def mouseReleaseEvent(self, event): self.select_roi_flag=False #移动鼠标 def mouseMoveEvent(self, event): if self.select_roi_flag is True: self.x1=event.x() self.y1=event.y() if self.draw_roi_flag is True: self.update() #绘制事件 def paintEvent(self,event): super().paintEvent(event) painter = QPainter(self) painter.setPen(QPen(Qt.red, 5, Qt.SolidLine)) if self.clear_flag is True: self.x0=0 self.y0=0 self.x1=0 self.y1=0 self.rect = QRect(self.x0, self.y0, abs(self.x1 - self.x0), abs(self.y1 - self.y0)) painter.drawRect(self.rect) self.update()
其他要注意的问题
子类Label除了能自定义选择目标框,还要在更新内容是清除绘制内容,实现这个功能可以通过设置清空标志位clear_flag,当标志位打开的时候,将起始坐标和更新坐标重置为:(0,0)(0,0),这样绘制内容就被更新了。
具体实现代码:
# 清除label对象的绘制内容 def clear_label(self): self.label_show.clear_flag = True self.label_show.clear()
此外我还重写了键盘事件,通过敲击键盘来控制鼠标的绘制事件,这里的内容主要包括切换游标,开启绘制事件,确认绘制事件。
具体实现代码:
# 重写键盘事件 def keyPressEvent(self, QKeyEvent): if self.open_keyboard_flag is True: # 当键盘事件为真的是才有键盘事件监控 if QKeyEvent.key() == Qt.Key_S: self.label_show.setCursor(Qt.CrossCursor) # 切换游标为十字型 self.label_show.open_mouse_flag = True self.label_show.draw_roi_flag = True if QKeyEvent.key() == Qt.Key_Q: # 按下'q'键键盘监控关闭 self.label_show.unsetCursor() self.label_show.draw_roi_flag = False self.label_show.open_mouse_flag = False self.open_keyboard_flag = False
到此这篇关于使用PyQt的QLabel组件实现选定目标框功能的方法示例的文章就介绍到这了,更多相关PyQt QLabel选定目标框 内容请搜索小牛知识库以前的文章或继续浏览下面的相关文章希望大家以后多多支持小牛知识库!
本文向大家介绍Android组件实现列表选择框功能,包括了Android组件实现列表选择框功能的使用技巧和注意事项,需要的朋友参考一下 android提供的列表选择框(Spinner)相当于web端用户注册时的选择下拉框,比如注册候选择省份城市等。如下图便是一个列表选择框 下拉列表的列表选择项能够通过xml文件的android:entries属性指定,或是在java代码中导入,属性android:
本文向大家介绍Yii框架使用魔术方法实现跨文件调用功能示例,包括了Yii框架使用魔术方法实现跨文件调用功能示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Yii框架使用魔术方法实现跨文件调用。分享给大家供大家参考,具体如下: 目前项目用yii框架,controller调用facade的方法,facade调用adapter的方法,adapter调用api的方法,api封装了sql方法,但
本文向大家介绍PyQt实现计数器的方法示例,包括了PyQt实现计数器的方法示例的使用技巧和注意事项,需要的朋友参考一下 1、PyQt介绍 PyQt是python的GUI框架之一,这是一个跨平台的UI框架,即可以运行在windows、Linux、Mac上,可以用来替换Python内置的TKinter。 PyQt支持Python2.x和Python3.x。而Qt是Digia公司的产品,是一个跨平台的C
本文向大家介绍Laravel框架实现的使用smtp发送邮件功能示例,包括了Laravel框架实现的使用smtp发送邮件功能示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Laravel框架实现的使用smtp发送邮件功能。分享给大家供大家参考,具体如下: 1、.env文件中配置 MAIL_DRIVER=smtp MAIL_HOST=smtp.邮箱后缀 MAIL_PORT=邮件服务器发送端
本文向大家介绍thinkPHP5框架实现分页查询功能的方法示例,包括了thinkPHP5框架实现分页查询功能的方法示例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了thinkPHP5框架实现分页查询功能的方法。分享给大家供大家参考,具体如下: controller文件内Admin.php model文件内Admin.php lst.html 更多关于thinkPHP相关内容感兴趣的读者可
本文向大家介绍Thinkphp5框架使用validate实现验证功能的方法,包括了Thinkphp5框架使用validate实现验证功能的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了Thinkphp5框架使用validate实现验证功能的方法。分享给大家供大家参考,具体如下: 作为前端er,对于验证这块有着切身的体会,虽然逐渐得心应手,但始终没有一个内置的功能拿来就能用。tp5恰好