图片标记-图像标注版本3-多标注框+标注标签

这个图像标注版本在前面多标注框基础上图片标记,增加了标注标签的选择,同时修正了一下之前绘制最后一个标注框的显示问题,现在看起来更像一个标注软件了。

参照labelImg的样式定义了一个自定义Dialog窗口,在这个窗口中加载了标注标签列表文件,同时这个标签是要必须选择的,或者取消。

对多标注框的代码重新做了优化图片标记,一个是关于正在绘制的标注框的显示问题,如果标签取消,则不予绘制,如果选择了标签才绘制出来

图片标记-图像标注版本3-多标注框+标注标签

一、通过qt designer设计一个标签选择的自定义Dialog窗口

# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'ui_labelchoose.ui'## Created by: PyQt5 UI code generator 5.15.4## WARNING: Any manual changes made to this file will be lost when pyuic5 is# run again.  Do not edit this file unless you know what you are doing.from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_Dialog(object):    def setupUi(self, Dialog):        Dialog.setObjectName("Dialog")        Dialog.resize(285, 336)        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)        sizePolicy.setHorizontalStretch(0)        sizePolicy.setVerticalStretch(0)        sizePolicy.setHeightForWidth(Dialog.sizePolicy().hasHeightForWidth())        Dialog.setSizePolicy(sizePolicy)        Dialog.setMinimumSize(QtCore.QSize(285, 336))        Dialog.setMaximumSize(QtCore.QSize(285, 336))        self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)        self.buttonBox.setGeometry(QtCore.QRect(80, 39, 193, 28))        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)        self.buttonBox.setObjectName("buttonBox")        self.leditChoosedLabel = QtWidgets.QLineEdit(Dialog)        self.leditChoosedLabel.setGeometry(QtCore.QRect(11, 11, 261, 21))        self.leditChoosedLabel.setObjectName("leditChoosedLabel")        self.leditChoosedLabel.setEnabled(False)        self.lviewLabelList = QtWidgets.QListView(Dialog)        self.lviewLabelList.setGeometry(QtCore.QRect(10, 80, 261, 241))        self.lviewLabelList.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)        self.lviewLabelList.setObjectName("lviewLabelList")        self.retranslateUi(Dialog)        QtCore.QMetaObject.conn【88 个靠.谱项.目】ectSlotsByName(Dialog)    def retranslateUi(self, Dialog):        _translate = QtCore.QCoreApplication.translate        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

二、实现自定义Dialog的相关功能

一个是初始化过程中对标签列表文件的加载

一个是QListView的点击事件

一个是Dialog的返回值

最后一个是对OK按钮事件的校验,确保已经选择了标签

from PyQt5 import QtCore, QtGui, QtWidgetsfrom PyQt5.QtWidgets import QMainWindow, QApplication,  QDialog,QMessageBoxfrom PyQt5.QtCore import QStringListModelclass DialogChoooseLabelWin(QDialog, Ui_Dialog):    def __init__(self,parent=None):        # super(DialogChoooseLabelWin, self).__init__()        QDialog.__init__(self,parent)        self.setupUi(self)        self.labelList=[]        self.initLableList()        self.lviewLabelList.clicked.connect(self.clickedlist)        self.buttonBox.accepted.connect(self.validate)        self.buttonBox.rejected.connect(self.reject)    def initLableList(self):        with open('datalabellistbak.txt', 'r',encoding='utf-8') as f:            self.labelList=[line.strip() for line in f]        self.labelslm=QStringListModel()        self.labelslm.setStringList(self.labelList)        self.lviewLabelList.setModel(self.labelslm)    def clicked【88 个靠.谱.项.目】list(self, qModelIndex):        self.leditChoosedLabel.setText(self.labelList[qModelIndex.row()])    def getValue(self):        return self.leditChoosedLabel.text()    def validate(self):        if self.leditChoosedLabel.text()!='':            self.accept()if __name__ == "__main__":    import sys    app = QtWidgets.QApplication(sys.argv)    Dialog=DialogChoooseLabelWin()    print('dialogChooseLabel.exec_()=', Dialog.exec_())    print('dialogChooseLabel.getValue()=', Dialog.getValue())    sys.exit(app.exec_())

三、对原来的MyLabel进行重写,参见加粗字体部分

引入了一个实时坐标的概念

在鼠标移动事件中,不断根据鼠标位置进行实时绘制

在鼠标释放事件中,增加了一个对话框选择项,确认后将相关标注项加入到bboxlist中(bboxlist相对于2.0版本有所调整)

在绘制事件中,修正了对实时标注框的单独绘制

from PyQt5.QtWidgets import QWidget, QApplication, QLabelfrom PyQt5.QtCore import QRect, Qtfrom PyQt5.QtGui import QPixmap, QPainter, QPenfrom ui_labelchoose import DialogChoooseLabelWinimport 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=[]    # 单击鼠标触发事件    # 获取鼠标事件的开始位置    def mousePressEvent(self, event):        # 将绘制标志设置为True        self.flag = True        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  # 这样就不用画出实时框了        # 将标注框的四个坐标轴存储到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)        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.bboxList.append(bbox)

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

# 窗口类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标注框3.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())

———END———
限 时 特 惠: 【资 ;源 之.家.】mxyxt .com 每日持.续更新.可.实操.的副.业.项目,【微-信 】 qgz mt1, 【点击查看详情】


站 长 微 信: qgzmt1