未验证 提交 53958638 编写于 作者: E Evezerest 提交者: GitHub

Merge pull request #5560 from PeterH0323/peterh_kie_dygraph

【PPOCRLabel】: 5 Optimizations 🛃  and 3 BUG Fixed 🐛 
...@@ -152,16 +152,6 @@ class MainWindow(QMainWindow): ...@@ -152,16 +152,6 @@ class MainWindow(QMainWindow):
self.fileListWidget.setIconSize(QSize(25, 25)) self.fileListWidget.setIconSize(QSize(25, 25))
filelistLayout.addWidget(self.fileListWidget) filelistLayout.addWidget(self.fileListWidget)
self.AutoRecognition = QToolButton()
self.AutoRecognition.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.AutoRecognition.setIcon(newIcon('Auto'))
autoRecLayout = QHBoxLayout()
autoRecLayout.setContentsMargins(0, 0, 0, 0)
autoRecLayout.addWidget(self.AutoRecognition)
autoRecContainer = QWidget()
autoRecContainer.setLayout(autoRecLayout)
filelistLayout.addWidget(autoRecContainer)
fileListContainer = QWidget() fileListContainer = QWidget()
fileListContainer.setLayout(filelistLayout) fileListContainer.setLayout(filelistLayout)
self.fileListName = getStr('fileList') self.fileListName = getStr('fileList')
...@@ -172,17 +162,30 @@ class MainWindow(QMainWindow): ...@@ -172,17 +162,30 @@ class MainWindow(QMainWindow):
# ================== Key List ================== # ================== Key List ==================
if self.kie_mode: if self.kie_mode:
# self.keyList = QListWidget()
self.keyList = UniqueLabelQListWidget() self.keyList = UniqueLabelQListWidget()
# self.keyList.itemSelectionChanged.connect(self.keyListSelectionChanged)
# self.keyList.itemDoubleClicked.connect(self.editBox) # set key list height
# self.keyList.itemChanged.connect(self.keyListItemChanged) key_list_height = int(QApplication.desktop().height() // 4)
if key_list_height < 50:
key_list_height = 50
self.keyList.setMaximumHeight(key_list_height)
self.keyListDockName = getStr('keyListTitle') self.keyListDockName = getStr('keyListTitle')
self.keyListDock = QDockWidget(self.keyListDockName, self) self.keyListDock = QDockWidget(self.keyListDockName, self)
self.keyListDock.setWidget(self.keyList) self.keyListDock.setWidget(self.keyList)
self.keyListDock.setFeatures(QDockWidget.NoDockWidgetFeatures) self.keyListDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
filelistLayout.addWidget(self.keyListDock) filelistLayout.addWidget(self.keyListDock)
self.AutoRecognition = QToolButton()
self.AutoRecognition.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
self.AutoRecognition.setIcon(newIcon('Auto'))
autoRecLayout = QHBoxLayout()
autoRecLayout.setContentsMargins(0, 0, 0, 0)
autoRecLayout.addWidget(self.AutoRecognition)
autoRecContainer = QWidget()
autoRecContainer.setLayout(autoRecLayout)
filelistLayout.addWidget(autoRecContainer)
# ================== Right Area ================== # ================== Right Area ==================
listLayout = QVBoxLayout() listLayout = QVBoxLayout()
listLayout.setContentsMargins(0, 0, 0, 0) listLayout.setContentsMargins(0, 0, 0, 0)
...@@ -431,8 +434,7 @@ class MainWindow(QMainWindow): ...@@ -431,8 +434,7 @@ class MainWindow(QMainWindow):
# ================== New Actions ================== # ================== New Actions ==================
edit = action(getStr('editLabel'), self.editLabel, edit = action(getStr('editLabel'), self.editLabel,
'Ctrl+E', 'edit', getStr('editLabelDetail'), 'Ctrl+E', 'edit', getStr('editLabelDetail'), enabled=False)
enabled=False)
AutoRec = action(getStr('autoRecognition'), self.autoRecognition, AutoRec = action(getStr('autoRecognition'), self.autoRecognition,
'', 'Auto', getStr('autoRecognition'), enabled=False) '', 'Auto', getStr('autoRecognition'), enabled=False)
...@@ -465,11 +467,10 @@ class MainWindow(QMainWindow): ...@@ -465,11 +467,10 @@ class MainWindow(QMainWindow):
'Ctrl+Z', "undo", getStr("undo"), enabled=False) 'Ctrl+Z', "undo", getStr("undo"), enabled=False)
change_cls = action(getStr("keyChange"), self.change_box_key, change_cls = action(getStr("keyChange"), self.change_box_key,
'Ctrl+B', "edit", getStr("keyChange"), enabled=False) 'Ctrl+X', "edit", getStr("keyChange"), enabled=False)
lock = action(getStr("lockBox"), self.lockSelectedShape, lock = action(getStr("lockBox"), self.lockSelectedShape,
None, "lock", getStr("lockBoxDetail"), None, "lock", getStr("lockBoxDetail"), enabled=False)
enabled=False)
self.editButton.setDefaultAction(edit) self.editButton.setDefaultAction(edit)
self.newButton.setDefaultAction(create) self.newButton.setDefaultAction(create)
...@@ -534,9 +535,10 @@ class MainWindow(QMainWindow): ...@@ -534,9 +535,10 @@ class MainWindow(QMainWindow):
fileMenuActions=(opendir, open_dataset_dir, saveLabel, resetAll, quit), fileMenuActions=(opendir, open_dataset_dir, saveLabel, resetAll, quit),
beginner=(), advanced=(), beginner=(), advanced=(),
editMenu=(createpoly, edit, copy, delete, singleRere, None, undo, undoLastPoint, editMenu=(createpoly, edit, copy, delete, singleRere, None, undo, undoLastPoint,
None, rotateLeft, rotateRight, None, color1, self.drawSquaresOption, lock), None, rotateLeft, rotateRight, None, color1, self.drawSquaresOption, lock,
None, change_cls),
beginnerContext=( beginnerContext=(
create, edit, copy, delete, singleRere, rotateLeft, rotateRight, lock, change_cls), create, edit, copy, delete, singleRere, rotateLeft, rotateRight, lock, change_cls),
advancedContext=(createMode, editMode, edit, copy, advancedContext=(createMode, editMode, edit, copy,
delete, shapeLineColor, shapeFillColor), delete, shapeLineColor, shapeFillColor),
onLoadActive=(create, createMode, editMode), onLoadActive=(create, createMode, editMode),
...@@ -1105,7 +1107,9 @@ class MainWindow(QMainWindow): ...@@ -1105,7 +1107,9 @@ class MainWindow(QMainWindow):
shapes = [format_shape(shape) for shape in self.canvas.shapes if shape.line_color != DEFAULT_LOCK_COLOR] shapes = [format_shape(shape) for shape in self.canvas.shapes if shape.line_color != DEFAULT_LOCK_COLOR]
# Can add differrent annotation formats here # Can add differrent annotation formats here
for box in self.result_dic: for box in self.result_dic:
trans_dic = {"label": box[1][0], "points": box[0], "difficult": False, "key_cls": "None"} trans_dic = {"label": box[1][0], "points": box[0], "difficult": False}
if self.kie_mode:
trans_dic.update({"key_cls": "None"})
if trans_dic["label"] == "" and mode == 'Auto': if trans_dic["label"] == "" and mode == 'Auto':
continue continue
shapes.append(trans_dic) shapes.append(trans_dic)
...@@ -1113,8 +1117,10 @@ class MainWindow(QMainWindow): ...@@ -1113,8 +1117,10 @@ class MainWindow(QMainWindow):
try: try:
trans_dic = [] trans_dic = []
for box in shapes: for box in shapes:
trans_dic.append({"transcription": box['label'], "points": box['points'], trans_dict = {"transcription": box['label'], "points": box['points'], "difficult": box['difficult']}
"difficult": box['difficult'], "key_cls": box['key_cls']}) if self.kie_mode:
trans_dict.update({"key_cls": box['key_cls']})
trans_dic.append(trans_dict)
self.PPlabel[annotationFilePath] = trans_dic self.PPlabel[annotationFilePath] = trans_dic
if mode == 'Auto': if mode == 'Auto':
self.Cachelabel[annotationFilePath] = trans_dic self.Cachelabel[annotationFilePath] = trans_dic
...@@ -1424,15 +1430,17 @@ class MainWindow(QMainWindow): ...@@ -1424,15 +1430,17 @@ class MainWindow(QMainWindow):
# box['ratio'] of the shapes saved in lockedShapes contains the ratio of the # box['ratio'] of the shapes saved in lockedShapes contains the ratio of the
# four corner coordinates of the shapes to the height and width of the image # four corner coordinates of the shapes to the height and width of the image
for box in self.canvas.lockedShapes: for box in self.canvas.lockedShapes:
key_cls = None if not self.kie_mode else box['key_cls']
if self.canvas.isInTheSameImage: if self.canvas.isInTheSameImage:
shapes.append((box['transcription'], [[s[0] * width, s[1] * height] for s in box['ratio']], shapes.append((box['transcription'], [[s[0] * width, s[1] * height] for s in box['ratio']],
DEFAULT_LOCK_COLOR, box['key_cls'], box['difficult'])) DEFAULT_LOCK_COLOR, key_cls, box['difficult']))
else: else:
shapes.append(('锁定框:待检测', [[s[0] * width, s[1] * height] for s in box['ratio']], shapes.append(('锁定框:待检测', [[s[0] * width, s[1] * height] for s in box['ratio']],
DEFAULT_LOCK_COLOR, box['key_cls'], box['difficult'])) DEFAULT_LOCK_COLOR, key_cls, box['difficult']))
if imgidx in self.PPlabel.keys(): if imgidx in self.PPlabel.keys():
for box in self.PPlabel[imgidx]: for box in self.PPlabel[imgidx]:
shapes.append((box['transcription'], box['points'], None, box['key_cls'], box['difficult'])) key_cls = None if not self.kie_mode else box['key_cls']
shapes.append((box['transcription'], box['points'], None, key_cls, box['difficult']))
self.loadLabels(shapes) self.loadLabels(shapes)
self.canvas.verified = False self.canvas.verified = False
...@@ -1460,6 +1468,7 @@ class MainWindow(QMainWindow): ...@@ -1460,6 +1468,7 @@ class MainWindow(QMainWindow):
def adjustScale(self, initial=False): def adjustScale(self, initial=False):
value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]() value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]()
self.zoomWidget.setValue(int(100 * value)) self.zoomWidget.setValue(int(100 * value))
self.imageSlider.setValue(self.zoomWidget.value()) # set zoom slider value
def scaleFitWindow(self): def scaleFitWindow(self):
"""Figure out the size of the pixmap in order to fit the main widget.""" """Figure out the size of the pixmap in order to fit the main widget."""
...@@ -1600,7 +1609,6 @@ class MainWindow(QMainWindow): ...@@ -1600,7 +1609,6 @@ class MainWindow(QMainWindow):
else: else:
self.keyDialog.labelList.addItems(self.existed_key_cls_set) self.keyDialog.labelList.addItems(self.existed_key_cls_set)
def importDirImages(self, dirpath, isDelete=False): def importDirImages(self, dirpath, isDelete=False):
if not self.mayContinue() or not dirpath: if not self.mayContinue() or not dirpath:
return return
...@@ -2200,13 +2208,22 @@ class MainWindow(QMainWindow): ...@@ -2200,13 +2208,22 @@ class MainWindow(QMainWindow):
print('The program will automatically save once after confirming 5 images (default)') print('The program will automatically save once after confirming 5 images (default)')
def change_box_key(self): def change_box_key(self):
if not self.kie_mode:
return
key_text, _ = self.keyDialog.popUp(self.key_previous_text) key_text, _ = self.keyDialog.popUp(self.key_previous_text)
if key_text is None: if key_text is None:
return return
self.key_previous_text = key_text self.key_previous_text = key_text
for shape in self.canvas.selectedShapes: for shape in self.canvas.selectedShapes:
shape.key_cls = key_text shape.key_cls = key_text
if not self.keyList.findItemsByLabel(key_text):
item = self.keyList.createItemFromLabel(key_text)
self.keyList.addItem(item)
rgb = self._get_rgb_by_label(key_text, self.kie_mode)
self.keyList.setItemLabel(item, key_text, rgb)
self._update_shape_color(shape) self._update_shape_color(shape)
self.keyDialog.addLabelHistory(key_text)
def undoShapeEdit(self): def undoShapeEdit(self):
self.canvas.restoreShape() self.canvas.restoreShape()
...@@ -2250,9 +2267,10 @@ class MainWindow(QMainWindow): ...@@ -2250,9 +2267,10 @@ class MainWindow(QMainWindow):
shapes = [format_shape(shape) for shape in self.canvas.selectedShapes] shapes = [format_shape(shape) for shape in self.canvas.selectedShapes]
trans_dic = [] trans_dic = []
for box in shapes: for box in shapes:
trans_dic.append({"transcription": box['label'], "ratio": box['ratio'], trans_dict = {"transcription": box['label'], "ratio": box['ratio'], "difficult": box['difficult']}
"difficult": box['difficult'], if self.kie_mode:
"key_cls": "None" if "key_cls" not in box else box["key_cls"]}) trans_dict.update({"key_cls": box["key_cls"]})
trans_dic.append(trans_dict)
self.canvas.lockedShapes = trans_dic self.canvas.lockedShapes = trans_dic
self.actions.save.setEnabled(True) self.actions.save.setEnabled(True)
......
...@@ -9,7 +9,7 @@ PPOCRLabel is a semi-automatic graphic annotation tool suitable for OCR field, w ...@@ -9,7 +9,7 @@ PPOCRLabel is a semi-automatic graphic annotation tool suitable for OCR field, w
### Recent Update ### Recent Update
- 2022.02:(by [PeterH0323](https://github.com/peterh0323) - 2022.02:(by [PeterH0323](https://github.com/peterh0323)
- Added KIE mode, for [detection + identification + keyword extraction] labeling. - Add KIE Mode by using `--kie`, for [detection + identification + keyword extraction] labeling.
- 2022.01:(by [PeterH0323](https://github.com/peterh0323) - 2022.01:(by [PeterH0323](https://github.com/peterh0323)
- Improve user experience: prompt for the number of files and labels, optimize interaction, and fix bugs such as only use CPU when inference - Improve user experience: prompt for the number of files and labels, optimize interaction, and fix bugs such as only use CPU when inference
- 2021.11.17: - 2021.11.17:
...@@ -156,6 +156,7 @@ python PPOCRLabel.py --kie True # [KIE mode] for [detection + recognition + keyw ...@@ -156,6 +156,7 @@ python PPOCRLabel.py --kie True # [KIE mode] for [detection + recognition + keyw
| X | Rotate the box anti-clockwise | | X | Rotate the box anti-clockwise |
| C | Rotate the box clockwise | | C | Rotate the box clockwise |
| Ctrl + E | Edit label of the selected box | | Ctrl + E | Edit label of the selected box |
| Ctrl + X | Change key class of the box when enable `--kie` |
| Ctrl + R | Re-recognize the selected box | | Ctrl + R | Re-recognize the selected box |
| Ctrl + C | Copy and paste the selected box | | Ctrl + C | Copy and paste the selected box |
| Ctrl + Left Mouse Button | Multi select the label box | | Ctrl + Left Mouse Button | Multi select the label box |
......
...@@ -9,7 +9,7 @@ PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置P ...@@ -9,7 +9,7 @@ PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置P
#### 近期更新 #### 近期更新
- 2022.02:(by [PeterH0323](https://github.com/peterh0323) - 2022.02:(by [PeterH0323](https://github.com/peterh0323)
- 新增:KIE 功能,用于打【检测+识别+关键字提取】的标签 - 新增:使用 `--kie` 进入 KIE 功能,用于打【检测+识别+关键字提取】的标签
- 2022.01:(by [PeterH0323](https://github.com/peterh0323) - 2022.01:(by [PeterH0323](https://github.com/peterh0323)
- 提升用户体验:新增文件与标记数目提示、优化交互、修复gpu使用等问题 - 提升用户体验:新增文件与标记数目提示、优化交互、修复gpu使用等问题
- 2021.11.17: - 2021.11.17:
...@@ -137,25 +137,26 @@ python PPOCRLabel.py --lang ch --kie True # 启动 【KIE 模式】,用于打 ...@@ -137,25 +137,26 @@ python PPOCRLabel.py --lang ch --kie True # 启动 【KIE 模式】,用于打
### 3.1 快捷键 ### 3.1 快捷键
| 快捷键 | 说明 | | 快捷键 | 说明 |
|------------------|----------------| |------------------|---------------------------------|
| Ctrl + shift + R | 对当前图片的所有标记重新识别 | | Ctrl + shift + R | 对当前图片的所有标记重新识别 |
| W | 新建矩形框 | | W | 新建矩形框 |
| Q | 新建四点框 | | Q | 新建四点框 |
| X | 框逆时针旋转 | | X | 框逆时针旋转 |
| C | 框顺时针旋转 | | C | 框顺时针旋转 |
| Ctrl + E | 编辑所选框标签 | | Ctrl + E | 编辑所选框标签 |
| Ctrl + R | 重新识别所选标记 | | Ctrl + X | `--kie` 模式下,修改 Box 的关键字种类 |
| Ctrl + C | 复制并粘贴选中的标记框 | | Ctrl + R | 重新识别所选标记 |
| Ctrl + 鼠标左键 | 多选标记框 | | Ctrl + C | 复制并粘贴选中的标记框 |
| Alt + X | 删除所选框 | | Ctrl + 鼠标左键 | 多选标记框 |
| Ctrl + V | 确认本张图片标记 | | Alt + X | 删除所选框 |
| Ctrl + Shift + d | 删除本张图片 | | Ctrl + V | 确认本张图片标记 |
| D | 下一张图片 | | Ctrl + Shift + d | 删除本张图片 |
| A | 上一张图片 | | D | 下一张图片 |
| Ctrl++ | 缩小 | | A | 上一张图片 |
| Ctrl-- | 放大 | | Ctrl++ | 缩小 |
| ↑→↓← | 移动标记框 | | Ctrl-- | 放大 |
| ↑→↓← | 移动标记框 |
### 3.2 内置模型 ### 3.2 内置模型
......
...@@ -546,7 +546,7 @@ class Canvas(QWidget): ...@@ -546,7 +546,7 @@ class Canvas(QWidget):
# Give up if both fail. # Give up if both fail.
for shape in shapes: for shape in shapes:
point = shape[0] point = shape[0]
offset = QPointF(2.0, 2.0) offset = QPointF(5.0, 5.0)
self.calculateOffsets(shape, point) self.calculateOffsets(shape, point)
self.prevPoint = point self.prevPoint = point
if not self.boundedMoveShape(shape, point - offset): if not self.boundedMoveShape(shape, point - offset):
......
# -*- encoding: utf-8 -*- # -*- encoding: utf-8 -*-
from PyQt5.QtCore import Qt from PyQt5.QtCore import Qt, QSize
from PyQt5 import QtWidgets from PyQt5 import QtWidgets
...@@ -40,6 +40,7 @@ class UniqueLabelQListWidget(EscapableQListWidget): ...@@ -40,6 +40,7 @@ class UniqueLabelQListWidget(EscapableQListWidget):
qlabel.setText('<font color="#{:02x}{:02x}{:02x}">●</font> {} '.format(*color, label)) qlabel.setText('<font color="#{:02x}{:02x}{:02x}">●</font> {} '.format(*color, label))
qlabel.setAlignment(Qt.AlignBottom) qlabel.setAlignment(Qt.AlignBottom)
item.setSizeHint(qlabel.sizeHint()) # item.setSizeHint(qlabel.sizeHint())
item.setSizeHint(QSize(25, 25))
self.setItemWidget(item, qlabel) self.setItemWidget(item, qlabel)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册