这个图像标注版本在前面多标注框基础上图片标记,增加了标注标签的选择,同时修正了一下之前绘制最后一个标注框的显示问题,现在看起来更像一个标注软件了。
参照labelImg的样式定义了一个自定义Dialog窗口,在这个窗口中加载了标注标签列表文件,同时这个标签是要必须选择的,或者取消。
对多标注框的代码重新做了优化图片标记,一个是关于正在绘制的标注框的显示问题,如果标签取消,则不予绘制,如果选择了标签才绘制出来
一、通过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———
限 时 特 惠: 【萌 心云学 堂】每日持续更新海量各大内部创业教程, 点击查看详情
站 长 微 信: 929444
声明:
本站内容均转载于互联网,并不代表副业库立场!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理!
拒绝任何人以任何形式在本站发表与中华人民共和国法律相抵触的言论!
本站内容均转载于互联网,并不代表副业库立场!如若本站内容侵犯了原著者的合法权益,可联系我们进行处理!
拒绝任何人以任何形式在本站发表与中华人民共和国法律相抵触的言论!