关于图像标注软件,业界已经有LabelImg、Labelme、VATIC、Label Studio、Prodigy、Datasaur等开源或商业的工具。
由于某种需要,本人需要开发一款数据标注工具,也尝试过阅读Labelme和LabelImg代码,但无奈水平有限放弃了,最后决定借鉴其标注界面和思想。
此外图像标注,之前试过simpleGUI,但交互性有点弱,决定用pyqt5重构一下,图像标注主要包括图像文件夹的选择,图像的预览,图像标注框选,图像标注Label选择,图像标注结果存储,甚至图像的放大缩小,子功能还是多的,关于图像的处理软件用QGraphicsView还是QLabel也有不同选择。
目前本人已经实现了四个版本:
第一个版本,最基本的图像标注,可以将标注框显示在图片上,这个版本在网上能见到的代码是最多的,也是最没什么难度的,参考了那么多代码,还是要感谢一下之前贡献的兄弟们。
第二个版本,最常见到的图像标注,多个标注框显示在图片上
第三个版本,实现了标注Label的选择,并且将结果保存下来
第四个版本,实现了基于当前位置双击后,被标注框的高亮显示和删除
第五个版本,对标注框结果进行各种类型的保存
这个图将以后作为标注的基准图片。
一、自定义一个QLabel
在QLabel中定义初始化、鼠标点击、鼠标移动、鼠标释放和图像绘制事件。
鼠标点击及按下意味着初始坐标
鼠标移动记录标注的动作,可以画也可以不画
鼠标释放记录标注框的终点
图像绘制事件中,主要交换了一下标注框的坐标,网上很多是错的,导致标注结果不对。
代码语言:javascript复制from PyQt5.QtWidgets import QWidget, QApplication, QLabel
from PyQt5.QtCore import QRect, Qt
from PyQt5.QtGui import QPixmap, QPainter, QPen
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.rect = QRect()
self.flag = False
# 单击鼠标触发事件
# 获取鼠标事件的开始位置
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.x1 = event.pos().x()
self.y1 = event.pos().y()
self.update()
# 鼠标释放事件
def mouseReleaseEvent(self, event):
# 将绘制标志设置为False
self.flag = False
# 绘制事件
def paintEvent(self, event):
super().paintEvent(event)
# 构造矩形框的起始坐标和宽度、高度
x0 = min(self.x0, self.x1)
y0 = min(self.y0, self.y1)
x1 = max(self.x0, self.x1)
y1 = max(self.y0, self.y1)
width = x1 - x0
height = y1 - y0
rect = QRect(x0, y0, width, height)
# 构造QPainter,进行矩形框绘制
painter = QPainter(self)
painter.setPen(QPen(Qt.red, 2, Qt.SolidLine))
painter.drawRect(rect)
二、实例化标注框,在一个主界面中显示标注框
代码语言: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标注框1.0版本')
# 加载重定义的label
self.lbl = MyLabel(self)
# 构造QPixmap,加载待标注图片
img = QPixmap('010.png')
# 在自定义label中显示QImage
self.lbl.setPixmap(img)
self.lbl.setCursor(Qt.CrossCursor)
self.show()
三、在一个main函数中,显示主窗口,其他功能暂时不需要
代码语言:javascript复制if __name__ == '__main__':
app = QApplication(sys.argv)
labelwin = LabelV1()
sys.exit(app.exec())
最后的标注成果
其他几个版本会陆续把代码和思想放出来,敬请关注!