ARViewer / api /responses.py
wizardsmagic's picture
Add Wizara Vision API endpoints without changing UI or inference.
3820d5b
Raw
History Blame Contribute Delete
3.52 kB
"""Standardized JSON responses for the Wizara Vision API."""
from __future__ import annotations
import json
import os
from typing import Any
PROVIDER_NAME = "LocateAnything"
DEFAULT_MODEL_NAME = "LocateAnything-3B"
def model_name() -> str:
path = os.environ.get("MODEL_PATH", DEFAULT_MODEL_NAME)
return path.split("/")[-1] if "/" in path else path
def success_response(
*,
image_width: int,
image_height: int,
objects: list[dict[str, Any]],
task: str,
extra: dict[str, Any] | None = None,
) -> dict[str, Any]:
payload: dict[str, Any] = {
"success": True,
"provider": PROVIDER_NAME,
"model": model_name(),
"task": task,
"image": {"width": image_width, "height": image_height},
"objects": objects,
}
if extra:
payload.update(extra)
return payload
def error_response(message: str, *, code: str | None = None) -> dict[str, Any]:
payload: dict[str, Any] = {"success": False, "error": message}
if code:
payload["code"] = code
return payload
def unsupported_response(task: str) -> dict[str, Any]:
return {
"success": True,
"supported": False,
"provider": PROVIDER_NAME,
"model": model_name(),
"task": task,
"message": "Not implemented by this model.",
}
def parse_advanced_settings(raw: str | None) -> dict[str, Any]:
if not raw or not str(raw).strip():
return {}
try:
parsed = json.loads(raw)
return parsed if isinstance(parsed, dict) else {}
except json.JSONDecodeError:
return {}
def infer_category(label: str) -> str:
text = (label or "object").lower()
rules = (
(("person", "man", "woman", "child", "human"), "person"),
(("car", "truck", "bus", "vehicle", "bike", "bicycle", "motorcycle"), "vehicle"),
(("dog", "cat", "bird", "animal"), "animal"),
(("tree", "plant", "flower"), "plant"),
(("building", "house", "window", "door"), "building"),
(("chair", "table", "desk", "sofa", "bed"), "furniture"),
(("phone", "laptop", "monitor", "screen", "keyboard"), "electronics"),
(("food", "plate", "bowl", "cup", "bottle"), "food"),
)
for keywords, category in rules:
if any(keyword in text for keyword in keywords):
return category
return "custom"
def normalize_bbox(coords: list[float]) -> dict[str, float] | None:
if len(coords) < 4:
return None
x1, y1, x2, y2 = coords[:4]
left = min(x1, x2) / 1000.0
top = min(y1, y2) / 1000.0
right = max(x1, x2) / 1000.0
bottom = max(y1, y2) / 1000.0
width = max(0.0, right - left)
height = max(0.0, bottom - top)
if width <= 0 or height <= 0:
return None
return {
"x": round(left, 6),
"y": round(top, 6),
"width": round(width, 6),
"height": round(height, 6),
}
def detections_to_objects(detections: list[dict[str, Any]]) -> list[dict[str, Any]]:
objects: list[dict[str, Any]] = []
for det in detections:
if det.get("type") != "box":
continue
bbox = normalize_bbox(det.get("coords") or [])
if not bbox:
continue
label = str(det.get("label") or "object")
objects.append(
{
"label": label,
"category": infer_category(label),
"confidence": None,
"bbox": bbox,
}
)
return objects