Download app.py from Ksh508/SSS: direct link, hf CLI and curl.
- Browser
- Download file 4.49 kB
-
https://huggingface.co/spaces/Ksh508/SSS/resolve/main/app.py
- Command line
-
hf download hf://spaces/Ksh508/SSS/app.py
-
curl -L -o app.py https://huggingface.co/spaces/Ksh508/SSS/resolve/main/app.py
4.49 kB
| import subprocess, sys | |
| # Self-install dependencies — runs before any import | |
| subprocess.check_call([ | |
| sys.executable, '-m', 'pip', 'install', | |
| '--quiet', '--no-cache-dir', | |
| 'ultralytics>=8.3.0', | |
| 'pillow>=10.0.0', | |
| 'numpy>=1.24.0' | |
| ]) | |
| import sys | |
| import threading | |
| import gradio as gr | |
| import spaces | |
| from PIL import Image | |
| import numpy as np | |
| def _suppress_fd_warnings(unraisable): | |
| if isinstance(unraisable.exc_value, ValueError) and 'Invalid file descriptor' in str(unraisable.exc_value): | |
| return | |
| sys.__unraisablehook__(unraisable) | |
| sys.unraisablehook = _suppress_fd_warnings | |
| from ultralytics import YOLO | |
| _models = {} | |
| def _load_triage(): | |
| if 'triage' not in _models: | |
| print('Loading triage model...') | |
| _models['triage'] = YOLO('natural_seabed.pt', task='classify') | |
| return _models['triage'] | |
| def _load_detector(key): | |
| if key not in _models: | |
| print(f'Loading {key} model...') | |
| _models[key] = YOLO(f'{key}.pt') | |
| return _models[key] | |
| DETECTOR_KEYS = ['shipwreck', 'subpipes', 'mines', 'cylinder', 'ghostvision'] | |
| def predict_sonar(image, detector_choice, conf_cutoff): | |
| if image is None: | |
| return None, {'error': 'No image provided'} | |
| pil_img = image if isinstance(image, Image.Image) else Image.fromarray(image) | |
| w, h = pil_img.size | |
| # Stage 1: Triage | |
| triage = _load_triage() | |
| t_res = triage.predict(pil_img, imgsz=224, verbose=False)[0] | |
| probs = t_res.probs | |
| prob_clean = float(probs.data[0]) | |
| prob_debris = float(probs.data[1]) | |
| is_anomaly = prob_debris >= 0.35 | |
| # Stage 2: Detection | |
| detections = [] | |
| models_to_run = ( | |
| DETECTOR_KEYS if detector_choice in ('all', 'auto') | |
| else [detector_choice.lower()] | |
| ) | |
| annotated_img = np.array(pil_img) | |
| for m_key in models_to_run: | |
| if m_key not in DETECTOR_KEYS: | |
| continue | |
| model = _load_detector(m_key) | |
| imgsz = 1024 if m_key == 'shipwreck' else (1536 if m_key == 'cylinder' else 640) | |
| det_conf = max(conf_cutoff, 0.28 if m_key == 'shipwreck' else (0.32 if m_key == 'subpipes' else conf_cutoff)) | |
| res = model.predict(pil_img, conf=det_conf, imgsz=imgsz, verbose=False)[0] | |
| if m_key == models_to_run[0]: | |
| annotated_img = res.plot() | |
| for box in res.boxes: | |
| cid = int(box.cls[0]) | |
| score = float(box.conf[0]) | |
| x1, y1, x2, y2 = [float(c) for c in box.xyxy[0].tolist()] | |
| bw = max(0.0, x2 - x1) | |
| bh = max(0.0, y2 - y1) | |
| detections.append({ | |
| 'model': m_key, 'class_id': cid, | |
| 'label': model.names[cid], | |
| 'confidence': round(score, 4), | |
| 'bbox': { | |
| 'x1': round(x1,1), 'y1': round(y1,1), | |
| 'x2': round(x2,1), 'y2': round(y2,1), | |
| 'w': round(bw,1), 'h': round(bh,1), | |
| 'pct_x': round((x1/w)*100,2), 'pct_y': round((y1/h)*100,2), | |
| 'pct_w': round((bw/w)*100,2), 'pct_h': round((bh/h)*100,2), | |
| } | |
| }) | |
| return annotated_img, { | |
| 'triage': { | |
| 'status': 'ABNORMALITY FLAGGED' if is_anomaly else 'CLEAN SEABED', | |
| 'is_anomaly': is_anomaly, | |
| 'prob_debris': round(prob_debris, 4), | |
| 'prob_clean': round(prob_clean, 4), | |
| }, | |
| 'detections_count': len(detections), | |
| 'detections': detections, | |
| } | |
| demo = gr.Interface( | |
| fn=predict_sonar, | |
| inputs=[ | |
| gr.Image(type='pil', label='Side-Scan Sonar Swath'), | |
| gr.Dropdown(choices=['all'] + DETECTOR_KEYS, value='shipwreck', label='Detector'), | |
| gr.Slider(0.05, 0.95, value=0.28, step=0.01, label='Confidence Cutoff'), | |
| ], | |
| outputs=[ | |
| gr.Image(type='numpy', label='Annotated Swath'), | |
| gr.JSON(label='Pipeline Intelligence'), | |
| ], | |
| title='SonarOps Acoustic Intelligence Engine', | |
| description='Dual-Stage AI: Natural Seabed Triage + High-Resolution Target Detectors.', | |
| api_name='predict', | |
| ) | |
| def _preload_all(): | |
| print('Pre-loading all 6 models on CPU...') | |
| _load_triage() | |
| for key in DETECTOR_KEYS: | |
| _load_detector(key) | |
| print('All 6 models ready!') | |
| threading.Thread(target=_preload_all, daemon=True).start() | |
| demo.queue() | |
| demo.launch(ssr_mode=False) | |