From 502e1675e4acf606214f51f287011990f23f87f5 Mon Sep 17 00:00:00 2001 From: Sanjay Rijal <37138338+zovelsanj@users.noreply.github.com> Date: Sat, 18 May 2024 07:04:06 +0545 Subject: [PATCH] Error with pyclipper inhomogeneous expanded array (#12108) * pyclipper inhomogeneous expanded array solved For some images, `np.array(offset.Execute(distance))` can result in inhomogeneous part of the detection box list, which cannot be casted into numpy array directly. * corrected box reshape position - box reshape was mistakenly done at line 145 which is now correctly done at line 92 of `db_postprocess.py` - if box is empty then continue * reverted mistakenly changed line 147 - reverted mistakenly changed `box.array(box)` to `np.array(box)` * expanded array fix for `det_box_type=quad` * polygons padding For `--det_box_type = poly`, pad the detected polygon arrays if they have different shapes to ensure even shapes of polygon arrays * fix codestyle --------- Co-authored-by: Wang Xin --- ppocr/postprocess/db_postprocess.py | 11 ++++++++--- tools/infer/predict_det.py | 15 +++++++++++++++ 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/ppocr/postprocess/db_postprocess.py b/ppocr/postprocess/db_postprocess.py index cdd050d19..348be5e05 100755 --- a/ppocr/postprocess/db_postprocess.py +++ b/ppocr/postprocess/db_postprocess.py @@ -89,7 +89,9 @@ class DBPostProcess(object): continue else: continue - box = box.reshape(-1, 2) + box = np.array(box).reshape(-1, 2) + if len(box) == 0: + continue _, sside = self.get_mini_boxes(box.reshape((-1, 1, 2))) if sside < self.min_size + 2: @@ -138,7 +140,10 @@ class DBPostProcess(object): if self.box_thresh > score: continue - box = self.unclip(points, self.unclip_ratio).reshape(-1, 1, 2) + box = self.unclip(points, self.unclip_ratio) + if len(box) > 1: + continue + box = np.array(box).reshape(-1, 1, 2) box, sside = self.get_mini_boxes(box) if sside < self.min_size + 2: continue @@ -157,7 +162,7 @@ class DBPostProcess(object): distance = poly.area * unclip_ratio / poly.length offset = pyclipper.PyclipperOffset() offset.AddPath(box, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON) - expanded = np.array(offset.Execute(distance)) + expanded = offset.Execute(distance) return expanded def get_mini_boxes(self, contour): diff --git a/tools/infer/predict_det.py b/tools/infer/predict_det.py index 148010acc..a78f11087 100755 --- a/tools/infer/predict_det.py +++ b/tools/infer/predict_det.py @@ -179,6 +179,14 @@ class TextDetector(object): rect[3] = tmp[np.argmax(diff)] return rect + def pad_polygons(self, polygon, max_points): + padding_size = max_points - len(polygon) + if padding_size == 0: + return polygon + last_point = polygon[-1] + padding = np.repeat([last_point], padding_size, axis=0) + return np.vstack([polygon, padding]) + def clip_det_res(self, points, img_height, img_width): for pno in range(points.shape[0]): points[pno, 0] = int(min(max(points[pno, 0], 0), img_width - 1)) @@ -209,6 +217,13 @@ class TextDetector(object): box = np.array(box) box = self.clip_det_res(box, img_height, img_width) dt_boxes_new.append(box) + + if len(dt_boxes_new) > 0: + max_points = max(len(polygon) for polygon in dt_boxes_new) + dt_boxes_new = [ + self.pad_polygons(polygon, max_points) for polygon in dt_boxes_new + ] + dt_boxes = np.array(dt_boxes_new) return dt_boxes