Spaces:
Sleeping
Sleeping
Upload folder using huggingface_hub
Browse files- app.py +59 -12
- requirements.txt +1 -0
- samples/CREDITS.txt +1 -1
app.py
CHANGED
|
@@ -34,6 +34,15 @@ from autolabel.export import build_coco
|
|
| 34 |
from autolabel.segment import load_sam2, segment_with_boxes
|
| 35 |
from autolabel.utils import save_json, setup_logging
|
| 36 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
setup_logging(logging.INFO)
|
| 38 |
logger = logging.getLogger(__name__)
|
| 39 |
|
|
@@ -162,32 +171,70 @@ def _get_sam2():
|
|
| 162 |
# Shared inference helpers
|
| 163 |
# ---------------------------------------------------------------------------
|
| 164 |
|
| 165 |
-
def
|
| 166 |
pil_image: Image.Image,
|
| 167 |
prompts: list[str],
|
| 168 |
threshold: float,
|
| 169 |
mode: str,
|
|
|
|
|
|
|
| 170 |
) -> list[dict]:
|
| 171 |
-
"""Run OWLv2 (
|
| 172 |
|
| 173 |
-
|
| 174 |
-
|
| 175 |
"""
|
| 176 |
-
processor,
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
|
| 182 |
if mode == "Segmentation" and detections:
|
| 183 |
sam2_processor, sam2_model = _get_sam2()
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
return detections
|
| 189 |
|
| 190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 191 |
def _parse_prompts(text: str) -> list[str]:
|
| 192 |
return [p.strip() for p in text.split(",") if p.strip()]
|
| 193 |
|
|
|
|
| 34 |
from autolabel.segment import load_sam2, segment_with_boxes
|
| 35 |
from autolabel.utils import save_json, setup_logging
|
| 36 |
|
| 37 |
+
# HuggingFace ZeroGPU: GPU is only available inside @spaces.GPU-decorated
|
| 38 |
+
# functions. Import gracefully so the app still runs locally without it.
|
| 39 |
+
try:
|
| 40 |
+
import spaces as _spaces # type: ignore
|
| 41 |
+
_ZERO_GPU = True
|
| 42 |
+
except ImportError:
|
| 43 |
+
_spaces = None
|
| 44 |
+
_ZERO_GPU = False
|
| 45 |
+
|
| 46 |
setup_logging(logging.INFO)
|
| 47 |
logger = logging.getLogger(__name__)
|
| 48 |
|
|
|
|
| 171 |
# Shared inference helpers
|
| 172 |
# ---------------------------------------------------------------------------
|
| 173 |
|
| 174 |
+
def _infer_on_device(
|
| 175 |
pil_image: Image.Image,
|
| 176 |
prompts: list[str],
|
| 177 |
threshold: float,
|
| 178 |
mode: str,
|
| 179 |
+
device: str,
|
| 180 |
+
dtype,
|
| 181 |
) -> list[dict]:
|
| 182 |
+
"""Run OWLv2 (+ optional SAM2) with explicit device/dtype.
|
| 183 |
|
| 184 |
+
In ZeroGPU mode this is called inside the @spaces.GPU context so CUDA is
|
| 185 |
+
available; locally it uses whatever settings.device resolved to.
|
| 186 |
"""
|
| 187 |
+
processor, owlv2 = _get_owlv2()
|
| 188 |
+
owlv2.to(device)
|
| 189 |
+
try:
|
| 190 |
+
detections = _owlv2_infer(
|
| 191 |
+
pil_image, processor, owlv2, prompts, threshold, device, dtype,
|
| 192 |
+
)
|
| 193 |
+
finally:
|
| 194 |
+
if _ZERO_GPU:
|
| 195 |
+
owlv2.to("cpu") # release VRAM back to ZeroGPU pool
|
| 196 |
|
| 197 |
if mode == "Segmentation" and detections:
|
| 198 |
sam2_processor, sam2_model = _get_sam2()
|
| 199 |
+
sam2_model.to(device)
|
| 200 |
+
try:
|
| 201 |
+
detections = segment_with_boxes(
|
| 202 |
+
pil_image, detections, sam2_processor, sam2_model, device
|
| 203 |
+
)
|
| 204 |
+
finally:
|
| 205 |
+
if _ZERO_GPU:
|
| 206 |
+
sam2_model.to("cpu")
|
| 207 |
|
| 208 |
return detections
|
| 209 |
|
| 210 |
|
| 211 |
+
if _ZERO_GPU:
|
| 212 |
+
@_spaces.GPU
|
| 213 |
+
def _run_detection(
|
| 214 |
+
pil_image: Image.Image,
|
| 215 |
+
prompts: list[str],
|
| 216 |
+
threshold: float,
|
| 217 |
+
mode: str,
|
| 218 |
+
) -> list[dict]:
|
| 219 |
+
"""ZeroGPU entry-point: GPU is allocated for the duration of this call."""
|
| 220 |
+
import torch
|
| 221 |
+
return _infer_on_device(
|
| 222 |
+
pil_image, prompts, threshold, mode,
|
| 223 |
+
device="cuda", dtype=torch.float16,
|
| 224 |
+
)
|
| 225 |
+
else:
|
| 226 |
+
def _run_detection(
|
| 227 |
+
pil_image: Image.Image,
|
| 228 |
+
prompts: list[str],
|
| 229 |
+
threshold: float,
|
| 230 |
+
mode: str,
|
| 231 |
+
) -> list[dict]:
|
| 232 |
+
return _infer_on_device(
|
| 233 |
+
pil_image, prompts, threshold, mode,
|
| 234 |
+
device=settings.device, dtype=settings.torch_dtype,
|
| 235 |
+
)
|
| 236 |
+
|
| 237 |
+
|
| 238 |
def _parse_prompts(text: str) -> list[str]:
|
| 239 |
return [p.strip() for p in text.split(",") if p.strip()]
|
| 240 |
|
requirements.txt
CHANGED
|
@@ -11,3 +11,4 @@ click>=8.1.7
|
|
| 11 |
tqdm>=4.66.0
|
| 12 |
python-dotenv>=1.0.1
|
| 13 |
gradio>=6.0.0
|
|
|
|
|
|
| 11 |
tqdm>=4.66.0
|
| 12 |
python-dotenv>=1.0.1
|
| 13 |
gradio>=6.0.0
|
| 14 |
+
spaces
|
samples/CREDITS.txt
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
Sample images used in the autolabel demo
|
| 2 |
=========================================
|
| 3 |
|
| 4 |
kitchen.jpg
|
|
|
|
| 1 |
+
Cool Sample images used in the autolabel demo
|
| 2 |
=========================================
|
| 3 |
|
| 4 |
kitchen.jpg
|