wuhp commited on
Commit
3911cda
·
verified ·
1 Parent(s): 99a318c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -46
app.py CHANGED
@@ -16,7 +16,7 @@ def parse_roboflow_url(url: str):
16
  parsed = urlparse(url)
17
  parts = parsed.path.strip('/').split('/')
18
  workspace = parts[0]
19
- project = parts[1]
20
  try:
21
  version = int(parts[-1])
22
  except ValueError:
@@ -29,8 +29,8 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
29
  rf = Roboflow(api_key=api_key)
30
  ws, proj_name, ver = parse_roboflow_url(dataset_url)
31
  version_obj = rf.workspace(ws).project(proj_name).version(ver)
32
- dataset = version_obj.download("coco-segmentation")
33
- root = dataset.location
34
 
35
  # --- find the COCO JSON
36
  ann_file = None
@@ -44,23 +44,23 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
44
  if not ann_file:
45
  raise FileNotFoundError(f"No JSON annotations under {root}")
46
 
47
- coco = json.load(open(ann_file, 'r'))
48
  images_info = {img['id']: img for img in coco['images']}
49
- cat_ids = sorted(c['id'] for c in coco.get('categories', []))
50
  id_to_index = {cid: idx for idx, cid in enumerate(cat_ids)}
51
 
52
- # --- make a flat YOLO folder
53
  out_root = tempfile.mkdtemp(prefix="yolov8_")
54
  flat_img = os.path.join(out_root, "flat_images")
55
  flat_lbl = os.path.join(out_root, "flat_labels")
56
  os.makedirs(flat_img, exist_ok=True)
57
  os.makedirs(flat_lbl, exist_ok=True)
58
 
59
- # --- convert each segmentation to a YOLO bbox line
60
  annos = {}
61
  for anno in coco['annotations']:
62
  img_id = anno['image_id']
63
- poly = anno['segmentation'][0]
64
  xs, ys = poly[0::2], poly[1::2]
65
  x_min, x_max = min(xs), max(xs)
66
  y_min, y_max = min(ys), max(ys)
@@ -74,16 +74,16 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
74
  )
75
  annos.setdefault(img_id, []).append(line)
76
 
77
- # --- locate the single images folder
78
  img_src = None
79
  for dp, _, files in os.walk(root):
80
  if any(f.lower().endswith(('.jpg','.png','.jpeg')) for f in files):
81
  img_src = dp
82
  break
83
  if not img_src:
84
- raise FileNotFoundError(f"No images folder in {root}")
85
 
86
- # --- copy images + write flat labels
87
  name_to_id = {img['file_name']: img['id'] for img in coco['images']}
88
  for fname, img_id in name_to_id.items():
89
  src_path = os.path.join(img_src, fname)
@@ -93,38 +93,48 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
93
  with open(os.path.join(flat_lbl, fname.rsplit('.',1)[0] + ".txt"), 'w') as lf:
94
  lf.write("\n".join(annos.get(img_id, [])))
95
 
96
- # --- split filenames into train/valid/test lists
97
- all_files = sorted([f for f in os.listdir(flat_img) if f.lower().endswith(('.jpg','.png','.jpeg'))])
 
 
 
98
  random.shuffle(all_files)
99
  n = len(all_files)
100
  n_train = max(1, int(n * split_ratios[0]))
101
  n_valid = max(1, int(n * split_ratios[1]))
102
- # ensure we don’t overshoot
103
  n_valid = min(n_valid, n - n_train - 1)
 
104
  splits = {
105
  "train": all_files[:n_train],
106
  "valid": all_files[n_train:n_train+n_valid],
107
  "test": all_files[n_train+n_valid:]
108
  }
109
 
110
- # --- create Roboflowfriendly structure:
111
- # out_root/images/{train,valid,test}
112
- # out_root/labels/{train,valid,test}
113
  for split, files in splits.items():
114
- img_dir = os.path.join(out_root, "images", split)
115
- lbl_dir = os.path.join(out_root, "labels", split)
116
- os.makedirs(img_dir, exist_ok=True)
117
- os.makedirs(lbl_dir, exist_ok=True)
118
  for fn in files:
119
- shutil.move(os.path.join(flat_img, fn), os.path.join(img_dir, fn))
120
- shutil.move(os.path.join(flat_lbl, fn.rsplit('.',1)[0] + ".txt"),
121
- os.path.join(lbl_dir, fn.rsplit('.',1)[0] + ".txt"))
122
-
123
- # --- clean up flats
 
 
 
 
 
 
 
 
124
  shutil.rmtree(flat_img)
125
  shutil.rmtree(flat_lbl)
126
 
127
- # --- build a few before/after previews
128
  before, after = [], []
129
  sample = random.sample(list(name_to_id.keys()), min(5, len(name_to_id)))
130
  for fname in sample:
@@ -135,17 +145,17 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
135
  for anno in coco['annotations']:
136
  if anno['image_id'] != name_to_id[fname]:
137
  continue
138
- pts = np.array(anno['segmentation'][0], np.int32).reshape(-1, 2)
139
- cv2.polylines(seg_vis, [pts], True, (255, 0, 0), 2)
140
 
141
  box_vis = img.copy()
142
  for line in annos.get(name_to_id[fname], []):
143
  _, cxn, cyn, wnorm, hnorm = map(float, line.split())
144
  iw, ih = images_info[name_to_id[fname]]['width'], images_info[name_to_id[fname]]['height']
145
- w0, h0 = int(wnorm * iw), int(hnorm * ih)
146
- x0 = int(cxn * iw - w0 / 2)
147
- y0 = int(cyn * ih - h0 / 2)
148
- cv2.rectangle(box_vis, (x0, y0), (x0+w0, y0+h0), (0, 255, 0), 2)
149
 
150
  before.append(Image.fromarray(seg_vis))
151
  after.append(Image.fromarray(box_vis))
@@ -164,10 +174,10 @@ def upload_and_train_detection(
164
  rf = Roboflow(api_key=api_key)
165
  ws = rf.workspace()
166
 
167
- # get-or-create your detection project
168
  try:
169
  proj = ws.project(project_slug)
170
- except Exception:
171
  proj = ws.create_project(
172
  project_slug,
173
  annotation=project_type,
@@ -175,7 +185,7 @@ def upload_and_train_detection(
175
  project_license=project_license
176
  )
177
 
178
- # upload the properly‑split folder
179
  ws.upload_dataset(
180
  dataset_path,
181
  project_slug,
@@ -183,13 +193,11 @@ def upload_and_train_detection(
183
  project_type=project_type
184
  )
185
 
186
- # create a new version
187
  version_num = proj.generate_version(settings={
188
  "augmentation": {},
189
  "preprocessing": {},
190
  })
191
-
192
- # enqueue training (now finds train/valid/test)
193
  proj.version(str(version_num)).train()
194
 
195
  # return the hosted endpoint URL
@@ -201,13 +209,13 @@ def upload_and_train_detection(
201
  with gr.Blocks() as app:
202
  gr.Markdown("## 🔄 Seg→BBox + Auto‐Upload/Train")
203
 
204
- api_input = gr.Textbox(label="Roboflow API Key", type="password")
205
- url_input = gr.Textbox(label="Segmentation Dataset URL")
206
- run_btn = gr.Button("Convert to BBoxes")
207
- before_g = gr.Gallery(columns=5, label="Before")
208
- after_g = gr.Gallery(columns=5, label="After")
209
- ds_state = gr.Textbox(visible=False)
210
- slug_state = gr.Textbox(visible=False)
211
 
212
  run_btn.click(
213
  convert_seg_to_bbox,
 
16
  parsed = urlparse(url)
17
  parts = parsed.path.strip('/').split('/')
18
  workspace = parts[0]
19
+ project = parts[1]
20
  try:
21
  version = int(parts[-1])
22
  except ValueError:
 
29
  rf = Roboflow(api_key=api_key)
30
  ws, proj_name, ver = parse_roboflow_url(dataset_url)
31
  version_obj = rf.workspace(ws).project(proj_name).version(ver)
32
+ dataset = version_obj.download("coco-segmentation")
33
+ root = dataset.location
34
 
35
  # --- find the COCO JSON
36
  ann_file = None
 
44
  if not ann_file:
45
  raise FileNotFoundError(f"No JSON annotations under {root}")
46
 
47
+ coco = json.load(open(ann_file, 'r'))
48
  images_info = {img['id']: img for img in coco['images']}
49
+ cat_ids = sorted(c['id'] for c in coco.get('categories', []))
50
  id_to_index = {cid: idx for idx, cid in enumerate(cat_ids)}
51
 
52
+ # --- prepare flat_images + flat_labels
53
  out_root = tempfile.mkdtemp(prefix="yolov8_")
54
  flat_img = os.path.join(out_root, "flat_images")
55
  flat_lbl = os.path.join(out_root, "flat_labels")
56
  os.makedirs(flat_img, exist_ok=True)
57
  os.makedirs(flat_lbl, exist_ok=True)
58
 
59
+ # --- convert each segmentation YOLO bbox line
60
  annos = {}
61
  for anno in coco['annotations']:
62
  img_id = anno['image_id']
63
+ poly = anno['segmentation'][0]
64
  xs, ys = poly[0::2], poly[1::2]
65
  x_min, x_max = min(xs), max(xs)
66
  y_min, y_max = min(ys), max(ys)
 
74
  )
75
  annos.setdefault(img_id, []).append(line)
76
 
77
+ # --- locate the single folder of raw images
78
  img_src = None
79
  for dp, _, files in os.walk(root):
80
  if any(f.lower().endswith(('.jpg','.png','.jpeg')) for f in files):
81
  img_src = dp
82
  break
83
  if not img_src:
84
+ raise FileNotFoundError(f"No images under {root}")
85
 
86
+ # --- copy images + write flat label files
87
  name_to_id = {img['file_name']: img['id'] for img in coco['images']}
88
  for fname, img_id in name_to_id.items():
89
  src_path = os.path.join(img_src, fname)
 
93
  with open(os.path.join(flat_lbl, fname.rsplit('.',1)[0] + ".txt"), 'w') as lf:
94
  lf.write("\n".join(annos.get(img_id, [])))
95
 
96
+ # --- split into train/valid/test
97
+ all_files = sorted(
98
+ f for f in os.listdir(flat_img)
99
+ if f.lower().endswith(('.jpg','.png','.jpeg'))
100
+ )
101
  random.shuffle(all_files)
102
  n = len(all_files)
103
  n_train = max(1, int(n * split_ratios[0]))
104
  n_valid = max(1, int(n * split_ratios[1]))
105
+ # ensure at least 1 for each split
106
  n_valid = min(n_valid, n - n_train - 1)
107
+
108
  splits = {
109
  "train": all_files[:n_train],
110
  "valid": all_files[n_train:n_train+n_valid],
111
  "test": all_files[n_train+n_valid:]
112
  }
113
 
114
+ # --- build Roboflowfriendly folder structure
 
 
115
  for split, files in splits.items():
116
+ out_img_dir = os.path.join(out_root, "images", split)
117
+ out_lbl_dir = os.path.join(out_root, "labels", split)
118
+ os.makedirs(out_img_dir, exist_ok=True)
119
+ os.makedirs(out_lbl_dir, exist_ok=True)
120
  for fn in files:
121
+ # move image
122
+ shutil.move(
123
+ os.path.join(flat_img, fn),
124
+ os.path.join(out_img_dir, fn)
125
+ )
126
+ # move corresponding .txt label
127
+ lbl_fn = fn.rsplit('.',1)[0] + ".txt"
128
+ shutil.move(
129
+ os.path.join(flat_lbl, lbl_fn),
130
+ os.path.join(out_lbl_dir, lbl_fn)
131
+ )
132
+
133
+ # --- clean up the flat dirs
134
  shutil.rmtree(flat_img)
135
  shutil.rmtree(flat_lbl)
136
 
137
+ # --- prepare a few before/after visuals
138
  before, after = [], []
139
  sample = random.sample(list(name_to_id.keys()), min(5, len(name_to_id)))
140
  for fname in sample:
 
145
  for anno in coco['annotations']:
146
  if anno['image_id'] != name_to_id[fname]:
147
  continue
148
+ pts = np.array(anno['segmentation'][0], np.int32).reshape(-1,2)
149
+ cv2.polylines(seg_vis, [pts], True, (255,0,0), 2)
150
 
151
  box_vis = img.copy()
152
  for line in annos.get(name_to_id[fname], []):
153
  _, cxn, cyn, wnorm, hnorm = map(float, line.split())
154
  iw, ih = images_info[name_to_id[fname]]['width'], images_info[name_to_id[fname]]['height']
155
+ w0, h0 = int(wnorm*iw), int(hnorm*ih)
156
+ x0 = int(cxn*iw - w0/2)
157
+ y0 = int(cyn*ih - h0/2)
158
+ cv2.rectangle(box_vis, (x0,y0), (x0+w0,y0+h0), (0,255,0), 2)
159
 
160
  before.append(Image.fromarray(seg_vis))
161
  after.append(Image.fromarray(box_vis))
 
174
  rf = Roboflow(api_key=api_key)
175
  ws = rf.workspace()
176
 
177
+ # get-or-create detection project
178
  try:
179
  proj = ws.project(project_slug)
180
+ except:
181
  proj = ws.create_project(
182
  project_slug,
183
  annotation=project_type,
 
185
  project_license=project_license
186
  )
187
 
188
+ # upload the folder that now has train/valid/test
189
  ws.upload_dataset(
190
  dataset_path,
191
  project_slug,
 
193
  project_type=project_type
194
  )
195
 
196
+ # create a new version & queue training
197
  version_num = proj.generate_version(settings={
198
  "augmentation": {},
199
  "preprocessing": {},
200
  })
 
 
201
  proj.version(str(version_num)).train()
202
 
203
  # return the hosted endpoint URL
 
209
  with gr.Blocks() as app:
210
  gr.Markdown("## 🔄 Seg→BBox + Auto‐Upload/Train")
211
 
212
+ api_input = gr.Textbox(label="Roboflow API Key", type="password")
213
+ url_input = gr.Textbox(label="Segmentation Dataset URL")
214
+ run_btn = gr.Button("Convert to BBoxes")
215
+ before_g = gr.Gallery(columns=5, label="Before")
216
+ after_g = gr.Gallery(columns=5, label="After")
217
+ ds_state = gr.Textbox(visible=False)
218
+ slug_state = gr.Textbox(visible=False)
219
 
220
  run_btn.click(
221
  convert_seg_to_bbox,