@@ -529,7 +529,8 @@ def create_video_classification_task(
529529 """
530530 endpoint = "tasks/video/classification"
531531 if not utils .is_video_supported_ext (file_path ):
532- raise FastLabelInvalidException ("Supported extensions are mp4." , 422 )
532+ raise FastLabelInvalidException (
533+ "Supported extensions are mp4." , 422 )
533534 file = utils .base64_encode (file_path )
534535 payload = {"project" : project , "name" : name , "file" : file }
535536 if status :
@@ -651,14 +652,17 @@ def export_coco(self, tasks: list, output_dir: str = os.path.join("output", "coc
651652 with open (file_path , 'w' ) as f :
652653 json .dump (coco , f , indent = 4 , ensure_ascii = False )
653654
654- def export_yolo (self , tasks : list , output_dir : str = os .path .join ("output" , "yolo" )) -> None :
655+ def export_yolo (self , tasks : list , classes : list = [], output_dir : str = os .path .join ("output" , "yolo" )) -> None :
655656 """
656657 Convert tasks to YOLO format and export as files.
658+ If you pass classes, classes.txt will be generated based on it .
659+ If not , classes.txt will be generated based on passed tasks .(Annotations never used in your project will not be exported.)
657660
658661 tasks is a list of tasks. (Required)
662+ classes is a list of annotation values. e.g. ['dog','bird'] (Optional)
659663 output_dir is output directory(default: output/yolo). (Optional)
660664 """
661- annos , categories = converters .to_yolo (tasks )
665+ annos , categories = converters .to_yolo (tasks , classes )
662666 for anno in annos :
663667 file_name = anno ["filename" ]
664668 basename = utils .get_basename (file_name )
@@ -709,12 +713,12 @@ def export_labelme(self, tasks: list, output_dir: str = os.path.join("output", "
709713 with open (file_path , 'w' ) as f :
710714 json .dump (labelme , f , indent = 4 , ensure_ascii = False )
711715
712-
713716 # Instance / Semantic Segmetation
717+
714718 def export_instance_segmentation (self , tasks : list , output_dir : str = os .path .join ("output" , "instance_segmentation" ), pallete : List [int ] = const .COLOR_PALETTE ) -> None :
715719 """
716720 Convert tasks to index color instance segmentation (PNG files).
717- Supports only bbox, polygon and segmentation annotation types. Hollowed points are not supported.
721+ Supports only bbox, polygon and segmentation annotation types.
718722 Supports up to 57 instances in default colors palette. Check const.COLOR_PALETTE for more details.
719723
720724 tasks is a list of tasks. (Required)
@@ -723,12 +727,13 @@ def export_instance_segmentation(self, tasks: list, output_dir: str = os.path.jo
723727 """
724728 tasks = converters .to_pixel_coordinates (tasks )
725729 for task in tasks :
726- self .__export_index_color_image (task = task , output_dir = output_dir , pallete = pallete , is_instance_segmentation = True )
727-
730+ self .__export_index_color_image (
731+ task = task , output_dir = output_dir , pallete = pallete , is_instance_segmentation = True )
732+
728733 def export_semantic_segmentation (self , tasks : list , output_dir : str = os .path .join ("output" , "semantic_segmentation" ), pallete : List [int ] = const .COLOR_PALETTE ) -> None :
729734 """
730735 Convert tasks to index color semantic segmentation (PNG files).
731- Supports only bbox, polygon and segmentation annotation types. Hollowed points are not supported.
736+ Supports only bbox, polygon and segmentation annotation types.
732737 Check const.COLOR_PALETTE for color pallete.
733738
734739 tasks is a list of tasks. (Required)
@@ -744,7 +749,8 @@ def export_semantic_segmentation(self, tasks: list, output_dir: str = os.path.jo
744749
745750 tasks = converters .to_pixel_coordinates (tasks )
746751 for task in tasks :
747- self .__export_index_color_image (task = task , output_dir = output_dir , pallete = pallete , is_instance_segmentation = False , classes = classes )
752+ self .__export_index_color_image (
753+ task = task , output_dir = output_dir , pallete = pallete , is_instance_segmentation = False , classes = classes )
748754
749755 def __export_index_color_image (self , task : list , output_dir : str , pallete : List [int ], is_instance_segmentation : bool = True , classes : list = []) -> None :
750756 image = Image .new ("RGB" , (task ["width" ], task ["height" ]), 0 )
@@ -753,28 +759,39 @@ def __export_index_color_image(self, task: list, output_dir: str, pallete: List[
753759
754760 index = 1
755761 for annotation in task ["annotations" ]:
756- color = index if is_instance_segmentation else classes .index (annotation ["value" ]) + 1
762+ color = index if is_instance_segmentation else classes .index (
763+ annotation ["value" ]) + 1
757764 if annotation ["type" ] == AnnotationType .segmentation .value :
758765 for region in annotation ["points" ]:
759766 count = 0
760767 for points in region :
761- cv_draw_points = self .__get_cv_draw_points (points )
762768 if count == 0 :
763- cv2 .fillPoly (image , [cv_draw_points ], color , lineType = cv2 .LINE_8 , shift = 0 )
769+ cv_draw_points = self .__get_cv_draw_points (points )
770+ cv2 .fillPoly (
771+ image , [cv_draw_points ], color , lineType = cv2 .LINE_8 , shift = 0 )
764772 else :
765- cv2 .fillPoly (image , [cv_draw_points ], 0 , lineType = cv2 .LINE_8 , shift = 0 )
773+ # Reverse hollow points for opencv because this points are counter clockwise
774+ cv_draw_points = self .__get_cv_draw_points (
775+ utils .reverse_points (points ))
776+ cv2 .fillPoly (
777+ image , [cv_draw_points ], 0 , lineType = cv2 .LINE_8 , shift = 0 )
766778 count += 1
767779 elif annotation ["type" ] == AnnotationType .polygon .value :
768- cv_draw_points = self .__get_cv_draw_points (annotation ["points" ])
769- cv2 .fillPoly (image , [cv_draw_points ], color , lineType = cv2 .LINE_8 , shift = 0 )
780+ cv_draw_points = self .__get_cv_draw_points (
781+ annotation ["points" ])
782+ cv2 .fillPoly (image , [cv_draw_points ], color ,
783+ lineType = cv2 .LINE_8 , shift = 0 )
770784 elif annotation ["type" ] == AnnotationType .bbox .value :
771- cv_draw_points = self .__get_cv_draw_points (annotation ["points" ])
772- cv2 .fillPoly (image , [cv_draw_points ], color , lineType = cv2 .LINE_8 , shift = 0 )
785+ cv_draw_points = self .__get_cv_draw_points (
786+ annotation ["points" ])
787+ cv2 .fillPoly (image , [cv_draw_points ], color ,
788+ lineType = cv2 .LINE_8 , shift = 0 )
773789 else :
774790 continue
775791 index += 1
776792
777- image_path = os .path .join (output_dir , utils .get_basename (task ["name" ]) + ".png" )
793+ image_path = os .path .join (
794+ output_dir , utils .get_basename (task ["name" ]) + ".png" )
778795 os .makedirs (os .path .dirname (image_path ), exist_ok = True )
779796 image = Image .fromarray (image )
780797 image = image .convert ('P' )
@@ -823,7 +840,6 @@ def __get_cv_draw_points(self, points: List[int]) -> List[int]:
823840 cv_points .append ((new_points [i * 2 ], new_points [i * 2 + 1 ]))
824841 return np .array (cv_points )
825842
826-
827843 # Annotation
828844
829845 def find_annotation (self , annotation_id : str ) -> dict :
0 commit comments