Raise configured YOLO max detections
This commit is contained in:
@@ -359,6 +359,7 @@ YOLO_CONFIG_DIR=/app/storage/ultralytics
|
||||
YOLO_DEVICE=cpu
|
||||
YOLO_IMAGE_SIZE=640
|
||||
YOLO_MAX_TILES=100
|
||||
YOLO_MAX_DETECTIONS=1000
|
||||
YOLO_BATCH_SIZE=1
|
||||
```
|
||||
|
||||
@@ -384,6 +385,10 @@ python scripts/yolo_preflight.py --model-path /absolute/path/to/local-model.pt -
|
||||
|
||||
The preflight checks configuration, dependency availability, local model file existence, tile manifest validity, tile count and referenced tile paths. JSON output also includes runtime diagnostics for the model directory, `YOLO_CONFIG_DIR`, installed `torch`/`ultralytics` versions and CUDA availability when dependency checks pass. It does not load a YOLO model, run inference or download weights.
|
||||
|
||||
`YOLO_MAX_DETECTIONS` is forwarded to Ultralytics as `max_det`. The default is
|
||||
`1000` because dense building AOIs can exceed the upstream default cap of 300
|
||||
detections before QA/QC can measure recall honestly.
|
||||
|
||||
The same read-only status is available through the API and Detection Lab UI:
|
||||
|
||||
```bash
|
||||
|
||||
@@ -31,6 +31,7 @@ class Settings(BaseSettings):
|
||||
yolo_device: str = Field(default="cpu", validation_alias="YOLO_DEVICE")
|
||||
yolo_image_size: int = Field(default=640, validation_alias="YOLO_IMAGE_SIZE")
|
||||
yolo_max_tiles: int = Field(default=100, validation_alias="YOLO_MAX_TILES")
|
||||
yolo_max_detections: int = Field(default=1000, validation_alias="YOLO_MAX_DETECTIONS")
|
||||
yolo_batch_size: int = Field(default=1, validation_alias="YOLO_BATCH_SIZE")
|
||||
cors_origins: list[str] | str = Field(
|
||||
default=["http://localhost:5173", "http://127.0.0.1:5173"],
|
||||
|
||||
@@ -72,6 +72,7 @@ class YoloDetectionAdapter:
|
||||
conf=float(confidence_threshold),
|
||||
imgsz=int(self.settings.yolo_image_size),
|
||||
device=self.settings.yolo_device,
|
||||
max_det=int(self.settings.yolo_max_detections),
|
||||
verbose=False,
|
||||
)
|
||||
except AppError:
|
||||
|
||||
@@ -93,6 +93,7 @@ def test_env_example_uses_runtime_env_names_read_by_backend_and_frontend() -> No
|
||||
assert "YOLO_MODEL_PATH=" in env_example
|
||||
assert "YOLO_CONFIG_DIR=./storage/ultralytics" in env_example
|
||||
assert "YOLO_MAX_TILES=100" in env_example
|
||||
assert "YOLO_MAX_DETECTIONS=1000" in env_example
|
||||
assert "ENABLE_YOLO" not in env_example
|
||||
assert "ENABLE_SAM" not in env_example
|
||||
assert "VITE_API_BASE_URL=" in env_example
|
||||
@@ -245,4 +246,5 @@ def test_unraid_deploy_passes_ai_build_arg_and_yolo_runtime_env() -> None:
|
||||
assert '-e YOLO_MODELS_DIR="$YOLO_MODELS_DIR"' in run_script
|
||||
assert '-e YOLO_MODEL_PATH="$YOLO_MODEL_PATH"' in run_script
|
||||
assert '-e YOLO_MAX_TILES="$YOLO_MAX_TILES"' in run_script
|
||||
assert '-e YOLO_MAX_DETECTIONS="$YOLO_MAX_DETECTIONS"' in run_script
|
||||
assert "-v \"${GEOINTEL_MODELS_PATH}:/app/models\"" in run_script
|
||||
|
||||
@@ -93,7 +93,7 @@ class RecordingPredictModel:
|
||||
def __init__(self) -> None:
|
||||
self.seen_sources: list[dict] = []
|
||||
|
||||
def predict(self, *, source, conf, imgsz, device, verbose):
|
||||
def predict(self, *, source, conf, imgsz, device, verbose, max_det):
|
||||
from PIL import Image
|
||||
|
||||
with Image.open(source) as image:
|
||||
@@ -106,6 +106,7 @@ class RecordingPredictModel:
|
||||
"imgsz": imgsz,
|
||||
"device": device,
|
||||
"verbose": verbose,
|
||||
"max_det": max_det,
|
||||
}
|
||||
)
|
||||
return []
|
||||
@@ -399,6 +400,20 @@ def test_yolo_adapter_converts_single_band_tiles_to_rgb_before_prediction(tmp_pa
|
||||
assert model.seen_sources[0]["imgsz"] == 64
|
||||
assert model.seen_sources[0]["device"] == "cpu"
|
||||
assert model.seen_sources[0]["verbose"] is False
|
||||
assert model.seen_sources[0]["max_det"] == 1000
|
||||
|
||||
|
||||
def test_yolo_adapter_uses_configured_max_detections(tmp_path: Path) -> None:
|
||||
Image = pytest.importorskip("PIL.Image")
|
||||
tile_path = tmp_path / "rgb_tile.png"
|
||||
Image.new("RGB", (16, 16), (10, 20, 30)).save(tile_path)
|
||||
model = RecordingPredictModel()
|
||||
settings = _settings(tmp_path, yolo_max_detections=1500)
|
||||
|
||||
detections = YoloDetectionAdapter(settings).predict_tile(model, tile_path, confidence_threshold=0.25)
|
||||
|
||||
assert detections == []
|
||||
assert model.seen_sources[0]["max_det"] == 1500
|
||||
|
||||
|
||||
def test_yolo_adapter_wraps_prediction_runtime_errors(tmp_path: Path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user