Merge pull request #5560 from PeterH0323/peterh_kie_dygraph
【PPOCRLabel】: 5 Optimizations 🛃 and 3 BUG Fixed 🐛pull/5561/head
commit
53958638a1
|
@ -152,16 +152,6 @@ class MainWindow(QMainWindow):
|
|||
self.fileListWidget.setIconSize(QSize(25, 25))
|
||||
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.setLayout(filelistLayout)
|
||||
self.fileListName = getStr('fileList')
|
||||
|
@ -172,17 +162,30 @@ class MainWindow(QMainWindow):
|
|||
|
||||
# ================== Key List ==================
|
||||
if self.kie_mode:
|
||||
# self.keyList = QListWidget()
|
||||
self.keyList = UniqueLabelQListWidget()
|
||||
# self.keyList.itemSelectionChanged.connect(self.keyListSelectionChanged)
|
||||
# self.keyList.itemDoubleClicked.connect(self.editBox)
|
||||
# self.keyList.itemChanged.connect(self.keyListItemChanged)
|
||||
|
||||
# set key list height
|
||||
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.keyListDock = QDockWidget(self.keyListDockName, self)
|
||||
self.keyListDock.setWidget(self.keyList)
|
||||
self.keyListDock.setFeatures(QDockWidget.NoDockWidgetFeatures)
|
||||
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 ==================
|
||||
listLayout = QVBoxLayout()
|
||||
listLayout.setContentsMargins(0, 0, 0, 0)
|
||||
|
@ -431,8 +434,7 @@ class MainWindow(QMainWindow):
|
|||
# ================== New Actions ==================
|
||||
|
||||
edit = action(getStr('editLabel'), self.editLabel,
|
||||
'Ctrl+E', 'edit', getStr('editLabelDetail'),
|
||||
enabled=False)
|
||||
'Ctrl+E', 'edit', getStr('editLabelDetail'), enabled=False)
|
||||
|
||||
AutoRec = action(getStr('autoRecognition'), self.autoRecognition,
|
||||
'', 'Auto', getStr('autoRecognition'), enabled=False)
|
||||
|
@ -465,11 +467,10 @@ class MainWindow(QMainWindow):
|
|||
'Ctrl+Z', "undo", getStr("undo"), enabled=False)
|
||||
|
||||
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,
|
||||
None, "lock", getStr("lockBoxDetail"),
|
||||
enabled=False)
|
||||
None, "lock", getStr("lockBoxDetail"), enabled=False)
|
||||
|
||||
self.editButton.setDefaultAction(edit)
|
||||
self.newButton.setDefaultAction(create)
|
||||
|
@ -534,9 +535,10 @@ class MainWindow(QMainWindow):
|
|||
fileMenuActions=(opendir, open_dataset_dir, saveLabel, resetAll, quit),
|
||||
beginner=(), advanced=(),
|
||||
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=(
|
||||
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,
|
||||
delete, shapeLineColor, shapeFillColor),
|
||||
onLoadActive=(create, createMode, editMode),
|
||||
|
@ -1105,7 +1107,9 @@ class MainWindow(QMainWindow):
|
|||
shapes = [format_shape(shape) for shape in self.canvas.shapes if shape.line_color != DEFAULT_LOCK_COLOR]
|
||||
# Can add differrent annotation formats here
|
||||
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':
|
||||
continue
|
||||
shapes.append(trans_dic)
|
||||
|
@ -1113,8 +1117,10 @@ class MainWindow(QMainWindow):
|
|||
try:
|
||||
trans_dic = []
|
||||
for box in shapes:
|
||||
trans_dic.append({"transcription": box['label'], "points": box['points'],
|
||||
"difficult": box['difficult'], "key_cls": box['key_cls']})
|
||||
trans_dict = {"transcription": box['label'], "points": box['points'], "difficult": box['difficult']}
|
||||
if self.kie_mode:
|
||||
trans_dict.update({"key_cls": box['key_cls']})
|
||||
trans_dic.append(trans_dict)
|
||||
self.PPlabel[annotationFilePath] = trans_dic
|
||||
if mode == 'Auto':
|
||||
self.Cachelabel[annotationFilePath] = trans_dic
|
||||
|
@ -1424,15 +1430,17 @@ class MainWindow(QMainWindow):
|
|||
# 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
|
||||
for box in self.canvas.lockedShapes:
|
||||
key_cls = None if not self.kie_mode else box['key_cls']
|
||||
if self.canvas.isInTheSameImage:
|
||||
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:
|
||||
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():
|
||||
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.canvas.verified = False
|
||||
|
@ -1460,6 +1468,7 @@ class MainWindow(QMainWindow):
|
|||
def adjustScale(self, initial=False):
|
||||
value = self.scalers[self.FIT_WINDOW if initial else self.zoomMode]()
|
||||
self.zoomWidget.setValue(int(100 * value))
|
||||
self.imageSlider.setValue(self.zoomWidget.value()) # set zoom slider value
|
||||
|
||||
def scaleFitWindow(self):
|
||||
"""Figure out the size of the pixmap in order to fit the main widget."""
|
||||
|
@ -1600,7 +1609,6 @@ class MainWindow(QMainWindow):
|
|||
else:
|
||||
self.keyDialog.labelList.addItems(self.existed_key_cls_set)
|
||||
|
||||
|
||||
def importDirImages(self, dirpath, isDelete=False):
|
||||
if not self.mayContinue() or not dirpath:
|
||||
return
|
||||
|
@ -2200,13 +2208,22 @@ class MainWindow(QMainWindow):
|
|||
print('The program will automatically save once after confirming 5 images (default)')
|
||||
|
||||
def change_box_key(self):
|
||||
if not self.kie_mode:
|
||||
return
|
||||
key_text, _ = self.keyDialog.popUp(self.key_previous_text)
|
||||
if key_text is None:
|
||||
return
|
||||
self.key_previous_text = key_text
|
||||
for shape in self.canvas.selectedShapes:
|
||||
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.keyDialog.addLabelHistory(key_text)
|
||||
|
||||
def undoShapeEdit(self):
|
||||
self.canvas.restoreShape()
|
||||
|
@ -2250,9 +2267,10 @@ class MainWindow(QMainWindow):
|
|||
shapes = [format_shape(shape) for shape in self.canvas.selectedShapes]
|
||||
trans_dic = []
|
||||
for box in shapes:
|
||||
trans_dic.append({"transcription": box['label'], "ratio": box['ratio'],
|
||||
"difficult": box['difficult'],
|
||||
"key_cls": "None" if "key_cls" not in box else box["key_cls"]})
|
||||
trans_dict = {"transcription": box['label'], "ratio": box['ratio'], "difficult": box['difficult']}
|
||||
if self.kie_mode:
|
||||
trans_dict.update({"key_cls": box["key_cls"]})
|
||||
trans_dic.append(trans_dict)
|
||||
self.canvas.lockedShapes = trans_dic
|
||||
self.actions.save.setEnabled(True)
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ PPOCRLabel is a semi-automatic graphic annotation tool suitable for OCR field, w
|
|||
### Recent Update
|
||||
|
||||
- 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) )
|
||||
- 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:
|
||||
|
@ -156,6 +156,7 @@ python PPOCRLabel.py --kie True # [KIE mode] for [detection + recognition + keyw
|
|||
| X | Rotate the box anti-clockwise |
|
||||
| C | Rotate the box clockwise |
|
||||
| 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 + C | Copy and paste the selected box |
|
||||
| Ctrl + Left Mouse Button | Multi select the label box |
|
||||
|
|
|
@ -9,7 +9,7 @@ PPOCRLabel是一款适用于OCR领域的半自动化图形标注工具,内置P
|
|||
#### 近期更新
|
||||
|
||||
- 2022.02:(by [PeterH0323](https://github.com/peterh0323) )
|
||||
- 新增:KIE 功能,用于打【检测+识别+关键字提取】的标签
|
||||
- 新增:使用 `--kie` 进入 KIE 功能,用于打【检测+识别+关键字提取】的标签
|
||||
- 2022.01:(by [PeterH0323](https://github.com/peterh0323) )
|
||||
- 提升用户体验:新增文件与标记数目提示、优化交互、修复gpu使用等问题
|
||||
- 2021.11.17:
|
||||
|
@ -137,25 +137,26 @@ python PPOCRLabel.py --lang ch --kie True # 启动 【KIE 模式】,用于打
|
|||
|
||||
### 3.1 快捷键
|
||||
|
||||
| 快捷键 | 说明 |
|
||||
|------------------|----------------|
|
||||
| Ctrl + shift + R | 对当前图片的所有标记重新识别 |
|
||||
| W | 新建矩形框 |
|
||||
| Q | 新建四点框 |
|
||||
| X | 框逆时针旋转 |
|
||||
| C | 框顺时针旋转 |
|
||||
| Ctrl + E | 编辑所选框标签 |
|
||||
| Ctrl + R | 重新识别所选标记 |
|
||||
| Ctrl + C | 复制并粘贴选中的标记框 |
|
||||
| Ctrl + 鼠标左键 | 多选标记框 |
|
||||
| Alt + X | 删除所选框 |
|
||||
| Ctrl + V | 确认本张图片标记 |
|
||||
| Ctrl + Shift + d | 删除本张图片 |
|
||||
| D | 下一张图片 |
|
||||
| A | 上一张图片 |
|
||||
| Ctrl++ | 缩小 |
|
||||
| Ctrl-- | 放大 |
|
||||
| ↑→↓← | 移动标记框 |
|
||||
| 快捷键 | 说明 |
|
||||
|------------------|---------------------------------|
|
||||
| Ctrl + shift + R | 对当前图片的所有标记重新识别 |
|
||||
| W | 新建矩形框 |
|
||||
| Q | 新建四点框 |
|
||||
| X | 框逆时针旋转 |
|
||||
| C | 框顺时针旋转 |
|
||||
| Ctrl + E | 编辑所选框标签 |
|
||||
| Ctrl + X | `--kie` 模式下,修改 Box 的关键字种类 |
|
||||
| Ctrl + R | 重新识别所选标记 |
|
||||
| Ctrl + C | 复制并粘贴选中的标记框 |
|
||||
| Ctrl + 鼠标左键 | 多选标记框 |
|
||||
| Alt + X | 删除所选框 |
|
||||
| Ctrl + V | 确认本张图片标记 |
|
||||
| Ctrl + Shift + d | 删除本张图片 |
|
||||
| D | 下一张图片 |
|
||||
| A | 上一张图片 |
|
||||
| Ctrl++ | 缩小 |
|
||||
| Ctrl-- | 放大 |
|
||||
| ↑→↓← | 移动标记框 |
|
||||
|
||||
### 3.2 内置模型
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ class Canvas(QWidget):
|
|||
# Give up if both fail.
|
||||
for shape in shapes:
|
||||
point = shape[0]
|
||||
offset = QPointF(2.0, 2.0)
|
||||
offset = QPointF(5.0, 5.0)
|
||||
self.calculateOffsets(shape, point)
|
||||
self.prevPoint = point
|
||||
if not self.boundedMoveShape(shape, point - offset):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- encoding: utf-8 -*-
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5 import QtWidgets
|
||||
|
||||
|
||||
|
@ -40,6 +40,7 @@ class UniqueLabelQListWidget(EscapableQListWidget):
|
|||
qlabel.setText('<font color="#{:02x}{:02x}{:02x}">●</font> {} '.format(*color, label))
|
||||
qlabel.setAlignment(Qt.AlignBottom)
|
||||
|
||||
item.setSizeHint(qlabel.sizeHint())
|
||||
# item.setSizeHint(qlabel.sizeHint())
|
||||
item.setSizeHint(QSize(25, 25))
|
||||
|
||||
self.setItemWidget(item, qlabel)
|
||||
|
|
Loading…
Reference in New Issue