Spaces:
Running on Zero
Running on Zero
Deploy GeoAP YOLO26m detection + segmentation Space
Browse files- app.py +17 -0
- requirements.txt +5 -4
- scripts/deploy_space.py +2 -0
- uv.lock +0 -0
- weights/.gitkeep +0 -0
app.py
CHANGED
|
@@ -29,6 +29,21 @@ from src.viz import hex_for
|
|
| 29 |
logging.basicConfig(level=logging.INFO, format="[%(asctime)s] %(levelname)s %(name)s β %(message)s")
|
| 30 |
logger = logging.getLogger("geoap.space")
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
# Gradio 6 moved `theme` from Blocks(...) to launch(...). Support both.
|
| 33 |
GRADIO_MAJOR = int(gr.__version__.split(".")[0])
|
| 34 |
_THEME_ON_LAUNCH = GRADIO_MAJOR >= 6
|
|
@@ -101,6 +116,7 @@ def _no_input():
|
|
| 101 |
return None, [], {"error": "Upload an image first."}, None, PLACEHOLDER
|
| 102 |
|
| 103 |
|
|
|
|
| 104 |
def predict_detection(raster, conf, iou, tile_size, overlap, progress=gr.Progress()):
|
| 105 |
if raster is None:
|
| 106 |
return _no_input()
|
|
@@ -112,6 +128,7 @@ def predict_detection(raster, conf, iou, tile_size, overlap, progress=gr.Progres
|
|
| 112 |
return _finish(res, raster, S.detection_classes, DET_COLORS, "detection")
|
| 113 |
|
| 114 |
|
|
|
|
| 115 |
def predict_segmentation(raster, conf, iou, tile_size, overlap, progress=gr.Progress()):
|
| 116 |
if raster is None:
|
| 117 |
return _no_input()
|
|
|
|
| 29 |
logging.basicConfig(level=logging.INFO, format="[%(asctime)s] %(levelname)s %(name)s β %(message)s")
|
| 30 |
logger = logging.getLogger("geoap.space")
|
| 31 |
|
| 32 |
+
# ββ ZeroGPU ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 33 |
+
# On ZeroGPU hardware a GPU is attached only for the duration of a function
|
| 34 |
+
# marked with @spaces.GPU. The `spaces` package exists only on HF, so locally
|
| 35 |
+
# we fall back to a no-op decorator and nothing changes.
|
| 36 |
+
try:
|
| 37 |
+
import spaces # type: ignore
|
| 38 |
+
|
| 39 |
+
def gpu(duration: int = 120):
|
| 40 |
+
return spaces.GPU(duration=duration)
|
| 41 |
+
except ImportError: # local run / non-ZeroGPU Space
|
| 42 |
+
def gpu(duration: int = 120):
|
| 43 |
+
def _identity(fn):
|
| 44 |
+
return fn
|
| 45 |
+
return _identity
|
| 46 |
+
|
| 47 |
# Gradio 6 moved `theme` from Blocks(...) to launch(...). Support both.
|
| 48 |
GRADIO_MAJOR = int(gr.__version__.split(".")[0])
|
| 49 |
_THEME_ON_LAUNCH = GRADIO_MAJOR >= 6
|
|
|
|
| 116 |
return None, [], {"error": "Upload an image first."}, None, PLACEHOLDER
|
| 117 |
|
| 118 |
|
| 119 |
+
@gpu(duration=120)
|
| 120 |
def predict_detection(raster, conf, iou, tile_size, overlap, progress=gr.Progress()):
|
| 121 |
if raster is None:
|
| 122 |
return _no_input()
|
|
|
|
| 128 |
return _finish(res, raster, S.detection_classes, DET_COLORS, "detection")
|
| 129 |
|
| 130 |
|
| 131 |
+
@gpu(duration=180)
|
| 132 |
def predict_segmentation(raster, conf, iou, tile_size, overlap, progress=gr.Progress()):
|
| 133 |
if raster is None:
|
| 134 |
return _no_input()
|
requirements.txt
CHANGED
|
@@ -11,9 +11,10 @@ pyyaml
|
|
| 11 |
jinja2>=3.1.2 # pandas/Styler backend used by gr.Dataframe
|
| 12 |
rasterio>=1.3 # GeoTIFF reading + CRS reprojection for the map
|
| 13 |
shapely>=2.0
|
| 14 |
-
#
|
| 15 |
-
|
| 16 |
-
# the
|
| 17 |
-
--
|
|
|
|
| 18 |
torch
|
| 19 |
torchvision
|
|
|
|
| 11 |
jinja2>=3.1.2 # pandas/Styler backend used by gr.Dataframe
|
| 12 |
rasterio>=1.3 # GeoTIFF reading + CRS reprojection for the map
|
| 13 |
shapely>=2.0
|
| 14 |
+
# ZeroGPU: allocates a GPU only inside @spaces.GPU-decorated functions.
|
| 15 |
+
spaces>=0.30.0
|
| 16 |
+
# Keep the default (CUDA) torch wheels β ZeroGPU needs them. If you ever move
|
| 17 |
+
# this Space to cpu-basic/cpu-upgrade, add:
|
| 18 |
+
# --extra-index-url https://download.pytorch.org/whl/cpu
|
| 19 |
torch
|
| 20 |
torchvision
|
scripts/deploy_space.py
CHANGED
|
@@ -27,6 +27,8 @@ from src.settings import ROOT, load_settings # noqa: E402
|
|
| 27 |
BASE_IGNORE: List[str] = [
|
| 28 |
".venv/*", "venv/*", "__pycache__/*", "*.pyc", ".git/*", ".gitignore",
|
| 29 |
"runs/*", ".DS_Store", "*.log", ".ipynb_checkpoints/*", "flagged/*",
|
|
|
|
|
|
|
| 30 |
]
|
| 31 |
WEIGHT_IGNORE: List[str] = ["weights/*.pt", "weights/*.onnx", "weights/*.engine"]
|
| 32 |
|
|
|
|
| 27 |
BASE_IGNORE: List[str] = [
|
| 28 |
".venv/*", "venv/*", "__pycache__/*", "*.pyc", ".git/*", ".gitignore",
|
| 29 |
"runs/*", ".DS_Store", "*.log", ".ipynb_checkpoints/*", "flagged/*",
|
| 30 |
+
# secrets β upload_folder does NOT read .gitignore, so list them here too
|
| 31 |
+
"token.txt", "*.token", ".env", ".env.*", "secrets*", "*credentials*",
|
| 32 |
]
|
| 33 |
WEIGHT_IGNORE: List[str] = ["weights/*.pt", "weights/*.onnx", "weights/*.engine"]
|
| 34 |
|
uv.lock
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
weights/.gitkeep
ADDED
|
File without changes
|