Skip to content

Commit 24c3357

Browse files
authored
Merge pull request #55 from fastlabel/hotfix/fix-segmentation-bug
fix segmentation bug
2 parents d84ac1b + 6c2c68b commit 24c3357

File tree

4 files changed

+75
-15
lines changed

4 files changed

+75
-15
lines changed

fastlabel/__init__.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
import json
44
from typing import List
55
from logging import getLogger
6-
from PIL import Image, ImageDraw
6+
from PIL import Image
7+
import cv2
8+
import numpy as np
79

810
import xmltodict
911

@@ -653,35 +655,37 @@ def export_semantic_segmentation(self, tasks: list, output_dir: str = os.path.jo
653655

654656
def __export_index_color_image(self, task: list, output_dir: str, pallete: List[int], is_instance_segmentation: bool = True, classes: list = []) -> None:
655657
image = Image.new("RGB", (task["width"], task["height"]), 0)
656-
image = image.convert('P')
657-
image.putpalette(pallete)
658-
draw = ImageDraw.Draw(image)
658+
image = np.array(image)
659+
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
659660

660661
index = 1
661662
for annotation in task["annotations"]:
662663
color = index if is_instance_segmentation else classes.index(annotation["value"]) + 1
663664
if annotation["type"] == AnnotationType.segmentation.value:
664665
for region in annotation["points"]:
665666
for points in region:
666-
pillow_draw_points = self.__get_pillow_draw_points(points)
667-
draw.polygon(pillow_draw_points, fill=color)
667+
cv_draw_points = self.__get_cv_draw_points(points)
668+
cv2.fillPoly(image, [cv_draw_points], color, lineType=cv2.LINE_8, shift=0)
668669
# hollowd points are not supported
669670
break
670671
elif annotation["type"] == AnnotationType.polygon.value:
671-
pillow_draw_points = self.__get_pillow_draw_points(annotation["points"])
672-
draw.polygon(pillow_draw_points, fill=color)
672+
cv_draw_points = self.__get_cv_draw_points(annotation["points"])
673+
cv2.fillPoly(image, [cv_draw_points], color, lineType=cv2.LINE_8, shift=0)
673674
elif annotation["type"] == AnnotationType.bbox.value:
674-
pillow_draw_points = self.__get_pillow_draw_points(annotation["points"])
675-
draw.polygon(pillow_draw_points, fill=color)
675+
cv_draw_points = self.__get_cv_draw_points(annotation["points"])
676+
cv2.fillPoly(image, [cv_draw_points], color, lineType=cv2.LINE_8, shift=0)
676677
else:
677678
continue
678679
index += 1
679680

680681
image_path = os.path.join(output_dir, utils.get_basename(task["name"]) + ".png")
681682
os.makedirs(os.path.dirname(image_path), exist_ok=True)
683+
image = Image.fromarray(image)
684+
image = image.convert('P')
685+
image.putpalette(pallete)
682686
image.save(image_path)
683687

684-
def __get_pillow_draw_points(self, points: List[int]) -> List[int]:
688+
def __get_cv_draw_points(self, points: List[int]) -> List[int]:
685689
"""
686690
Convert points to pillow draw points. Diagonal points are not supported.
687691
"""
@@ -717,7 +721,11 @@ def __get_pillow_draw_points(self, points: List[int]) -> List[int]:
717721
for i in range(int(len(points) / 2)):
718722
new_points.append(x_points[i * 2])
719723
new_points.append(y_points[i * 2 + 1])
720-
return new_points
724+
725+
cv_points = []
726+
for i in range(int(len(new_points) / 2)):
727+
cv_points.append((new_points[i * 2], new_points[i * 2 + 1]))
728+
return np.array(cv_points)
721729

722730

723731
# Annotation

fastlabel/converters.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,14 +301,65 @@ def to_pixel_coordinates(tasks: list) -> list:
301301
]
302302
else:
303303
continue
304+
305+
# Remove duplicate points
306+
for task in tasks:
307+
for anno in task["annotations"]:
308+
if annotation["type"] == AnnotationType.segmentation.value:
309+
new_regions = []
310+
for region in anno["points"]:
311+
new_region = []
312+
for points in region:
313+
new_points = __remove_duplicated_coordinates(points)
314+
new_region.append(new_points)
315+
new_regions.append(new_region)
316+
anno["points"] = new_regions
317+
elif annotation["type"] == AnnotationType.polygon.value:
318+
new_points = __remove_duplicated_coordinates(annotation["points"])
319+
annotation["points"] = new_points
304320
return tasks
305321

322+
def __remove_duplicated_coordinates(points: List[int]) -> List[int]:
323+
"""
324+
Remove duplicated coordinates.
325+
"""
326+
if len(points) == 0:
327+
return []
328+
329+
new_points = []
330+
for i in range(int(len(points) / 2)):
331+
if i == 0:
332+
new_points.append(points[i*2])
333+
new_points.append(points[i*2 + 1])
334+
335+
if new_points[-2] == points[i*2] and new_points[-1] == points[i*2 + 1]:
336+
continue
337+
338+
if len(new_points) <= 2:
339+
new_points.append(points[i*2])
340+
new_points.append(points[i*2 + 1])
341+
else:
342+
if new_points[-4] == new_points[-2] and new_points[-2] == points[i*2]:
343+
new_points.pop()
344+
new_points.pop()
345+
new_points.append(points[i*2])
346+
new_points.append(points[i*2 + 1])
347+
elif new_points[-3] == new_points[-1] and new_points[-1] == points[i*2 + 1]:
348+
new_points.pop()
349+
new_points.pop()
350+
new_points.append(points[i*2])
351+
new_points.append(points[i*2 + 1])
352+
else:
353+
new_points.append(points[i*2])
354+
new_points.append(points[i*2 + 1])
355+
return new_points
356+
306357
def __get_pixel_coordinates(points: List[int or float]) -> List[int]:
307358
"""
308359
Remove diagonal coordinates and return pixel outline coordinates.
309360
"""
310361
if len(points) == 0:
311-
return
362+
return []
312363

313364
new_points = []
314365
new_points.append(int(points[0]))

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ requests==2.25.1
22
numpy==1.20.2
33
geojson==2.5.0
44
xmltodict==0.12.0
5-
Pillow==8.3.1
5+
Pillow==8.3.1
6+
opencv-python==4.5.3.56

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
setuptools.setup(
1010
name="fastlabel",
11-
version="0.9.8",
11+
version="0.9.9",
1212
author="eisuke-ueta",
1313
author_email="[email protected]",
1414
description="The official Python SDK for FastLabel API, the Data Platform for AI",

0 commit comments

Comments
 (0)