77import shutil
88import time
99from pathlib import Path
10- from typing import Union
10+ from typing import List , Union
1111
12+ import cv2
1213import numpy as np
1314from tqdm import tqdm
1415
@@ -182,12 +183,14 @@ def generate_json(self, img_list, save_dir):
182183 raw_json_path = img_path .with_suffix (".json" )
183184 raw_json_data = self .read_json (raw_json_path )
184185
186+ img_h = raw_json_data .get ("imageHeight" )
187+ img_w = raw_json_data .get ("imageWidth" )
185188 img_info = {
186189 "date_captured" : str (self .cur_year ),
187190 "file_name" : new_img_name ,
188191 "id" : img_id ,
189- "height" : raw_json_data . get ( "imageHeight" ) ,
190- "width" : raw_json_data . get ( "imageWidth" ) ,
192+ "height" : img_h ,
193+ "width" : img_w ,
191194 }
192195 anno ["images" ].append (img_info )
193196
@@ -208,7 +211,8 @@ def generate_json(self, img_list, save_dir):
208211 if shape_type == RECTANGLE :
209212 x0 , y0 = np .min (points , axis = 0 )
210213 x1 , y1 = np .max (points , axis = 0 )
211- area = (x1 - x0 ) * (y1 - y0 )
214+ w , h = x1 - x1 , y1 - y0
215+ area = w * h
212216
213217 seg_points = [np .ravel (points , order = "C" ).tolist ()]
214218
@@ -217,12 +221,29 @@ def generate_json(self, img_list, save_dir):
217221 "area" : area ,
218222 "iscrowd" : 0 ,
219223 "image_id" : img_id ,
220- "bbox" : [x0 , y0 , x1 , y1 ],
224+ "bbox" : [x0 , y0 , w , h ],
221225 "category_id" : label_id ,
222226 "id" : self .object_id ,
223227 }
224228 elif shape_type == POLYGON :
225- pass
229+ mask = np .zeros ((img_h , img_w ), dtype = "uint8" )
230+ img_mask = cv2 .fillPoly (mask , np .int32 ([points ]), 255 )
231+ contours , _ = cv2 .findContours (
232+ img_mask , cv2 .RETR_LIST , cv2 .CHAIN_APPROX_SIMPLE
233+ )
234+ contour = contours [0 ]
235+ bbox_points = self .get_mini_boxes (contour )
236+ area = cv2 .contourArea (contour )
237+
238+ one_anno_dict = {
239+ "segmentation" : points .tolist (),
240+ "area" : area ,
241+ "iscrowd" : 0 ,
242+ "image_id" : img_id ,
243+ "bbox" : bbox_points ,
244+ "category_id" : label_id ,
245+ "id" : self .object_id ,
246+ }
226247
227248 anno_list .append (one_anno_dict )
228249 self .object_id += 1
@@ -255,6 +276,37 @@ def cp_file(self, file_path: Path, dst_dir: Path):
255276
256277 shutil .copy2 (str (file_path ), dst_dir )
257278
279+ def convert_polygon_to_rectangle (
280+ self ,
281+ ):
282+ pass
283+
284+ @staticmethod
285+ def get_mini_boxes (contour ) -> List [int ]:
286+ bounding_box = cv2 .minAreaRect (contour )
287+ points = sorted (list (cv2 .boxPoints (bounding_box )), key = lambda x : x [0 ])
288+
289+ index_1 , index_2 , index_3 , index_4 = 0 , 1 , 2 , 3
290+ if points [1 ][1 ] > points [0 ][1 ]:
291+ index_1 = 0
292+ index_4 = 1
293+ else :
294+ index_1 = 1
295+ index_4 = 0
296+ if points [3 ][1 ] > points [2 ][1 ]:
297+ index_2 = 2
298+ index_3 = 3
299+ else :
300+ index_2 = 3
301+ index_3 = 2
302+
303+ box = [points [index_1 ], points [index_2 ], points [index_3 ], points [index_4 ]]
304+ box = np .round (box ).astype (np .int32 ).tolist ()
305+ left_top , right_bottom = box [0 ], box [2 ]
306+ box_w = right_bottom [0 ] - left_top [0 ]
307+ box_h = right_bottom [1 ] - left_top [1 ]
308+ return left_top + [box_w , box_h ]
309+
258310
259311def main ():
260312 parser = argparse .ArgumentParser ("Datasets converter from labelme to COCO" )
0 commit comments