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

所属分类: 脚本专栏 / python 阅读数: 920
收藏 0 赞 0 分享

问题背景

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

上图中的红色框框就是在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
更多精彩内容其他人还在看

python中seaborn包常用图形使用详解

今天小编就为大家分享一篇python中seaborn包常用图形使用详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

numpy:找到指定元素的索引示例

今天小编就为大家分享一篇numpy:找到指定元素的索引示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

python实现图片上添加图片

这篇文章主要为大家详细介绍了python实现图片上添加图片,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

从numpy数组中取出满足条件的元素示例

今天小编就为大家分享一篇从numpy数组中取出满足条件的元素示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python实现图片添加文字

这篇文章主要为大家详细介绍了Python实现图片添加文字,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
收藏 0 赞 0 分享

python实现在多维数组中挑选符合条件的全部元素

今天小编就为大家分享一篇python实现在多维数组中挑选符合条件的全部元素,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python如何使用BeautifulSoup爬取网页信息

这篇文章主要介绍了Python如何使用BeautifulSoup爬取网页信息,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享

浅谈python已知元素,获取元素索引(numpy,pandas)

今天小编就为大家分享一篇浅谈python已知元素,获取元素索引(numpy,pandas),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

numpy ndarray 按条件筛选数组,关联筛选的例子

今天小编就为大家分享一篇numpy ndarray 按条件筛选数组,关联筛选的例子,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Python pickle模块实现对象序列化

这篇文章主要介绍了Python pickle模块实现对象序列化,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多