From 3c6d551207f8eb5d0916404a7eca5e641887047d Mon Sep 17 00:00:00 2001 From: Leif <4603009@qq.com> Date: Fri, 18 Mar 2022 11:24:01 +0800 Subject: [PATCH] Support multipoint labeling Support multipoint labeling --- PPOCRLabel/PPOCRLabel.py | 40 ++++++++++++++++++++++++++++++++++++++- PPOCRLabel/README.md | 2 +- PPOCRLabel/README_ch.md | 2 +- PPOCRLabel/libs/canvas.py | 2 +- PPOCRLabel/libs/shape.py | 6 +++++- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/PPOCRLabel/PPOCRLabel.py b/PPOCRLabel/PPOCRLabel.py index 34c045e9..7d1df9d2 100644 --- a/PPOCRLabel/PPOCRLabel.py +++ b/PPOCRLabel/PPOCRLabel.py @@ -379,7 +379,7 @@ class MainWindow(QMainWindow): 'w', 'objects', getStr('crtBoxDetail'), enabled=False) delete = action(getStr('delBox'), self.deleteSelectedShape, - 'Alt+X', 'delete', getStr('delBoxDetail'), enabled=False) + 'backspace', 'delete', getStr('delBoxDetail'), enabled=False) copy = action(getStr('dupBox'), self.copySelectedShape, 'Ctrl+C', 'copy', getStr('dupBoxDetail'), @@ -1931,6 +1931,38 @@ class MainWindow(QMainWindow): owidth += itemwidget.width() self.iconlist.setMinimumWidth(owidth + 50) + def gen_quad_from_poly(self, poly): + """ + Generate min area quad from poly. + """ + point_num = poly.shape[0] + min_area_quad = np.zeros((4, 2), dtype=np.float32) + rect = cv2.minAreaRect(poly.astype( + np.int32)) # (center (x,y), (width, height), angle of rotation) + box = np.array(cv2.boxPoints(rect)) + + first_point_idx = 0 + min_dist = 1e4 + for i in range(4): + dist = np.linalg.norm(box[(i + 0) % 4] - poly[0]) + \ + np.linalg.norm(box[(i + 1) % 4] - poly[point_num // 2 - 1]) + \ + np.linalg.norm(box[(i + 2) % 4] - poly[point_num // 2]) + \ + np.linalg.norm(box[(i + 3) % 4] - poly[-1]) + if dist < min_dist: + min_dist = dist + first_point_idx = i + for i in range(4): + min_area_quad[i] = box[(first_point_idx + i) % 4] + + bbox_new = min_area_quad.tolist() + bbox = [] + + for box in bbox_new: + box = list(map(int, box)) + bbox.append(box) + + return bbox + def getImglabelidx(self, filePath): if platform.system() == 'Windows': spliter = '\\' @@ -1965,7 +1997,11 @@ class MainWindow(QMainWindow): rec_flag = 0 for shape in self.canvas.shapes: box = [[int(p.x()), int(p.y())] for p in shape.points] + + if len(box) > 4: + box = self.gen_quad_from_poly(np.array(box)) assert len(box) == 4 + img_crop = get_rotate_crop_image(img, np.array(box, np.float32)) if img_crop is None: msg = 'Can not recognise the detection box in ' + self.filePath + '. Please change manually' @@ -2014,6 +2050,8 @@ class MainWindow(QMainWindow): img = cv2.imread(self.filePath) for shape in self.canvas.selectedShapes: box = [[int(p.x()), int(p.y())] for p in shape.points] + if len(box) > 4: + box = self.gen_quad_from_poly(np.array(box)) assert len(box) == 4 img_crop = get_rotate_crop_image(img, np.array(box, np.float32)) if img_crop is None: diff --git a/PPOCRLabel/README.md b/PPOCRLabel/README.md index 4d25e670..9d5eea04 100644 --- a/PPOCRLabel/README.md +++ b/PPOCRLabel/README.md @@ -159,7 +159,7 @@ python PPOCRLabel.py --kie True # [KIE mode] for [detection + recognition + keyw | Ctrl + R | Re-recognize the selected box | | Ctrl + C | Copy and paste the selected box | | Ctrl + Left Mouse Button | Multi select the label box | -| Alt + X | Delete the selected box | +| Backspace | Delete the selected box | | Ctrl + V | Check image | | Ctrl + Shift + d | Delete image | | D | Next image | diff --git a/PPOCRLabel/README_ch.md b/PPOCRLabel/README_ch.md index 3f8dc4f0..a25871d9 100644 --- a/PPOCRLabel/README_ch.md +++ b/PPOCRLabel/README_ch.md @@ -148,7 +148,7 @@ python PPOCRLabel.py --lang ch --kie True # 启动 【KIE 模式】,用于打 | Ctrl + R | 重新识别所选标记 | | Ctrl + C | 复制并粘贴选中的标记框 | | Ctrl + 鼠标左键 | 多选标记框 | -| Alt + X | 删除所选框 | +| Backspace | 删除所选框 | | Ctrl + V | 确认本张图片标记 | | Ctrl + Shift + d | 删除本张图片 | | D | 下一张图片 | diff --git a/PPOCRLabel/libs/canvas.py b/PPOCRLabel/libs/canvas.py index 095fe5ab..6c1043da 100644 --- a/PPOCRLabel/libs/canvas.py +++ b/PPOCRLabel/libs/canvas.py @@ -263,7 +263,7 @@ class Canvas(QWidget): if self.current.isClosed(): # print('1111') self.finalise() - elif self.drawSquare: # 增加 + elif self.drawSquare: assert len(self.current.points) == 1 self.current.points = self.line.points self.finalise() diff --git a/PPOCRLabel/libs/shape.py b/PPOCRLabel/libs/shape.py index fc8ab5ec..18cc4a8e 100644 --- a/PPOCRLabel/libs/shape.py +++ b/PPOCRLabel/libs/shape.py @@ -57,6 +57,7 @@ class Shape(object): self.locked = False self.direction = 0 self.center = None + self.epsilon = 5 # same as canvas self._highlightIndex = None self._highlightMode = self.NEAR_VERTEX self._highlightSettings = { @@ -98,11 +99,14 @@ class Shape(object): return False def addPoint(self, point): - if self.reachMaxPoints(): + if self.reachMaxPoints() and self.closeEnough(self.points[0], point): self.close() else: self.points.append(point) + def closeEnough(self, p1, p2): + return distance(p1 - p2) < self.epsilon + def popPoint(self): if self.points: return self.points.pop() -- GitLab