66from typing import Dict , Any
77from tqdm .contrib .concurrent import process_map
88
9+ from ..utils import save_text
910from .dataset import list_datasets , load_dataset , search_images , list_models , download_file
10- from ..utils import make_dirs
1111
1212
1313def load_tasks (task ):
14- tasks = ['classify' , 'detect' , 'segment' ]
1514 if task :
16- idx = tasks . index ( task )
17- return tasks [:idx + 1 ]
15+ tasks = [ 'classify' , 'detect' , 'segment' ]
16+ return tasks [:tasks . index ( task ) + 1 ]
1817 return []
1918
2019
2120def save_annotation (annotation , folder , classes , task ):
21+ im = Image .open (os .path .join (folder , 'images' , annotation ['filename' ]))
22+ label_lines = []
23+ for object in annotation .get ('objects' , []):
24+ label , box , polygon = object .get ('label' ), object .get ('box' ), object .get ('polygon' )
25+ if task == 'segment' :
26+ if polygon :
27+ label_line = f"{ classes .index (label )} " + ' ' .join ([f"{ point [0 ] / im .width } { point [1 ] / im .height } " for point in polygon ])
28+ label_lines .append (label_line )
29+ elif task == 'detect' :
30+ if polygon :
31+ xx , yy = [point [0 ] for point in polygon ], [point [1 ] for point in polygon ]
32+ x1 , y1 , x2 , y2 = min (xx ), min (yy ), max (xx ), max (yy )
33+ box = [x1 , y1 , x2 - x1 , y2 - y1 ]
34+ if box :
35+ label_line = f"{ classes .index (label )} { (box [0 ] + box [2 ] / 2 ) / im .width } { (box [1 ] + box [3 ] / 2 ) / im .height } { box [2 ] / im .width } { box [3 ] / im .height } "
36+ label_lines .append (label_line )
37+ label_path = os .path .join (folder , 'labels' , f"{ os .path .splitext (annotation ['filename' ])[0 ]} .txt" )
38+ save_text (label_path , '\n ' .join (label_lines ))
39+
40+
41+ def save_data (annotation , folder , classes , task ):
42+ path = annotation ['path' ]
43+ dest = folder if task == 'classify' else os .path .join (folder , 'images' )
2244 if task == 'classify' :
23- for object in annotation .get ('objects' , []):
24- label = object .get ('label' )
25- if label :
26- src = os .path .join (folder , annotation ['filename' ])
27- dest = os .path .join (folder , label , annotation ['filename' ])
28- shutil .move (src , dest )
29- break
30- else :
31- im = Image .open (os .path .join (folder , 'images' , annotation ['filename' ]))
32- label_lines = []
33- for object in annotation .get ('objects' , []):
34- label , box , polygon = object .get ('label' ), object .get ('box' ), object .get ('polygon' )
35- # Convert polygon or box to yolo format
36- if task == 'segment' :
37- if polygon :
38- label_line = f"{ classes .index (label )} " + ' ' .join ([f"{ point [0 ] / im .width } { point [1 ] / im .height } " for point in polygon ])
39- label_lines .append (label_line )
40- elif task == 'detect' :
41- if polygon :
42- xx , yy = [point [0 ] for point in polygon ], [point [1 ] for point in polygon ]
43- x1 , y1 , x2 , y2 = min (xx ), min (yy ), max (xx ), max (yy )
44- box = [x1 , y1 , x2 - x1 , y2 - y1 ]
45- if box :
46- label_line = f"{ classes .index (label )} { (box [0 ] + box [2 ] / 2 ) / im .width } { (box [1 ] + box [3 ] / 2 ) / im .height } { box [2 ] / im .width } { box [3 ] / im .height } "
47- label_lines .append (label_line )
48- label_path = os .path .join (folder , 'labels' , f"{ os .path .splitext (annotation ['filename' ])[0 ]} .txt" )
49- with open (label_path , 'w' ) as f :
50- f .write ('\n ' .join (label_lines ))
51-
52-
53- def save_data (annotations , folder , classes , task ):
54- if (task == 'classify' ):
55- make_dirs (os .path .join (folder , '' ))
56- paths = [annotation ['path' ] for annotation in annotations ]
57- process_map (download_file , paths , itertools .repeat (folder ), max_workers = 5 )
58- for label in classes :
59- make_dirs (os .path .join (folder , label , '' ))
60- for annotation in annotations :
61- save_annotation (annotation , folder , classes , task )
62- else :
63- make_dirs (os .path .join (folder , 'images' , '' ))
64- paths = [annotation ['path' ] for annotation in annotations ]
65- process_map (download_file , paths , itertools .repeat (os .path .join (folder , 'images' )), max_workers = 5 )
66- make_dirs (os .path .join (folder , 'labels' , '' ))
67- for annotation in annotations :
68- save_annotation (annotation , folder , classes , task )
45+ label = next ((obj .get ('label' , '' ) for obj in annotation .get ('objects' , [])), '' )
46+ dest = os .path .join (dest , label )
47+ download_file (path , dest )
48+ if task != 'classify' :
49+ save_annotation (annotation , folder , classes , task )
6950
7051
7152def save_config (dataset , classes ):
@@ -76,17 +57,20 @@ def save_config(dataset, classes):
7657 names: { classes }
7758 '''
7859 path = os .path .join (dataset , 'data.yaml' )
79- with open (path , 'w' ) as f :
80- f .write (yaml_content )
60+ save_text (path , yaml_content )
8161
8262
8363def prepare_dataset (dataset , force = False ):
8464 if force or not os .path .exists (dataset .project ):
85- train , val , test = dataset .split ()
86- data_annotations = {'train' : train , 'val' : val , 'test' : test }
87- for x in ['train' , 'val' , 'test' ]:
88- save_data (data_annotations [x ], f"{ dataset .project } /{ x } " , dataset .classes , dataset .task )
89- save_config (dataset .project , dataset .classes )
65+ splits = list (zip (['train' , 'val' , 'test' ], dataset .split ()))
66+ all_annotations , all_folders = [], []
67+ for x , annotations in splits :
68+ folder = os .path .join (dataset .project , x )
69+ all_annotations .extend (annotations )
70+ all_folders .extend ([folder ] * len (annotations ))
71+ process_map (save_data , all_annotations , all_folders , itertools .repeat (dataset .classes ), itertools .repeat (dataset .task ), max_workers = 5 , chunksize = 1 , desc = "Downloading images" )
72+ if dataset .task != 'classify' :
73+ save_config (dataset .project , dataset .classes )
9074
9175
9276class ModelTrainer :
0 commit comments