前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >图像标注版本4-多标注框+标注标签+高亮和删除标签

图像标注版本4-多标注框+标注标签+高亮和删除标签

作者头像
python与大数据分析
发布2023-09-03 21:17:01
2420
发布2023-09-03 21:17:01
举报
文章被收录于专栏:python与大数据分析

4.0版本在3.0版本基础上增加了双击某个位置时,如果这个位置在标注框内,则对选中的标注框进行标识出来,同时提示是否要删除当前选中的标注框,进行删除处理。

在这个版本中首先需要增加双击事件,在双击事件中对当前鼠标位置是否属于某个标注框进行遍历,某个位置可能属于多标注框时,则按照先入后出的原则,进行删除。

在绘制事件中主要是对当前位置所在的标注框进行区分显示。

其他代码基本未变。

一、修改MyLabel代码

增加鼠标双击事件

修改paintevent事件

代码语言:javascript
复制
代码语言:javascript
复制
from PyQt5.QtWidgets import QWidget, QApplication, QLabel, QMessageBox
from PyQt5.QtCore import QRect, Qt
from PyQt5.QtGui import QPixmap, QPainter, QPen
from ui_labelchoose import DialogChoooseLabelWin
import sys


# 重定义QLabel,实现绘制事件和各类鼠标事件
class MyLabel(QLabel):
    def __init__(self, parent=None):
        '''
        :param parent:
        初始化基本参数
        '''
        super(MyLabel, self).__init__(parent)
        self.x0 = 0
        self.y0 = 0
        self.x1 = 0
        self.y1 = 0
        self.x1RealTime = 0
        self.y1RealTime = 0
        self.rect = QRect()
        self.flag = False
        # 增加一个存储标注框坐标的列表
        self.bboxList = []
        self.labelindex = 0
        self.curChoosedbbox = []
        self.curbboxindex = -1
        self.deleteboxflag = False

    # 鼠标双击事件,选中当前坐标的被标注框
    # 如存在在多个被标注框内,则显示最新标注的那个
    # 再询问是否要删除标注框
    # 如果确定要删除,则删除当前坐标所在的标注框
    def mouseDoubleClickEvent(self, event):
        x = event.pos().x()
        y = event.pos().y()
        self.curChoosedbbox = []
        # 如果尚未做标注框,则不处理
        if self.bboxList == []:
            return
        else:
            # 以此判断当前双击坐标出现在哪个标注框中,最后标注的优先删除
            tempbboxlist = self.bboxList
            for index, bbox in enumerate(tempbboxlist):
                # 判断坐标是否在标注框中
                if bbox[0] <= x <= bbox[2] and bbox[1] <= y <= bbox[3]:
                    # 如果在的话,记录当前选中的标注框和list中的索引号
                    self.curChoosedbbox = bbox
                    self.curbboxindex = index
                    # 第一次绘制,高亮显示被选中的标注框
                    self.update()
                    # 判断是否已有选中的标注框
            if self.curChoosedbbox != []:
                reply = QMessageBox.question(self, "警告!", "是否要删除当前选中的标注框",
                                             QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No,
                                             QMessageBox.StandardButton.Yes)
                if reply == QMessageBox.Yes:
                    self.deleteboxflag = True
                    self.bboxList.pop(self.curbboxindex)
                    self.update()
                else:
                    return

    # 单击鼠标触发事件
    # 获取鼠标事件的开始位置
    def mousePressEvent(self, event):
        # 将绘制标志设置为True
        self.flag = True
        self.deleteboxflag = False
        # 重新开始点击事件后,取消已选中的标注框
        self.curChoosedbbox = []
        self.x0 = event.pos().x()
        self.y0 = event.pos().y()

    # 鼠标移动事件
    # 绘制鼠标行进过程中的矩形框
    def mouseMoveEvent(self, event):
        if self.flag:
            self.x1RealTime = event.pos().x()
            self.y1RealTime = event.pos().y()
            self.update()

    # 鼠标释放事件
    def mouseReleaseEvent(self, event):
        # 将绘制标志设置为False
        self.flag = False
        self.x1 = event.pos().x()
        self.y1 = event.pos().y()
        # 这样就不用画出实时框了
        self.x1RealTime = self.x0
        self.y1RealTime = self.y0
        # 修正单击鼠标的保存事件bug,当开始坐标等于结束坐标时,或者为一条直线时,均不响应
        if self.x0 == self.x1 or self.y0 == self.y1:
            return
            # 将标注框的四个坐标轴存储到bboxList
        dialogChooseLabel = DialogChoooseLabelWin()
        if dialogChooseLabel.exec_():
            labelname = dialogChooseLabel.getValue()
            self.saveBBbox(self.x0, self.y0, self.x1, self.y1, labelname)
        event.ignore()

    # 绘制事件
    def paintEvent(self, event):
        super().paintEvent(event)
        painter = QPainter()
        # 增加绘制开始和结束时间
        painter.begin(self)
        # 遍历之前存储的标注框坐标列表
        for point in self.bboxList:
            rect = QRect(point[0], point[1], abs(point[0] - point[2]), abs(point[1] - point[3]))
            painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
            painter.drawRect(rect)
            painter.drawText(point[0], point[1], point[4])
        # 绘制当前标注框的举行
        # 构造矩形框的起始坐标和宽度、高度
        tempx0 = min(self.x0, self.x1RealTime)
        tempy0 = min(self.y0, self.y1RealTime)
        tempx1 = max(self.x0, self.x1RealTime)
        tempy1 = max(self.y0, self.y1RealTime)
        width = tempx1 - tempx0
        height = tempy1 - tempy0
        currect = QRect(tempx0, tempy0, width, height)
        # 构造QPainter,进行矩形框绘制
        painter.setPen(QPen(Qt.blue, 1, Qt.SolidLine))
        painter.drawRect(currect)

        # 判断是否有当前选中窗口,如果有,且未被删除,则高亮显示
        if self.curChoosedbbox != []:
            # 如果当前不是删除标志,则高亮显示
            # 否则就不再绘制该标注框
            if self.deleteboxflag == False:
                point = self.curChoosedbbox
                rect = QRect(point[0], point[1], abs(point[0] - point[2]), abs(point[1] - point[3]))
                painter.setPen(QPen(Qt.green, 4, Qt.SolidLine))
                painter.drawRect(rect)
                painter.drawText(point[0], point[1], point[4])

        painter.end()

    # 保存到bbox列表
    def saveBBbox(self, x0, y0, x1, y1, labelname):
        tempx0 = min(x0, x1)
        tempy0 = min(y0, y1)
        tempx1 = max(x0, x1)
        tempy1 = max(y0, y1)
        bbox = (tempx0, tempy0, tempx1, tempy1, labelname, self.labelindex)
        self.bboxList.append(bbox)
        self.labelindex += 1

二、窗口类和main函数未做调整

代码语言:javascript
复制
# 窗口类
class LabelV1(QWidget):
    def __init__(self):
        super(LabelV1, self).__init__()
        self.initUI()

    def initUI(self):
        self.resize(960, 540)
        self.move(100, 50)
        self.setWindowTitle('Label标注框4.0版本')
        # 加载重定义的label
        self.lbl = MyLabel(self)
        # 构造QPixmap,加载待标注图片
        img = QPixmap('010.png')
        # 在自定义label中显示QImage
        self.lbl.setPixmap(img)
        self.lbl.setCursor(Qt.CrossCursor)
        self.show()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    labelwin = LabelV1()
    sys.exit(app.exec())
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2023-07-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 python与大数据分析 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档