From a0aa9886ba10e35a6c66da42310f18ae9c6145f9 Mon Sep 17 00:00:00 2001 From: daichi Date: Fri, 26 Nov 2021 21:15:20 +0900 Subject: [PATCH 1/2] fix to clockwise check and hollow points export for index color --- fastlabel/__init__.py | 25 ++++++++++++++++++++++--- fastlabel/utils.py | 25 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/fastlabel/__init__.py b/fastlabel/__init__.py index 4732e0f..728adb1 100644 --- a/fastlabel/__init__.py +++ b/fastlabel/__init__.py @@ -1142,24 +1142,39 @@ def __export_index_color_image(self, task: list, output_dir: str, pallete: List[ image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) index = 1 + # In case segmentation, to avoid hollowed points overwrite other segmentation in them, segmentation rendering process is different from other annotation type + seg_mask_images = [] for annotation in task["annotations"]: color = index if is_instance_segmentation else classes.index( annotation["value"]) + 1 if annotation["type"] == AnnotationType.segmentation.value: + # Create each annotation's masks and merge them finally + seg_mask_ground = Image.new( + "RGB", (task["width"], task["height"]), 0) + seg_mask_image = np.array(seg_mask_ground) + seg_mask_image = cv2.cvtColor(seg_mask_image, cv2.COLOR_BGR2GRAY) + for region in annotation["points"]: count = 0 for points in region: if count == 0: - cv_draw_points = self.__get_cv_draw_points(points) + cv_draw_points = [] + if utils.is_clockwise(points): + cv_draw_points = self.__get_cv_draw_points( + points) + else: + cv_draw_points = self.__get_cv_draw_points( + utils.reverse_points(points)) cv2.fillPoly( - image, [cv_draw_points], color, lineType=cv2.LINE_8, shift=0) + seg_mask_image, [cv_draw_points], color, lineType=cv2.LINE_8, shift=0) else: # Reverse hollow points for opencv because this points are counter clockwise cv_draw_points = self.__get_cv_draw_points( utils.reverse_points(points)) cv2.fillPoly( - image, [cv_draw_points], 0, lineType=cv2.LINE_8, shift=0) + seg_mask_image, [cv_draw_points], 0, lineType=cv2.LINE_8, shift=0) count += 1 + seg_mask_images.append(seg_mask_image) elif annotation["type"] == AnnotationType.polygon.value: cv_draw_points = self.__get_cv_draw_points( annotation["points"]) @@ -1174,6 +1189,10 @@ def __export_index_color_image(self, task: list, output_dir: str, pallete: List[ continue index += 1 + # For segmentation, merge each mask images + for seg_mask_image in seg_mask_images: + image = image | seg_mask_image + image_path = os.path.join( output_dir, utils.get_basename(task["name"]) + ".png") os.makedirs(os.path.dirname(image_path), exist_ok=True) diff --git a/fastlabel/utils.py b/fastlabel/utils.py index 605e9f2..1d209cf 100644 --- a/fastlabel/utils.py +++ b/fastlabel/utils.py @@ -1,5 +1,7 @@ import os import base64 +import numpy as np +import geojson from typing import List @@ -41,3 +43,26 @@ def reverse_points(points: List[int]) -> List[int]: reversed_points.insert( 0, points[index]) return reversed_points + +def is_clockwise(points: list) -> bool: + """ + points: [x1, y1, x2, y2, x3, y3, ... xn, yn] + Sum over the edges, (x2 − x1)(y2 + y1). + If the result is positive the curve is clockwise, if it's negative the curve is counter-clockwise. + + The above is assumes a normal Cartesian coordinate system. + HTML5 canvas, use an inverted Y-axis. + Therefore If the area is negative, the curve is clockwise. + """ + points_splitted = [points[idx:idx + 2] + for idx in range(0, len(points), 2)] + polygon_geo = geojson.Polygon(points_splitted) + coords = np.array(list(geojson.utils.coords(polygon_geo))) + xs, ys = map(list, zip(*coords)) + xs.append(xs[0]) + ys.append(ys[0]) + sum_edges = sum((xs[i] - xs[i - 1]) * (ys[i] + ys[i - 1]) for i in range(1, len(points_splitted))) / 2.0 + + if sum_edges < 0: + return True + return False From 841c61653d7d6834a1ca561e8160eee4de6b4547 Mon Sep 17 00:00:00 2001 From: daichi Date: Fri, 26 Nov 2021 21:53:52 +0900 Subject: [PATCH 2/2] add setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 6ed4a2a..e9c2523 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ setuptools.setup( name="fastlabel", - version="0.11.8", + version="0.11.9", author="eisuke-ueta", author_email="eisuke.ueta@fastlabel.ai", description="The official Python SDK for FastLabel API, the Data Platform for AI",