From 0d6c0ff2b8cf409b8c2dedc029502c4d431536d8 Mon Sep 17 00:00:00 2001 From: Muhammed OZDOGAN Date: Wed, 1 Apr 2026 00:43:37 +0300 Subject: [PATCH] Remove difficult flag --- PPOCRLabel.py | 33 +++------------------- README.md | 4 ++- README_ch.md | 7 +++-- libs/shape.py | 3 -- resources/strings/strings-en.properties | 1 - resources/strings/strings-zh-CN.properties | 1 - 6 files changed, 12 insertions(+), 37 deletions(-) diff --git a/PPOCRLabel.py b/PPOCRLabel.py index 4516305..c99cf70 100644 --- a/PPOCRLabel.py +++ b/PPOCRLabel.py @@ -1229,8 +1229,6 @@ def get_str(str_id): self.fillColor = None self.zoom_level = 100 self.fit_window = False - # Add Chris - self.difficult = False # Fix the compatible issue for qt4 and qt5. Convert the QStringList to python list if settings.get(SETTING_RECENT_FILES): @@ -1265,8 +1263,6 @@ def get_str(str_id): settings.get(SETTING_FILL_COLOR, DEFAULT_FILL_COLOR) ) self.canvas.setDrawingColor(self.lineColor) - # Add chris - Shape.difficult = self.difficult # ADD: # Populate the File menu dynamically. @@ -1834,11 +1830,7 @@ def addLabel(self, shape): shape.paintIdx = self.displayIndexOption.isChecked() item = HashableQListWidgetItem(shape.label) - # current difficult checkbox is disable - # item.setFlags(item.flags() | Qt.ItemIsUserCheckable) - # item.setCheckState(Qt.Unchecked) if shape.difficult else item.setCheckState(Qt.Checked) - # Checked means difficult is False # item.setBackground(generateColorByText(shape.label)) self.itemsToShapes[item] = shape self.shapesToItems[shape] = item @@ -1891,7 +1883,7 @@ def remLabels(self, shapes): def loadLabels(self, shapes): s = [] shape_index = 0 - for label, points, line_color, key_cls, difficult in shapes: + for label, points, line_color, key_cls in shapes: shape = Shape( label=label, line_color=line_color, @@ -1905,7 +1897,6 @@ def loadLabels(self, shapes): self.setDirty() shape.addPoint(QPointF(x, y)) - shape.difficult = difficult shape.idx = shape_index shape_index += 1 # shape.locked = False @@ -1962,7 +1953,6 @@ def format_shape(s): line_color=s.line_color.getRgb(), fill_color=s.fill_color.getRgb(), points=[(int(p.x()), int(p.y())) for p in s.points], # QPonitF - difficult=s.difficult, key_cls=s.key_cls, ) # bool @@ -1976,7 +1966,7 @@ def format_shape(s): ] # Can add different annotation formats here for box in self.result_dic: - trans_dic = {"label": box[1][0], "points": box[0], "difficult": False} + trans_dic = {"label": box[1][0], "points": box[0]} if self.kie_mode: if len(box) == 3: trans_dic.update({"key_cls": box[2]}) @@ -1992,7 +1982,7 @@ def format_shape(s): trans_dict = { "transcription": box["label"], "points": box["points"], - "difficult": box["difficult"], + "difficult": False, } if self.kie_mode: trans_dict.update({"key_cls": box["key_cls"]}) @@ -2070,14 +2060,6 @@ def labelItemChanged(self, item): shape.label = item.text() # shape.line_color = generateColorByText(shape.label) self.setDirty() - elif not ((item.checkState() == Qt.Unchecked) ^ (not shape.difficult)): - shape.difficult = True if item.checkState() == Qt.Unchecked else False - self.setDirty() - else: # User probably changed item visibility - self.canvas.setShapeVisible( - shape, True - ) # item.checkState() == Qt.Checked - # self.actions.save.setEnabled(True) else: logger.warning( "enter labelItemChanged slot with unhashable item: %s %s", @@ -2425,7 +2407,6 @@ def showBoundingBoxFromPPlabel(self, filePath): [[s[0] * width, s[1] * height] for s in box["ratio"]], DEFAULT_LOCK_COLOR, key_cls, - box["difficult"], ) ) else: @@ -2435,7 +2416,6 @@ def showBoundingBoxFromPPlabel(self, filePath): [[s[0] * width, s[1] * height] for s in box["ratio"]], DEFAULT_LOCK_COLOR, key_cls, - box["difficult"], ) ) if img_idx in self.PPlabel.keys(): @@ -2447,7 +2427,6 @@ def showBoundingBoxFromPPlabel(self, filePath): box["points"], None, key_cls, - box.get("difficult", False), ) ) @@ -3333,7 +3312,6 @@ def TableRecognition(self): # If not, fix them. x, y, _ = self.canvas.snapPointToCanvas(x, y) shape.addPoint(QPointF(x, y)) - shape.difficult = False shape.idx = order_index order_index += 1 # shape.locked = False @@ -3703,8 +3681,6 @@ def saveRecResult(self): np.fromfile(img_path, dtype=np.uint8), cv2.IMREAD_COLOR ) for i, label in enumerate(self.PPlabel[idx]): - if label["difficult"]: - continue img_crop = get_rotate_crop_image( img, np.array(label["points"], np.float32) ) @@ -3818,7 +3794,6 @@ def format_shape(s): ratio=[ [int(p.x()) / width, int(p.y()) / height] for p in s.points ], # QPonitF - difficult=s.difficult, # bool key_cls=s.key_cls, # bool ) @@ -3833,7 +3808,7 @@ def format_shape(s): trans_dict = { "transcription": box["label"], "ratio": box["ratio"], - "difficult": box["difficult"], + "difficult": False, } if self.kie_mode: trans_dict.update({"key_cls": box["key_cls"]}) diff --git a/README.md b/README.md index de5d263..2f3b8ce 100644 --- a/README.md +++ b/README.md @@ -168,7 +168,7 @@ PPOCRLabel.exe --lang ch 6. Click 're-Recognition', model will rewrite ALL recognition results in ALL detection box[3]. -7. Single click the result in 'recognition result' list to manually change inaccurate recognition results. +7. Single click the result in 'recognition result' list to manually change inaccurate recognition results. **Note:** If the text is illegible or extremely blurry, it is recommended to change the label to `###`. The PaddleOCR training pipeline will treat these as "ignore" regions, ensuring they don't negatively impact your model's fine-tuning. 8. **Click "Check", the image status will switch to "√",then the program automatically jump to the next.** @@ -177,6 +177,8 @@ PPOCRLabel.exe --lang ch 10. Labeling result: the user can export the label result manually through the menu "File - Export Label", while the program will also export automatically if "File - Auto export Label Mode" is selected. The manually checked label will be stored in *Label.txt* under the opened picture folder. Click "File"-"Export Recognition Results" in the menu bar, the recognition training data of such pictures will be saved in the *crop_img* folder, and the recognition label will be saved in *rec_gt.txt*[4]. 11. Additional Feature Description + - **The "###" vs "*":** The core **PaddleOCR detection training pipeline** ignores boolean flags and specifically looks for the transcription string `###` or `*` to identify regions that should be ignored. For maximum compatibility with all fine-tuning stages (both Detection and Recognition), always use `###` for unreadable text. + - **The "difficult" flag:** You may notice a `difficult` field in the exported `Label.txt`. This is a legacy field from the original `labelImg` tool. In this version of PPOCRLabel, this field is **hardcoded to `False`** for all exported labels to ensure backward compatibility with third-party data pipelines and older versions of the application while preventing unintended data exclusion during training exports. - `File` -> `Re-recognition`: After checking, the newly annotated box content will automatically trigger the `Re-recognition` function of the current annotation box, eliminating the need to click the Re-identify button. This is suitable for scenarios where you do not want to use Automatic Annotation but prefer manual annotation, such as license plate recognition. In a single image with only one license plate, using Automatic Annotation would require deleting many additional recognized text boxes, which is less efficient than directly re-annotating. - `File` -> `Auto Save Unsaved changes`: By default, you need to press the `Check` button to complete the marking confirmation for the current box, which can be cumbersome. After checking, when switching to the next image (by pressing the shortcut key `D`), a prompt box asking to confirm whether to save unconfirmed markings will no longer appear. The current markings will be automatically saved and the next image will be switched, making it convenient for quick marking. - After selecting the bounding box, there are 5 shortcut keys available to individually control the movement of the four vertices of the bounding box, suitable for scenarios that require precise control over the positions of the bounding box vertices: diff --git a/README_ch.md b/README_ch.md index cfb3c4f..6190e05 100644 --- a/README_ch.md +++ b/README_ch.md @@ -155,11 +155,14 @@ PPOCRLabel.exe --lang ch 4. 手动标注:点击 “矩形标注”(推荐直接在英文模式下点击键盘中的 “W”),用户可对当前图片中模型未检出的部分进行手动绘制标记框。点击键盘Q,则使用四点标注模式(或点击“编辑” - “四点标注”),用户依次点击4个点后,双击左键表示标注完成。 5. 标记框绘制完成后,用户点击 “确认”,检测框会先被预分配一个 “待识别” 标签。 6. 重新识别:将图片中的所有检测画绘制/调整完成后,点击 “重新识别”,PP-OCR模型会对当前图片中的**所有检测框**重新识别[3]。 -7. 内容更改:单击识别结果,对不准确的识别结果进行手动更改。 +7. 内容更改:单击识别结果,对不准确的识别结果进行手动更改。**注意:** 如果文字无法辨认或非常模糊,建议将标签修改为 `###`。PaddleOCR 训练流程会将其视为“忽略”区域,避免其对模型微调产生负面影响。 + 8. **确认标记:点击 “确认”,图片状态切换为 “√”,跳转至下一张。** 9. 删除:点击 “删除图像”,图片将会被删除至回收站。 10. 导出结果:用户可以通过菜单中“文件-导出标记结果”手动导出,同时也可以点击“文件 - 自动导出标记结果”开启自动导出。手动确认过的标记将会被存放在所打开图片文件夹下的*Label.txt*中。在菜单栏点击 “文件” - "导出识别结果"后,会将此类图片的识别训练数据保存在*crop_img*文件夹下,识别标签保存在*rec_gt.txt*中[4]。 -11. 补充功能说明 +11. 其他功能说明 + - **“###” 与 “*” 的区别:** 核心的 **PaddleOCR 检测训练流程** 会忽略布尔标志,并专门查找转录字符串 `###` 或 `*` 来识别应忽略的区域。因此,为了最大限度地兼容所有微调阶段(检测和识别),对于无法辨认的文字,请始终使用 `###`。 + - **“difficult” 标志:** 您可能会在导出的 `Label.txt` 中注意到 `difficult` 字段。这是一个源自原始 `labelImg` 工具的遗留字段。在此版本的 PPOCRLabel 中,此字段已 **硬编码为 `False`**,以确保与第三方数据流水线和旧版本应用程序的后向兼容性,同时防止在训练导出期间意外排除数据。 - `文件` -> `自动重新识别` : 勾选后,对于新标注的框内容会自动触发当前标注框的重新识别功能,不需要再去点击`重新识别`按钮,适合各种原因不想使用`自动标注`只想手动标注的场景,例如车牌识别,一张图里只有一个车牌,如果使用`自动标注`,需要删除很多额外识别出来的文字框,不如直接重新标注 - `文件` -> `自动保存未提交变更` : 默认是按`确认`按钮完成当前框的标记确认,有点繁琐,勾选后,切换下一张图(按快捷键`D`)的时候,不再弹出提示框确认是否保存未确认的标记,自动保存当前标记并切换下一张图,方便快速标记 - 选中标记框后,5个可以控制标记框四个顶点单独移动的快捷键,适合需要精确控制标记框四个顶点位置的场景 diff --git a/libs/shape.py b/libs/shape.py index e32f1b2..5f7acc8 100644 --- a/libs/shape.py +++ b/libs/shape.py @@ -53,7 +53,6 @@ def __init__( self, label=None, line_color=None, - difficult=False, key_cls="None", paintLabel=False, paintIdx=False, @@ -64,7 +63,6 @@ def __init__( self.points = [] self.fill = False self.selected = False - self.difficult = difficult self.key_cls = key_cls self.paintLabel = paintLabel self.paintIdx = paintIdx @@ -268,7 +266,6 @@ def copy(self): shape.line_color = self.line_color if self.fill_color != Shape.fill_color: shape.fill_color = self.fill_color - shape.difficult = self.difficult shape.key_cls = self.key_cls return shape diff --git a/resources/strings/strings-en.properties b/resources/strings/strings-en.properties index 87627ab..f6df2aa 100644 --- a/resources/strings/strings-en.properties +++ b/resources/strings/strings-en.properties @@ -57,7 +57,6 @@ shapeFillColor=Shape Fill Color shapeFillColorDetail=Change the fill color for this specific shape showHide=Show/Hide Label Panel useDefaultLabel=Use default label -useDifficult=Difficult boxLabelText=Box Labels labels=Labels autoSaveMode=Auto Save mode diff --git a/resources/strings/strings-zh-CN.properties b/resources/strings/strings-zh-CN.properties index ef7dd63..a002e73 100644 --- a/resources/strings/strings-zh-CN.properties +++ b/resources/strings/strings-zh-CN.properties @@ -57,7 +57,6 @@ focusAndZoom=聚焦缩放 focusAndZoomDetail=聚焦并缩放至所选框 nextImg=下一张 useDefaultLabel=使用预设标签 -useDifficult=有难度的 boxLabelText=区块的标签 labels=标签 autoSaveMode=自动保存模式