99
1010from tqdm import tqdm
1111from PIL import Image
12- from ..utils import HEADERS , load_image , load_url , list_dir
13- from . import list_datasets , list_images , load_annotations , save_annotations
12+ from sklearn .model_selection import train_test_split
13+
14+ from ..client import Abraia
15+ from ..utils import HEADERS , load_image , load_url , list_dir , url_path
16+ from ..inference .detect import segment_objects
17+
18+ abraia = Abraia ()
1419
1520GOOGLE_BASE_URL = 'https://www.google.com/search?q='
1621GOOGLE_PICTURE_ID = '''&biw=1536&bih=674&tbm=isch&sxsrf=ACYBGNSXXpS6YmAKUiLKKBs6xWb4uUY5gA:1581168823770&source=lnms&sa=X&ved=0ahUKEwioj8jwiMLnAhW9AhAIHbXTBMMQ_AUI3QUoAQ'''
@@ -24,7 +29,7 @@ def download_page(url):
2429 return resp .text
2530
2631
27- def save_image (link , output_dir , timeout = 10 , max_size = 1920 ):
32+ def save_image_file (link , output_dir , timeout = 10 , max_size = 1920 ):
2833 resp = requests .get (link , headers = HEADERS , allow_redirects = True , timeout = timeout )
2934 kind = filetype .guess (resp .content )
3035 if kind and kind .mime .startswith ('image' ):
@@ -39,27 +44,27 @@ def save_image(link, output_dir, timeout=10, max_size=1920):
3944
4045
4146def get_filter (shorthand ):
42- if shorthand == "line" or shorthand == "linedrawing" :
43- return "+filterui:photo-linedrawing"
44- elif shorthand == "photo" :
45- return "+filterui:photo-photo"
46- elif shorthand == "clipart" :
47- return "+filterui:photo-clipart"
48- elif shorthand == "gif" or shorthand == "animatedgif" :
49- return "+filterui:photo-animatedgif"
50- elif shorthand == "transparent" :
51- return "+filterui:photo-transparent"
52- else :
53- return ""
54-
47+ if shorthand == "line" or shorthand == "linedrawing" :
48+ return "+filterui:photo-linedrawing"
49+ elif shorthand == "photo" :
50+ return "+filterui:photo-photo"
51+ elif shorthand == "clipart" :
52+ return "+filterui:photo-clipart"
53+ elif shorthand == "gif" or shorthand == "animatedgif" :
54+ return "+filterui:photo-animatedgif"
55+ elif shorthand == "transparent" :
56+ return "+filterui:photo-transparent"
57+ else :
58+ return ""
59+
5560
5661def scan_bing_page (html ):
5762 links = re .findall ('murl":"(.*?)"' , html )
5863 for link in links :
5964 link = link .replace (" " , "%20" )
6065 yield link
6166
62-
67+
6368def search_bing (query , limit = 50 , adult = 'off' , filter = '' ):
6469 for page_counter in range (100 ):
6570 # Parse the page source and download pics
@@ -106,7 +111,7 @@ def download(query, limit=100, output_dir='dataset', verbose=True):
106111 seen .add (link )
107112 if download_count < limit :
108113 try :
109- save_image (link , output_dir )
114+ save_image_file (link , output_dir )
110115 download_count += 1
111116 if verbose :
112117 print (f"[%] Downloaded Image #{ download_count } from { link } " )
@@ -119,12 +124,20 @@ def download(query, limit=100, output_dir='dataset', verbose=True):
119124 if set (ends ) == {True }:
120125 break
121126
127+
122128def search_images (query , limit = 100 , output_dir = 'dataset' , verbose = True ):
123129 """Search and download images from Google and Bing."""
124130 download (query , limit = limit , output_dir = output_dir , verbose = verbose )
125131 return list_dir (output_dir )
126132
127133
134+ def download_file (path , folder ):
135+ dest = os .path .join (folder , os .path .basename (path ))
136+ if not os .path .exists (dest ):
137+ abraia .download_file (path , dest )
138+ return dest
139+
140+
128141# As the Grounding DINO model was trained with a "." after each text, we'll do the same here.
129142def preprocess_caption (caption : str ) -> str :
130143 result = caption .lower ().strip ()
@@ -149,17 +162,116 @@ def annotate_image(pipe, img, classes, threshold=0.3):
149162 return objects
150163
151164
152- def annotate_images (images , classes ):
165+ def annotate_images (images , classes , segment = False ):
153166 """Annotate a dataset using Grounding Dino."""
154167 from transformers import pipeline
155168 pipe = pipeline (task = "zero-shot-object-detection" , model = "IDEA-Research/grounding-dino-tiny" )
156- #pipe = pipeline(task="zero-shot-object-detection", model="google/owlv2-base-patch16-ensemble")
157169 annotations = []
158170 for row in tqdm (images ):
159171 url , filename = row ['url' ], row ['name' ]
160172 img = load_image (load_url (url ))
161173 objects = annotate_image (pipe , img , classes )
162174 if objects :
175+ if segment :
176+ try :
177+ objects = segment_objects (img , objects )
178+ except :
179+ continue
163180 annotation = {'url' : url , 'filename' : filename , 'objects' : objects }
164181 annotations .append (annotation )
165182 return annotations
183+
184+
185+ def list_datasets ():
186+ folders = abraia .list_files ()[1 ]
187+ return [folder ['name' ] for folder in folders if abraia .check_file (f"{ folder ['name' ]} /annotations.json" )]
188+
189+
190+ def list_models (project ):
191+ files = abraia .list_files (f"{ project } /" )[0 ]
192+ return [f ['name' ] for f in files if f ['name' ].endswith ('.onnx' )]
193+
194+
195+ def load_annotations (project ):
196+ annotations = abraia .load_json (f"{ project } /annotations.json" )
197+ for annotation in annotations :
198+ annotation ['path' ] = f"{ project } /{ annotation ['filename' ]} "
199+ annotation ['url' ] = url_path (f"{ abraia .userid } /{ annotation ['path' ]} " )
200+ return annotations
201+
202+
203+ def load_labels (annotations ):
204+ labels = []
205+ for annotation in annotations :
206+ for object in annotation .get ('objects' , []):
207+ label = object .get ('label' )
208+ if label and label not in labels :
209+ labels .append (label )
210+ return list (set (labels ))
211+
212+
213+ def load_task (annotations ):
214+ classify , detect , segment = False , False , False
215+ for annotation in annotations :
216+ for object in annotation .get ('objects' , []):
217+ if 'polygon' in object :
218+ segment = True
219+ elif 'box' in object :
220+ detect = True
221+ elif 'label' in object :
222+ classify = True
223+ return 'segment' if segment else 'detect' if detect else 'classify' if classify else ''
224+
225+
226+ def list_images (project ):
227+ files = abraia .list_files (f"{ project } /" )[0 ]
228+ files = [f for f in files if f ['type' ] in ['image/jpeg' , 'image/png' ]]
229+ for data in files :
230+ data ['url' ] = url_path (f"{ abraia .userid } /{ data ['path' ]} " )
231+ return files
232+
233+
234+ def save_annotations (project , annotations ):
235+ abraia .save_json (f"{ project } /annotations.json" , annotations )
236+
237+
238+ class Dataset :
239+ def __init__ (self , project ):
240+ self .project = project
241+ self .annotations = []
242+ self .classes = []
243+ self .task = ''
244+ self .images = []
245+
246+ def load (self ):
247+ if self .project in list_datasets ():
248+ self .annotations = load_annotations (self .project )
249+ self .classes = load_labels (self .annotations )
250+ self .task = load_task (self .annotations )
251+ self .images = list_images (self .project )
252+ return self
253+
254+ def annotate (self , label , segment = False ):
255+ annotated_filenames = {a ['filename' ] for a in self .annotations }
256+ images = [img for img in self .images if img ['name' ] not in annotated_filenames ]
257+ new_annotations = annotate_images (images , [label ], segment = segment )
258+ self .annotations .extend (new_annotations )
259+ return self .annotations
260+
261+ def save (self , annotations = None ):
262+ if annotations is not None :
263+ self .annotations = annotations
264+ save_annotations (self .project , self .annotations )
265+
266+ def split (self ):
267+ # TODO: Split dataset by classes to avoid class imbalance
268+ backgrounds = [annotation for annotation in self .annotations if not annotation .get ('objects' )]
269+ annotations = [annotation for annotation in self .annotations if annotation .get ('objects' )]
270+ train , test = train_test_split (annotations , test_size = 0.3 )
271+ val , test = train_test_split (test , test_size = 0.5 )
272+ train .extend (backgrounds )
273+ return train , val , test
274+
275+
276+ def load_dataset (project ):
277+ return Dataset (project ).load ()
0 commit comments