Spaces:
Running
Running
File size: 6,273 Bytes
bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 0425447 228a29d 0425447 228a29d 6d361b8 7e2847c 6d361b8 7e2847c 99c4ece 6d361b8 43b1849 228a29d 99c4ece 6d361b8 99c4ece 6d361b8 43b1849 bc6cd18 43b1849 6d361b8 bc6cd18 43b1849 bc6cd18 0425447 bc6cd18 43b1849 bc6cd18 6d361b8 bc6cd18 6d361b8 43b1849 bc6cd18 43b1849 bc6cd18 99c4ece 6d361b8 7e2847c 0425447 6d361b8 228a29d 6d361b8 43b1849 6d361b8 43b1849 bc6cd18 6d361b8 bc6cd18 6d361b8 43b1849 bc6cd18 43b1849 6d361b8 bc6cd18 99c4ece 43b1849 bc6cd18 6d361b8 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 43b1849 bc6cd18 7e2847c 6d361b8 7838f2e 6d361b8 7838f2e bc6cd18 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
import os
import json
import random
import shutil
import tempfile
from urllib.parse import urlparse
import cv2
import numpy as np
from PIL import Image
import gradio as gr
from roboflow import Roboflow
def parse_roboflow_url(url: str):
"""Extract workspace, project name, and version from a Roboflow URL."""
parsed = urlparse(url)
parts = parsed.path.strip('/').split('/')
workspace = parts[0]
project = parts[1]
try:
version = int(parts[-1])
except ValueError:
version = int(parts[-2])
return workspace, project, version
def convert_seg_to_bbox(api_key: str, dataset_url: str):
# 1) download the dataset
rf = Roboflow(api_key=api_key)
ws, proj, ver = parse_roboflow_url(dataset_url)
version_obj = rf.workspace(ws).project(proj).version(ver)
dataset = version_obj.download("coco-segmentation")
root = dataset.location # e.g. "/home/user/app/ds-2"
# --- DEBUG: print out the downloaded directory tree ---
print(f"\n=== Downloaded dataset root: {root} ===")
for dirpath, dirnames, filenames in os.walk(root):
print(f"\nDirectory: {dirpath}")
for d in dirnames:
print(f" [DIR ] {d}")
for f in filenames:
print(f" [FILE] {f}")
print("=== end tree dump ===\n")
# 2) search for any JSON file with "train" in its name
ann_file = None
for dirpath, _, filenames in os.walk(root):
for fname in filenames:
if 'train' in fname.lower() and fname.lower().endswith('.json'):
ann_file = os.path.join(dirpath, fname)
print(f"Found TRAIN annotation file: {ann_file}")
break
if ann_file:
break
# 2b) fallback: first .json anywhere
if ann_file is None:
for dirpath, _, filenames in os.walk(root):
for fname in filenames:
if fname.lower().endswith('.json'):
ann_file = os.path.join(dirpath, fname)
print(f"No TRAIN file—falling back to first JSON: {ann_file}")
break
if ann_file:
break
if ann_file is None:
raise FileNotFoundError(f"No JSON annotations found under {root}")
# 3) load COCO annotations
with open(ann_file, 'r') as f:
coco = json.load(f)
images_info = {img['id']: img for img in coco['images']}
# 4) build category→index map
cat_ids = sorted(c['id'] for c in coco.get('categories', []))
id_to_index = {cid: idx for idx, cid in enumerate(cat_ids)}
# 5) prepare YOLO output directories
out_root = tempfile.mkdtemp(prefix="yolov8_")
img_out = os.path.join(out_root, "images")
lbl_out = os.path.join(out_root, "labels")
os.makedirs(img_out, exist_ok=True)
os.makedirs(lbl_out, exist_ok=True)
print(f"Preparing YOLOv8 output in: {out_root}")
# 6) convert each segmentation annotation to a YOLO bbox line
annos = {}
for anno in coco['annotations']:
img_id = anno['image_id']
poly = anno['segmentation'][0]
xs, ys = poly[0::2], poly[1::2]
x_min, x_max = min(xs), max(xs)
y_min, y_max = min(ys), max(ys)
w, h = x_max - x_min, y_max - y_min
cx, cy = x_min + w/2, y_min + h/2
info = images_info[img_id]
iw, ih = info['width'], info['height']
line = (
f"{id_to_index[anno['category_id']]} "
f"{cx/iw:.6f} {cy/ih:.6f} {w/iw:.6f} {h/ih:.6f}"
)
annos.setdefault(img_id, []).append(line)
# 7) locate your image folder (first with any .jpg/.png)
train_img_dir = None
for dirpath, _, files in os.walk(root):
if any(f.lower().endswith(('.jpg', '.png', '.jpeg')) for f in files):
train_img_dir = dirpath
print(f"Found image directory: {train_img_dir}")
break
if train_img_dir is None:
raise FileNotFoundError(f"No image files found under {root}")
# 8) copy images + write labels
name_to_id = {img['file_name']: img['id'] for img in coco['images']}
for fname, img_id in name_to_id.items():
src = os.path.join(train_img_dir, fname)
if not os.path.isfile(src):
continue
shutil.copy(src, os.path.join(img_out, fname))
lbl_path = os.path.join(lbl_out, fname.rsplit('.', 1)[0] + ".txt")
with open(lbl_path, 'w') as lf:
lf.write("\n".join(annos.get(img_id, [])))
# 9) build before/after galleries
before, after = [], []
sample = random.sample(list(name_to_id.keys()), min(5, len(name_to_id)))
for fname in sample:
src = os.path.join(train_img_dir, fname)
img = cv2.cvtColor(cv2.imread(src), cv2.COLOR_BGR2RGB)
seg_vis = img.copy()
img_id = name_to_id[fname]
for anno in coco['annotations']:
if anno['image_id'] != img_id: continue
pts = np.array(anno['segmentation'][0], dtype=np.int32).reshape(-1, 2)
cv2.polylines(seg_vis, [pts], True, (255, 0, 0), 2)
box_vis = img.copy()
for line in annos.get(img_id, []):
_, cxn, cyn, wnorm, hnorm = map(float, line.split())
iw, ih = images_info[img_id]['width'], images_info[img_id]['height']
w0, h0 = int(wnorm * iw), int(hnorm * ih)
x0 = int(cxn * iw - w0/2)
y0 = int(cyn * ih - h0/2)
cv2.rectangle(box_vis, (x0, y0), (x0 + w0, y0 + h0), (0, 255, 0), 2)
before.append(Image.fromarray(seg_vis))
after.append(Image.fromarray(box_vis))
return before, after
# --- Gradio app ---
with gr.Blocks() as app:
gr.Markdown("# Segmentation → YOLOv8 Converter")
api_input = gr.Textbox(label="Roboflow API Key", type="password")
url_input = gr.Textbox(label="Roboflow Dataset URL (Segmentation)")
run_btn = gr.Button("Convert")
before_gallery = gr.Gallery(label="Before (Segmentation)", columns=5, height="auto")
after_gallery = gr.Gallery(label="After (Bounding Boxes)", columns=5, height="auto")
run_btn.click(
fn=convert_seg_to_bbox,
inputs=[api_input, url_input],
outputs=[before_gallery, after_gallery]
)
if __name__ == "__main__":
app.launch()
|