Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -3,7 +3,7 @@ import json
|
|
3 |
import random
|
4 |
import shutil
|
5 |
import tempfile
|
6 |
-
import time
|
7 |
from urllib.parse import urlparse
|
8 |
|
9 |
import cv2
|
@@ -32,11 +32,11 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
32 |
3) Split into train/valid/test
|
33 |
4) Return before/after visuals plus (dataset_path, detection_slug)
|
34 |
"""
|
35 |
-
rf
|
36 |
ws, proj_name, ver = parse_roboflow_url(dataset_url)
|
37 |
-
version_obj
|
38 |
-
dataset
|
39 |
-
root
|
40 |
|
41 |
# find the COCO JSON
|
42 |
ann_file = None
|
@@ -50,9 +50,9 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
50 |
if not ann_file:
|
51 |
raise FileNotFoundError(f"No JSON found under {root}")
|
52 |
|
53 |
-
coco
|
54 |
images_info = {img['id']: img for img in coco['images']}
|
55 |
-
cat_ids
|
56 |
id_to_index = {cid: idx for idx, cid in enumerate(cat_ids)}
|
57 |
|
58 |
# build YOLO bboxes
|
@@ -71,13 +71,8 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
71 |
)
|
72 |
annos.setdefault(img_id, []).append(line)
|
73 |
|
74 |
-
#
|
75 |
out_root = tempfile.mkdtemp(prefix="yolov8_")
|
76 |
-
flat_img = os.path.join(out_root, "flat_images")
|
77 |
-
flat_lbl = os.path.join(out_root, "flat_labels")
|
78 |
-
os.makedirs(flat_img, exist_ok=True)
|
79 |
-
os.makedirs(flat_lbl, exist_ok=True)
|
80 |
-
|
81 |
name_to_id = {img['file_name']: img['id'] for img in coco['images']}
|
82 |
file_paths = {
|
83 |
f: os.path.join(dp, f)
|
@@ -86,17 +81,8 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
86 |
if f in name_to_id
|
87 |
}
|
88 |
|
89 |
-
|
90 |
-
|
91 |
-
if not src:
|
92 |
-
continue
|
93 |
-
shutil.copy(src, os.path.join(flat_img, fname))
|
94 |
-
lbl_path = os.path.join(flat_lbl, fname.rsplit('.',1)[0] + ".txt")
|
95 |
-
with open(lbl_path, 'w') as lf:
|
96 |
-
lf.write("\n".join(annos.get(img_id, [])))
|
97 |
-
|
98 |
-
# split filenames
|
99 |
-
all_files = [f for f in os.listdir(flat_img) if f.lower().endswith(('.jpg','.png','.jpeg'))]
|
100 |
random.shuffle(all_files)
|
101 |
n = len(all_files)
|
102 |
n_train = max(1, int(n * split_ratios[0]))
|
@@ -108,27 +94,26 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
108 |
"test": all_files[n_train+n_valid:]
|
109 |
}
|
110 |
|
111 |
-
#
|
112 |
for split, files in splits.items():
|
113 |
-
img_dir = os.path.join(out_root, "images"
|
114 |
-
lbl_dir = os.path.join(out_root, "labels"
|
115 |
os.makedirs(img_dir, exist_ok=True)
|
116 |
os.makedirs(lbl_dir, exist_ok=True)
|
117 |
-
for
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
# prepare
|
126 |
before, after = [], []
|
127 |
-
sample = random.sample(
|
128 |
for fname in sample:
|
129 |
img = cv2.cvtColor(cv2.imread(file_paths[fname]), cv2.COLOR_BGR2RGB)
|
130 |
|
131 |
-
# original segmentation overlay
|
132 |
seg_vis = img.copy()
|
133 |
for anno in coco['annotations']:
|
134 |
if anno['image_id'] != name_to_id[fname]:
|
@@ -136,7 +121,6 @@ def convert_seg_to_bbox(api_key: str, dataset_url: str, split_ratios=(0.8, 0.1,
|
|
136 |
pts = np.array(anno['segmentation'][0], np.int32).reshape(-1,2)
|
137 |
cv2.polylines(seg_vis, [pts], True, (255,0,0), 2)
|
138 |
|
139 |
-
# bbox overlay
|
140 |
box_vis = img.copy()
|
141 |
for line in annos.get(name_to_id[fname], []):
|
142 |
_, cxn, cyn, wnorm, hnorm = map(float, line.split())
|
@@ -168,7 +152,7 @@ def upload_and_train_detection(
|
|
168 |
rf = Roboflow(api_key=api_key)
|
169 |
ws = rf.workspace()
|
170 |
|
171 |
-
#
|
172 |
try:
|
173 |
proj = ws.project(detection_slug)
|
174 |
except Exception as e:
|
@@ -182,7 +166,7 @@ def upload_and_train_detection(
|
|
182 |
else:
|
183 |
raise
|
184 |
|
185 |
-
#
|
186 |
_, real_slug = proj.id.rsplit("/", 1)
|
187 |
ws.upload_dataset(
|
188 |
dataset_path,
|
@@ -191,16 +175,12 @@ def upload_and_train_detection(
|
|
191 |
project_type=project_type
|
192 |
)
|
193 |
|
194 |
-
#
|
195 |
try:
|
196 |
-
version_num = proj.generate_version(settings={
|
197 |
-
"augmentation": {},
|
198 |
-
"preprocessing": {}
|
199 |
-
})
|
200 |
except RuntimeError as e:
|
201 |
msg = str(e).lower()
|
202 |
if "unsupported request" in msg or "does not exist" in msg:
|
203 |
-
# bump slug and retry
|
204 |
new_slug = real_slug + "-v2"
|
205 |
proj = ws.create_project(
|
206 |
new_slug,
|
@@ -208,20 +188,14 @@ def upload_and_train_detection(
|
|
208 |
project_type=project_type,
|
209 |
project_license=project_license
|
210 |
)
|
211 |
-
ws.upload_dataset(
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
project_type=project_type
|
216 |
-
)
|
217 |
-
version_num = proj.generate_version(settings={
|
218 |
-
"augmentation": {},
|
219 |
-
"preprocessing": {}
|
220 |
-
})
|
221 |
else:
|
222 |
raise
|
223 |
|
224 |
-
#
|
225 |
for _ in range(20):
|
226 |
try:
|
227 |
model = proj.version(str(version_num)).train()
|
@@ -241,12 +215,12 @@ def upload_and_train_detection(
|
|
241 |
with gr.Blocks() as app:
|
242 |
gr.Markdown("## 🔄 Seg→BBox + Auto‑Upload/Train")
|
243 |
|
244 |
-
api_input
|
245 |
-
url_input
|
246 |
-
run_btn
|
247 |
-
before_g
|
248 |
-
after_g
|
249 |
-
ds_state
|
250 |
slug_state = gr.Textbox(visible=False, label="Detection Project Slug")
|
251 |
|
252 |
run_btn.click(
|
@@ -257,7 +231,7 @@ with gr.Blocks() as app:
|
|
257 |
|
258 |
gr.Markdown("## 🚀 Upload & Train Detection Model")
|
259 |
train_btn = gr.Button("Upload & Train")
|
260 |
-
url_out
|
261 |
|
262 |
train_btn.click(
|
263 |
upload_and_train_detection,
|
|
|
3 |
import random
|
4 |
import shutil
|
5 |
import tempfile
|
6 |
+
import time
|
7 |
from urllib.parse import urlparse
|
8 |
|
9 |
import cv2
|
|
|
32 |
3) Split into train/valid/test
|
33 |
4) Return before/after visuals plus (dataset_path, detection_slug)
|
34 |
"""
|
35 |
+
rf = Roboflow(api_key=api_key)
|
36 |
ws, proj_name, ver = parse_roboflow_url(dataset_url)
|
37 |
+
version_obj = rf.workspace(ws).project(proj_name).version(ver)
|
38 |
+
dataset = version_obj.download("coco-segmentation")
|
39 |
+
root = dataset.location
|
40 |
|
41 |
# find the COCO JSON
|
42 |
ann_file = None
|
|
|
50 |
if not ann_file:
|
51 |
raise FileNotFoundError(f"No JSON found under {root}")
|
52 |
|
53 |
+
coco = json.load(open(ann_file, 'r'))
|
54 |
images_info = {img['id']: img for img in coco['images']}
|
55 |
+
cat_ids = sorted(c['id'] for c in coco.get('categories', []))
|
56 |
id_to_index = {cid: idx for idx, cid in enumerate(cat_ids)}
|
57 |
|
58 |
# build YOLO bboxes
|
|
|
71 |
)
|
72 |
annos.setdefault(img_id, []).append(line)
|
73 |
|
74 |
+
# prepare temporary split folder
|
75 |
out_root = tempfile.mkdtemp(prefix="yolov8_")
|
|
|
|
|
|
|
|
|
|
|
76 |
name_to_id = {img['file_name']: img['id'] for img in coco['images']}
|
77 |
file_paths = {
|
78 |
f: os.path.join(dp, f)
|
|
|
81 |
if f in name_to_id
|
82 |
}
|
83 |
|
84 |
+
# determine splits
|
85 |
+
all_files = list(name_to_id.keys())
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
86 |
random.shuffle(all_files)
|
87 |
n = len(all_files)
|
88 |
n_train = max(1, int(n * split_ratios[0]))
|
|
|
94 |
"test": all_files[n_train+n_valid:]
|
95 |
}
|
96 |
|
97 |
+
# create Roboflow‐style folders
|
98 |
for split, files in splits.items():
|
99 |
+
img_dir = os.path.join(out_root, split, "images")
|
100 |
+
lbl_dir = os.path.join(out_root, split, "labels")
|
101 |
os.makedirs(img_dir, exist_ok=True)
|
102 |
os.makedirs(lbl_dir, exist_ok=True)
|
103 |
+
for fname in files:
|
104 |
+
# copy image
|
105 |
+
shutil.copy(file_paths[fname], os.path.join(img_dir, fname))
|
106 |
+
# write label
|
107 |
+
txt = "\n".join(annos.get(name_to_id[fname], []))
|
108 |
+
with open(os.path.join(lbl_dir, fname.rsplit('.',1)[0] + ".txt"), 'w') as f:
|
109 |
+
f.write(txt)
|
110 |
+
|
111 |
+
# prepare display examples
|
112 |
before, after = [], []
|
113 |
+
sample = random.sample(all_files, min(5, len(all_files)))
|
114 |
for fname in sample:
|
115 |
img = cv2.cvtColor(cv2.imread(file_paths[fname]), cv2.COLOR_BGR2RGB)
|
116 |
|
|
|
117 |
seg_vis = img.copy()
|
118 |
for anno in coco['annotations']:
|
119 |
if anno['image_id'] != name_to_id[fname]:
|
|
|
121 |
pts = np.array(anno['segmentation'][0], np.int32).reshape(-1,2)
|
122 |
cv2.polylines(seg_vis, [pts], True, (255,0,0), 2)
|
123 |
|
|
|
124 |
box_vis = img.copy()
|
125 |
for line in annos.get(name_to_id[fname], []):
|
126 |
_, cxn, cyn, wnorm, hnorm = map(float, line.split())
|
|
|
152 |
rf = Roboflow(api_key=api_key)
|
153 |
ws = rf.workspace()
|
154 |
|
155 |
+
# get-or-create project
|
156 |
try:
|
157 |
proj = ws.project(detection_slug)
|
158 |
except Exception as e:
|
|
|
166 |
else:
|
167 |
raise
|
168 |
|
169 |
+
# upload entire split folder
|
170 |
_, real_slug = proj.id.rsplit("/", 1)
|
171 |
ws.upload_dataset(
|
172 |
dataset_path,
|
|
|
175 |
project_type=project_type
|
176 |
)
|
177 |
|
178 |
+
# generate new version (with fallback)
|
179 |
try:
|
180 |
+
version_num = proj.generate_version(settings={"augmentation": {}, "preprocessing": {}})
|
|
|
|
|
|
|
181 |
except RuntimeError as e:
|
182 |
msg = str(e).lower()
|
183 |
if "unsupported request" in msg or "does not exist" in msg:
|
|
|
184 |
new_slug = real_slug + "-v2"
|
185 |
proj = ws.create_project(
|
186 |
new_slug,
|
|
|
188 |
project_type=project_type,
|
189 |
project_license=project_license
|
190 |
)
|
191 |
+
ws.upload_dataset(dataset_path, new_slug,
|
192 |
+
project_license=project_license,
|
193 |
+
project_type=project_type)
|
194 |
+
version_num = proj.generate_version(settings={"augmentation": {}, "preprocessing": {}})
|
|
|
|
|
|
|
|
|
|
|
|
|
195 |
else:
|
196 |
raise
|
197 |
|
198 |
+
# wait until ready, then train
|
199 |
for _ in range(20):
|
200 |
try:
|
201 |
model = proj.version(str(version_num)).train()
|
|
|
215 |
with gr.Blocks() as app:
|
216 |
gr.Markdown("## 🔄 Seg→BBox + Auto‑Upload/Train")
|
217 |
|
218 |
+
api_input = gr.Textbox(label="Roboflow API Key", type="password")
|
219 |
+
url_input = gr.Textbox(label="Segmentation Dataset URL")
|
220 |
+
run_btn = gr.Button("Convert to BBoxes")
|
221 |
+
before_g = gr.Gallery(columns=5, label="Before")
|
222 |
+
after_g = gr.Gallery(columns=5, label="After")
|
223 |
+
ds_state = gr.Textbox(visible=False, label="Converted Dataset Path")
|
224 |
slug_state = gr.Textbox(visible=False, label="Detection Project Slug")
|
225 |
|
226 |
run_btn.click(
|
|
|
231 |
|
232 |
gr.Markdown("## 🚀 Upload & Train Detection Model")
|
233 |
train_btn = gr.Button("Upload & Train")
|
234 |
+
url_out = gr.Textbox(label="Hosted Model Endpoint URL")
|
235 |
|
236 |
train_btn.click(
|
237 |
upload_and_train_detection,
|