Spaces:
Runtime error
Runtime error
Desert segmentation Gradio Space
Browse files- .gitattributes +2 -0
- HUGGINGFACE_SPACES.md +93 -0
- README_HF_SPACES.md +19 -0
- app.py +85 -0
- packages.txt +5 -0
- requirements.txt +2 -0
- scripts/demo_gradio.py +68 -44
.gitattributes
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Use Git LFS for checkpoints when pushing to Hugging Face (avoids hard size limits).
|
| 2 |
+
*.pt filter=lfs diff=lfs merge=lfs -text
|
HUGGINGFACE_SPACES.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Deploy this project to Hugging Face Spaces
|
| 2 |
+
|
| 3 |
+
Your Space: `https://huggingface.co/spaces/webVishnu/code-wizards` (replace if yours differs).
|
| 4 |
+
|
| 5 |
+
## 1. One-time: access token
|
| 6 |
+
|
| 7 |
+
Create a token with **write** access: [Settings → Access Tokens](https://huggingface.co/settings/tokens).
|
| 8 |
+
|
| 9 |
+
## 2. Connect git to the Space
|
| 10 |
+
|
| 11 |
+
From **this repository root** (where `app.py` lives). If this folder is **already** a git repo, skip `git init`.
|
| 12 |
+
|
| 13 |
+
```powershell
|
| 14 |
+
git remote add space https://huggingface.co/spaces/webVishnu/code-wizards
|
| 15 |
+
```
|
| 16 |
+
|
| 17 |
+
If `git remote add` fails because `space` exists, use `git remote set-url space https://huggingface.co/spaces/webVishnu/code-wizards`.
|
| 18 |
+
|
| 19 |
+
Stage what the Space needs (trim paths you do not want public):
|
| 20 |
+
|
| 21 |
+
```powershell
|
| 22 |
+
git add app.py requirements.txt packages.txt .gitattributes desert_segmentation scripts
|
| 23 |
+
git add HUGGINGFACE_SPACES.md README_HF_SPACES.md
|
| 24 |
+
```
|
| 25 |
+
|
| 26 |
+
Optional: `git add eval_summary.json` (validation accuracy in the UI). Optional: `git add checkpoints/best.pt` (only with **Git LFS**; see step 3).
|
| 27 |
+
|
| 28 |
+
- Add **`checkpoints/best.pt`** only if you use a file in the repo (use **Git LFS**; see below). Otherwise use Hub download (step 4).
|
| 29 |
+
- Do **not** commit huge `training/` folders unless you intend to; the demo only needs code + weights + optional `eval_summary.json`.
|
| 30 |
+
|
| 31 |
+
**Space README (card + Gradio metadata):** Hugging Face reads **`README.md`** at the Space repo root (YAML frontmatter + markdown).
|
| 32 |
+
|
| 33 |
+
- **Easiest (does not touch your local GitHub README):** After the first successful push, open the Space → **Files** → `README.md` → **Edit**, delete the boilerplate, and **paste the full contents of `README_HF_SPACES.md`**, then commit on the Hub.
|
| 34 |
+
- **If this folder is only for the Space:** you can `git add` a `README.md` that is a copy of `README_HF_SPACES.md` (rename the file to `README.md` before committing).
|
| 35 |
+
- **If you use one git repo for both GitHub and HF:** do **not** overwrite your long `README.md`; use the Hub web editor for the Space card, or maintain a dedicated branch for the Space with a short `README.md`.
|
| 36 |
+
|
| 37 |
+
## 3. Git LFS for `best.pt` (if the checkpoint lives in the repo)
|
| 38 |
+
|
| 39 |
+
```powershell
|
| 40 |
+
git lfs install
|
| 41 |
+
git lfs track "*.pt"
|
| 42 |
+
git add .gitattributes checkpoints/best.pt
|
| 43 |
+
```
|
| 44 |
+
|
| 45 |
+
## 4. Weights without committing the file (recommended for large checkpoints)
|
| 46 |
+
|
| 47 |
+
1. Create a **Model** repository on the Hub and upload `best.pt` (with LFS).
|
| 48 |
+
2. In the Space → **Settings → Repository secrets**, add nothing extra for public models.
|
| 49 |
+
3. In the Space → **Settings → Variables** (or **Secrets**), add:
|
| 50 |
+
- **`HF_HUB_CHECKPOINT_REPO`** = your model repo id, e.g. `webVishnu/desert-seg-best`
|
| 51 |
+
- **`HF_HUB_CHECKPOINT_FILENAME`** = `best.pt` (optional if the filename is `best.pt`)
|
| 52 |
+
|
| 53 |
+
`app.py` will download the file on startup. For a **private** model repo, add a read token as **`HF_TOKEN`** (secret).
|
| 54 |
+
|
| 55 |
+
Alternatively set **`CHECKPOINT_PATH`** to an absolute path inside the container (rare).
|
| 56 |
+
|
| 57 |
+
## 5. Optional: validation accuracy line in the UI
|
| 58 |
+
|
| 59 |
+
Commit **`eval_summary.json`** at the repo root (same layout as local). The demo shows **Accuracy (val)** when `global_pixel_accuracy` is present.
|
| 60 |
+
|
| 61 |
+
## 6. Hardware
|
| 62 |
+
|
| 63 |
+
Space **Settings → Hardware**: start with **CPU** to verify the build; switch to **GPU** (e.g. T4) for usable speed. Update the `hardware:` field in the Space `README.md` YAML if you use a template that expects it.
|
| 64 |
+
|
| 65 |
+
## 7. Push
|
| 66 |
+
|
| 67 |
+
```powershell
|
| 68 |
+
git commit -m "Add Gradio Space app and dependencies"
|
| 69 |
+
git push space main
|
| 70 |
+
```
|
| 71 |
+
|
| 72 |
+
If the default branch on the Hub is `main`, use `main`. Use your **token** as the password when Git asks.
|
| 73 |
+
|
| 74 |
+
## 8. Verify
|
| 75 |
+
|
| 76 |
+
Open the **App** tab. When the container builds, you should see the demo (first load downloads weights if using Hub env vars).
|
| 77 |
+
|
| 78 |
+
## Environment variables reference
|
| 79 |
+
|
| 80 |
+
| Variable | Purpose |
|
| 81 |
+
|----------|---------|
|
| 82 |
+
| `CHECKPOINT_PATH` | Path to `.pt` if bundled or mounted |
|
| 83 |
+
| `HF_HUB_CHECKPOINT_REPO` | Model repo id for `hf_hub_download` |
|
| 84 |
+
| `HF_HUB_CHECKPOINT_FILENAME` | Filename in that repo (default `best.pt`) |
|
| 85 |
+
| `HF_TOKEN` | Read token for private Hub weights |
|
| 86 |
+
| `DEMO_MAX_SIDE` | Max image side (default `4096`) |
|
| 87 |
+
| `DEMO_MAX_MEGAPIXELS` | Max megapixels (default `16`) |
|
| 88 |
+
|
| 89 |
+
Local run still works:
|
| 90 |
+
|
| 91 |
+
```powershell
|
| 92 |
+
python scripts/demo_gradio.py --checkpoint checkpoints/best.pt
|
| 93 |
+
```
|
README_HF_SPACES.md
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Desert semantic segmentation
|
| 3 |
+
emoji: 🏜️
|
| 4 |
+
colorFrom: yellow
|
| 5 |
+
colorTo: orange
|
| 6 |
+
sdk: gradio
|
| 7 |
+
app_file: app.py
|
| 8 |
+
pinned: false
|
| 9 |
+
license: apache-2.0
|
| 10 |
+
short_description: Upload a desert/off-road RGB image and get a per-pixel class mask, overlay, and metrics.
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# Desert semantic segmentation
|
| 14 |
+
|
| 15 |
+
Interactive **semantic segmentation** demo: each pixel is classified into terrain / scene categories. Upload an RGB image, click **Run segmentation**, and view the colored mask, overlay, strip, timing, optional **validation accuracy**, and dominant classes.
|
| 16 |
+
|
| 17 |
+
**Weights:** configure `CHECKPOINT_PATH`, or `HF_HUB_CHECKPOINT_REPO` (+ optional `HF_HUB_CHECKPOINT_FILENAME`), or commit `checkpoints/best.pt` (prefer **Git LFS**). See `HUGGINGFACE_SPACES.md` in the project repository.
|
| 18 |
+
|
| 19 |
+
**Hardware:** CPU works but is slow; enable a **GPU** in Space settings for responsive inference.
|
app.py
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Hugging Face Spaces entrypoint: exposes ``demo`` for the Gradio SDK.
|
| 3 |
+
|
| 4 |
+
Checkpoint resolution (first match wins):
|
| 5 |
+
1. ``CHECKPOINT_PATH`` — absolute or relative to repo root, file must exist.
|
| 6 |
+
2. ``HF_HUB_CHECKPOINT_REPO`` + optional ``HF_HUB_CHECKPOINT_FILENAME`` (default ``best.pt``)
|
| 7 |
+
— downloads from the Hub (use a Model repo; set Space secret ``HF_TOKEN`` if private).
|
| 8 |
+
3. ``<repo_root>/checkpoints/best.pt``
|
| 9 |
+
|
| 10 |
+
Optional: ``eval_summary.json`` at repo root enables **Accuracy (val)** in the UI.
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
from __future__ import annotations
|
| 14 |
+
|
| 15 |
+
import logging
|
| 16 |
+
import os
|
| 17 |
+
import sys
|
| 18 |
+
from pathlib import Path
|
| 19 |
+
from typing import Optional
|
| 20 |
+
|
| 21 |
+
ROOT = Path(__file__).resolve().parent
|
| 22 |
+
if str(ROOT) not in sys.path:
|
| 23 |
+
sys.path.insert(0, str(ROOT))
|
| 24 |
+
|
| 25 |
+
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
| 26 |
+
|
| 27 |
+
logger = logging.getLogger("app")
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _resolve_checkpoint(root: Path) -> Path:
|
| 31 |
+
env_path = os.environ.get("CHECKPOINT_PATH", "").strip()
|
| 32 |
+
if env_path:
|
| 33 |
+
p = Path(env_path)
|
| 34 |
+
if not p.is_absolute():
|
| 35 |
+
p = (root / p).resolve()
|
| 36 |
+
else:
|
| 37 |
+
p = p.resolve()
|
| 38 |
+
if p.is_file():
|
| 39 |
+
logger.info("Using checkpoint from CHECKPOINT_PATH=%s", p)
|
| 40 |
+
return p
|
| 41 |
+
logger.warning("CHECKPOINT_PATH set but not a file: %s", p)
|
| 42 |
+
|
| 43 |
+
hub_repo = os.environ.get("HF_HUB_CHECKPOINT_REPO", "").strip()
|
| 44 |
+
if hub_repo:
|
| 45 |
+
from huggingface_hub import hf_hub_download
|
| 46 |
+
|
| 47 |
+
fn = os.environ.get("HF_HUB_CHECKPOINT_FILENAME", "best.pt").strip() or "best.pt"
|
| 48 |
+
token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
|
| 49 |
+
path = hf_hub_download(repo_id=hub_repo, filename=fn, token=token)
|
| 50 |
+
p = Path(path).resolve()
|
| 51 |
+
logger.info("Downloaded checkpoint from Hub repo=%s file=%s -> %s", hub_repo, fn, p)
|
| 52 |
+
return p
|
| 53 |
+
|
| 54 |
+
cand = root / "checkpoints" / "best.pt"
|
| 55 |
+
if cand.is_file():
|
| 56 |
+
logger.info("Using bundled checkpoint %s", cand)
|
| 57 |
+
return cand.resolve()
|
| 58 |
+
|
| 59 |
+
raise FileNotFoundError(
|
| 60 |
+
"No weights found. Do one of: "
|
| 61 |
+
"(1) Set Space secret / env CHECKPOINT_PATH to your .pt file, "
|
| 62 |
+
"(2) Set HF_HUB_CHECKPOINT_REPO (and optional HF_HUB_CHECKPOINT_FILENAME) to a Model repo, "
|
| 63 |
+
f"(3) Add checkpoints/best.pt under {root} (use Git LFS for large files)."
|
| 64 |
+
)
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def _resolve_eval_summary(root: Path) -> Optional[Path]:
|
| 68 |
+
p = root / "eval_summary.json"
|
| 69 |
+
return p if p.is_file() else None
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
_checkpoint = _resolve_checkpoint(ROOT)
|
| 73 |
+
_eval_summary = _resolve_eval_summary(ROOT)
|
| 74 |
+
|
| 75 |
+
from scripts.demo_gradio import create_demo # noqa: E402
|
| 76 |
+
|
| 77 |
+
_max_side = int(os.environ.get("DEMO_MAX_SIDE", "4096"))
|
| 78 |
+
_max_mp = float(os.environ.get("DEMO_MAX_MEGAPIXELS", "16"))
|
| 79 |
+
|
| 80 |
+
demo = create_demo(
|
| 81 |
+
_checkpoint,
|
| 82 |
+
_eval_summary,
|
| 83 |
+
max_side=_max_side,
|
| 84 |
+
max_megapixels=_max_mp,
|
| 85 |
+
)
|
packages.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# System packages for Spaces (OpenCV / headless image stack). Safe to ignore locally.
|
| 2 |
+
libglib2.0-0
|
| 3 |
+
libsm6
|
| 4 |
+
libxext6
|
| 5 |
+
libxrender1
|
requirements.txt
CHANGED
|
@@ -8,3 +8,5 @@ albumentations>=1.3.1,<1.5
|
|
| 8 |
segmentation-models-pytorch>=0.3.3
|
| 9 |
tqdm>=4.66.0
|
| 10 |
pytest>=7.4.0
|
|
|
|
|
|
|
|
|
| 8 |
segmentation-models-pytorch>=0.3.3
|
| 9 |
tqdm>=4.66.0
|
| 10 |
pytest>=7.4.0
|
| 11 |
+
gradio>=4.44.0,<6
|
| 12 |
+
huggingface_hub>=0.20.0
|
scripts/demo_gradio.py
CHANGED
|
@@ -176,49 +176,20 @@ def _run(
|
|
| 176 |
return rgb, colored, overlay, strip, stats, dominant
|
| 177 |
|
| 178 |
|
| 179 |
-
def
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
help="Path to best.pt (default: env CHECKPOINT_PATH or <root>/checkpoints/best.pt)",
|
| 189 |
-
)
|
| 190 |
-
parser.add_argument("--host", type=str, default="127.0.0.1")
|
| 191 |
-
parser.add_argument("--port", type=int, default=7860)
|
| 192 |
-
parser.add_argument("--share", action="store_true", help="Create a temporary public Gradio link")
|
| 193 |
-
parser.add_argument("--max-side", type=int, default=4096)
|
| 194 |
-
parser.add_argument("--max-megapixels", type=float, default=16.0)
|
| 195 |
-
parser.add_argument(
|
| 196 |
-
"--eval-summary",
|
| 197 |
-
type=str,
|
| 198 |
-
default=None,
|
| 199 |
-
help="Optional path to eval_summary.json (default: <root>/eval_summary.json if that file exists)",
|
| 200 |
-
)
|
| 201 |
-
args = parser.parse_args()
|
| 202 |
-
|
| 203 |
-
root = Path(args.root or ROOT).resolve()
|
| 204 |
-
ckpt_arg = args.checkpoint or str(root / "checkpoints" / "best.pt")
|
| 205 |
-
ckpt = Path(ckpt_arg)
|
| 206 |
-
if not ckpt.is_absolute():
|
| 207 |
-
ckpt = (root / ckpt).resolve()
|
| 208 |
if not ckpt.is_file():
|
| 209 |
-
raise
|
| 210 |
-
|
| 211 |
-
eval_summary_arg = args.eval_summary
|
| 212 |
-
if eval_summary_arg:
|
| 213 |
-
eval_summary = Path(eval_summary_arg)
|
| 214 |
-
if not eval_summary.is_absolute():
|
| 215 |
-
eval_summary = (root / eval_summary).resolve()
|
| 216 |
-
else:
|
| 217 |
-
cand = root / "eval_summary.json"
|
| 218 |
-
eval_summary = cand if cand.is_file() else None
|
| 219 |
|
| 220 |
-
|
| 221 |
-
_init_state(ckpt,
|
| 222 |
|
| 223 |
icfg = _STATE["icfg"]
|
| 224 |
def_tta = bool(icfg.get("tta_flip", True))
|
|
@@ -239,7 +210,7 @@ _Confidence heatmaps for full-resolution sliding windows are not in this demo (v
|
|
| 239 |
"""
|
| 240 |
|
| 241 |
cpu_note = ""
|
| 242 |
-
if
|
| 243 |
cpu_note = "\n\n> Running on **CPU** — expect slower inference. Use a CUDA GPU for best speed.\n"
|
| 244 |
|
| 245 |
with gr.Blocks(title="Desert segmentation", theme=gr.themes.Soft()) as demo:
|
|
@@ -261,8 +232,8 @@ _Confidence heatmaps for full-resolution sliding windows are not in this demo (v
|
|
| 261 |
gr.Markdown("### Class legend (fixed palette)")
|
| 262 |
gr.HTML(_STATE["legend_html_static"])
|
| 263 |
|
| 264 |
-
def _fn(img, tta, ov, ts):
|
| 265 |
-
return _run(img, tta, ov, ts,
|
| 266 |
|
| 267 |
run_btn.click(
|
| 268 |
fn=_fn,
|
|
@@ -270,6 +241,59 @@ _Confidence heatmaps for full-resolution sliding windows are not in this demo (v
|
|
| 270 |
outputs=[out_orig, out_mask, out_overlay, out_strip, stats_md, dominant_md],
|
| 271 |
)
|
| 272 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 273 |
logger.info("Launching Gradio on http://%s:%s", args.host, args.port)
|
| 274 |
demo.launch(server_name=args.host, server_port=args.port, share=args.share)
|
| 275 |
|
|
|
|
| 176 |
return rgb, colored, overlay, strip, stats, dominant
|
| 177 |
|
| 178 |
|
| 179 |
+
def create_demo(
|
| 180 |
+
checkpoint: Path,
|
| 181 |
+
eval_summary: Optional[Path],
|
| 182 |
+
max_side: int = 4096,
|
| 183 |
+
max_megapixels: float = 16.0,
|
| 184 |
+
device: Optional[torch.device] = None,
|
| 185 |
+
) -> gr.Blocks:
|
| 186 |
+
"""Build the Gradio Blocks app (Hugging Face Spaces: assign ``demo = create_demo(...)``; do not call ``launch``)."""
|
| 187 |
+
ckpt = checkpoint.resolve()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 188 |
if not ckpt.is_file():
|
| 189 |
+
raise FileNotFoundError(f"Checkpoint not found: {ckpt}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 190 |
|
| 191 |
+
dev = device or torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 192 |
+
_init_state(ckpt, dev, eval_summary)
|
| 193 |
|
| 194 |
icfg = _STATE["icfg"]
|
| 195 |
def_tta = bool(icfg.get("tta_flip", True))
|
|
|
|
| 210 |
"""
|
| 211 |
|
| 212 |
cpu_note = ""
|
| 213 |
+
if dev.type == "cpu":
|
| 214 |
cpu_note = "\n\n> Running on **CPU** — expect slower inference. Use a CUDA GPU for best speed.\n"
|
| 215 |
|
| 216 |
with gr.Blocks(title="Desert segmentation", theme=gr.themes.Soft()) as demo:
|
|
|
|
| 232 |
gr.Markdown("### Class legend (fixed palette)")
|
| 233 |
gr.HTML(_STATE["legend_html_static"])
|
| 234 |
|
| 235 |
+
def _fn(img: Any, tta: bool, ov: float, ts: float) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray, str, str]:
|
| 236 |
+
return _run(img, tta, ov, ts, max_side, max_megapixels)
|
| 237 |
|
| 238 |
run_btn.click(
|
| 239 |
fn=_fn,
|
|
|
|
| 241 |
outputs=[out_orig, out_mask, out_overlay, out_strip, stats_md, dominant_md],
|
| 242 |
)
|
| 243 |
|
| 244 |
+
return demo
|
| 245 |
+
|
| 246 |
+
|
| 247 |
+
def main() -> None:
|
| 248 |
+
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
|
| 249 |
+
|
| 250 |
+
parser = argparse.ArgumentParser(description="Gradio demo for desert semantic segmentation")
|
| 251 |
+
parser.add_argument("--root", type=str, default=os.environ.get("ROOT"), help="Workspace root (default: repo root or env ROOT)")
|
| 252 |
+
parser.add_argument(
|
| 253 |
+
"--checkpoint",
|
| 254 |
+
type=str,
|
| 255 |
+
default=os.environ.get("CHECKPOINT_PATH"),
|
| 256 |
+
help="Path to best.pt (default: env CHECKPOINT_PATH or <root>/checkpoints/best.pt)",
|
| 257 |
+
)
|
| 258 |
+
parser.add_argument("--host", type=str, default="127.0.0.1")
|
| 259 |
+
parser.add_argument("--port", type=int, default=7860)
|
| 260 |
+
parser.add_argument("--share", action="store_true", help="Create a temporary public Gradio link")
|
| 261 |
+
parser.add_argument("--max-side", type=int, default=4096)
|
| 262 |
+
parser.add_argument("--max-megapixels", type=float, default=16.0)
|
| 263 |
+
parser.add_argument(
|
| 264 |
+
"--eval-summary",
|
| 265 |
+
type=str,
|
| 266 |
+
default=None,
|
| 267 |
+
help="Optional path to eval_summary.json (default: <root>/eval_summary.json if that file exists)",
|
| 268 |
+
)
|
| 269 |
+
args = parser.parse_args()
|
| 270 |
+
|
| 271 |
+
root = Path(args.root or ROOT).resolve()
|
| 272 |
+
ckpt_arg = args.checkpoint or str(root / "checkpoints" / "best.pt")
|
| 273 |
+
ckpt = Path(ckpt_arg)
|
| 274 |
+
if not ckpt.is_absolute():
|
| 275 |
+
ckpt = (root / ckpt).resolve()
|
| 276 |
+
if not ckpt.is_file():
|
| 277 |
+
raise SystemExit(f"Checkpoint not found: {ckpt}")
|
| 278 |
+
|
| 279 |
+
eval_summary_arg = args.eval_summary
|
| 280 |
+
if eval_summary_arg:
|
| 281 |
+
eval_summary = Path(eval_summary_arg)
|
| 282 |
+
if not eval_summary.is_absolute():
|
| 283 |
+
eval_summary = (root / eval_summary).resolve()
|
| 284 |
+
else:
|
| 285 |
+
cand = root / "eval_summary.json"
|
| 286 |
+
eval_summary = cand if cand.is_file() else None
|
| 287 |
+
|
| 288 |
+
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
|
| 289 |
+
demo = create_demo(
|
| 290 |
+
ckpt,
|
| 291 |
+
eval_summary,
|
| 292 |
+
max_side=args.max_side,
|
| 293 |
+
max_megapixels=args.max_megapixels,
|
| 294 |
+
device=device,
|
| 295 |
+
)
|
| 296 |
+
|
| 297 |
logger.info("Launching Gradio on http://%s:%s", args.host, args.port)
|
| 298 |
demo.launch(server_name=args.host, server_port=args.port, share=args.share)
|
| 299 |
|