使用PyQt的QLabel组件实现选定目标框功能的方法示例


Posted in Python onMay 19, 2020

问题背景

  基于PyQt5开发了一个可以用于目标跟踪的软件,在开发过程中遇到一个问题,就是如何在PyQt5的组件QLable中自主选定目标框,这个在opencv里面有专门的函数完成这个工作:cv2.selectROI(),我的目的就是在QLabel的基础上,实现类似函数cv2.selectROI()的功能,这样在运行程序的过程中,就能在视频框里面直接选取感兴趣区域。直接贴出实现的最终效果:

使用PyQt的QLabel组件实现选定目标框功能的方法示例

上图中的红色框框就是在QLabel的基础上实现的功能。

实现思路

  具体要实现的功能是,在视频显示区域,点击鼠标左键,开启选择,按照鼠标左键,移动游标,慢慢地绘制出红色的目标框。释放鼠标左键就停止选择目标框。最开始以为PyQt好歹也会提供这样的类来进行开发吧,后来发现其实是没有的,没办法只能写一个QLabel类的子类了。子类的命名为Label,继承自QLabel类,在子类中重写鼠标事件函数,接受鼠标在Label对象上位置信号。PyQt本来就有自己的事件循环,当鼠标落在视频显示区域的时候,触发到Label的鼠标事件,那么就可以开始绘制目标框了。

  这里要记录的就是鼠标按下左键时候的起始坐标pos_1和移动坐标pos_2pos_1=(x0,y0),pos_2=(x1,y1)

  重写按下鼠标事件 按下鼠标左键,触发事件函数mousePressEvent(),事件函数打开绘制标志位self.select_roi_flag,传入事件对象数据,初始化起始坐标x0,y0

  重写释放鼠标事件 按下鼠标左键,触发事件函数mousePressEvent(),关闭绘制标志位self.select_roi_flag

  绘制事件 继承鼠标事件绘制类,创建画笔类对象,在这可以设置画笔的颜色,画线的粗细,如果绘制标志位self.select_roi_flag是打开的,那么将事件对象的位置数据传给x1,y1QRect类是是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选定目标框 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现的简单猜数字游戏
Apr 04 Python
Jupyter中直接显示Matplotlib的图形方法
May 24 Python
基于python3 OpenCV3实现静态图片人脸识别
May 25 Python
Flask-Mail用法实例分析
Jul 21 Python
Python字典中的键映射多个值的方法(列表或者集合)
Oct 17 Python
Python判断变量名是否合法的方法示例
Jan 28 Python
Django框架组成结构、基本概念与文件功能分析
Jul 30 Python
Ubuntu16.04安装python3.6.5步骤详解
Jan 10 Python
Python爬虫教程之利用正则表达式匹配网页内容
Dec 08 Python
Python中seaborn库之countplot的数据可视化使用
Jun 11 Python
Python初学者必备的文件读写指南
Jun 23 Python
利用For循环遍历Python字典的三种方法实例
Mar 25 Python
python 数据分析实现长宽格式的转换
May 18 #Python
如何把外网python虚拟环境迁移到内网
May 18 #Python
python 实现 hive中类似 lateral view explode的功能示例
May 18 #Python
pandas dataframe 中的explode函数用法详解
May 18 #Python
Python pandas 列转行操作详解(类似hive中explode方法)
May 18 #Python
Win 10下Anaconda虚拟环境的教程
May 18 #Python
python异常处理之try finally不报错的原因
May 18 #Python
You might like
PHP4实际应用经验篇(4)
2006/10/09 PHP
PHP 将逗号、空格、回车分隔的字符串转换为数组的函数
2012/06/07 PHP
php数据结构之顺序链表与链式线性表示例
2018/01/22 PHP
javascript 简练的几个函数
2009/08/29 Javascript
基于jquery的无刷新分页技术
2011/06/11 Javascript
两个数组去重的JS代码
2013/12/04 Javascript
js中对象的声明方式以及数组的一些用法示例
2013/12/11 Javascript
利用JavaScript脚本实现滚屏效果的方法
2015/07/07 Javascript
使用jquery实现鼠标滑过弹出更多相关信息层附源码下载
2015/11/23 Javascript
IE8 内存泄露(内存一直增长 )的原因及解决办法
2016/04/06 Javascript
jQuery AJAX timeout 超时问题详解
2016/06/21 Javascript
又一款js时钟!transform实现时钟效果
2016/08/15 Javascript
js canvas仿支付宝芝麻信用分仪表盘
2016/11/16 Javascript
js生成随机数方法和实例
2017/01/17 Javascript
npm国内镜像 安装失败的几种解决方案
2017/06/04 Javascript
vue 里面使用axios 和封装的示例代码
2017/09/01 Javascript
浅谈vue中数据双向绑定的实现原理
2017/09/14 Javascript
vue中路由验证和相应拦截的使用详解
2017/12/13 Javascript
babel的使用及安装配置教程
2018/02/22 Javascript
解决vue处理axios post请求传参的问题
2018/03/05 Javascript
vuex存储复杂参数(如对象数组等)刷新数据丢失的解决方法
2019/11/05 Javascript
详解vue3.0 diff算法的使用(超详细)
2020/07/01 Javascript
JavaScript实现切换多张图片
2021/01/27 Javascript
[42:22]DOTA2上海特级锦标赛C组小组赛#1 OG VS Archon第一局
2016/02/27 DOTA
Python处理PDF及生成多层PDF实例代码
2017/04/24 Python
详解python的argpare和click模块小结
2019/03/31 Python
LocalStorage记住用户和密码功能
2017/07/24 HTML / CSS
美国最大的城市服装和运动鞋零售商:Jimmy Jazz
2016/11/19 全球购物
美国最大的网上冲印店:Shutterfly
2017/01/01 全球购物
利用异或运算实现两个无符号数的加法运算
2013/12/20 面试题
MYSQL支持事务吗
2013/08/09 面试题
捐款倡议书
2014/04/14 职场文书
端午节活动总结报告
2015/02/11 职场文书
小学少先队活动总结
2015/05/08 职场文书
2015年学校政教处工作总结
2015/05/26 职场文书
《分数乘法》教学反思
2016/02/24 职场文书