26-7-31-1

This commit is contained in:
shuai
2026-07-31 12:27:41 +08:00
commit 9b8b8b57b3
142 changed files with 22408 additions and 0 deletions
+135
View File
@@ -0,0 +1,135 @@
from __future__ import annotations
import logging
from fastapi import APIRouter, File, HTTPException, UploadFile
from pydantic import BaseModel, Field
from app.services.yolo_detector import get_detector, reload_detector, yolo_available
from app.services.yolo_manager import get_yolo_manager
logger = logging.getLogger(__name__)
router = APIRouter(prefix="/yolo", tags=["yolo"])
class ActivateRequest(BaseModel):
name: str = Field(..., description="权重文件名")
demo_mode: str | None = Field(default=None, description="demo|real|auto")
class DemoModeRequest(BaseModel):
demo_mode: str = Field(..., description="demo|real|auto")
@router.get("/status")
def yolo_status() -> dict:
mgr = get_yolo_manager()
det = get_detector()
return mgr.status(det.info())
@router.get("/weights")
def list_weights() -> dict:
mgr = get_yolo_manager()
return {"items": mgr.list_weights(), "count": len(mgr.list_weights())}
@router.post("/weights/upload")
async def upload_weight(file: UploadFile = File(...)) -> dict:
if not file.filename:
raise HTTPException(400, "缺少文件名")
raw = await file.read()
try:
item = get_yolo_manager().save_upload(file.filename, raw)
return {"ok": True, "weight": item}
except ValueError as e:
raise HTTPException(400, str(e)) from e
except Exception as e:
logger.exception("上传权重失败")
raise HTTPException(500, f"上传失败: {e}") from e
@router.post("/weights/activate")
def activate_weight(body: ActivateRequest) -> dict:
try:
status = get_yolo_manager().activate(body.name, body.demo_mode)
info = reload_detector()
status.update(info)
status["ok"] = True
return status
except FileNotFoundError as e:
raise HTTPException(404, str(e)) from e
except ValueError as e:
raise HTTPException(400, str(e)) from e
@router.post("/weights/deactivate")
def deactivate_weight() -> dict:
status = get_yolo_manager().deactivate()
info = reload_detector()
status.update(info)
status["ok"] = True
return status
@router.delete("/weights/{name}")
def delete_weight(name: str) -> dict:
"""逻辑删除:隐藏权重,本地 .pt 文件仍保留在 data/weights。"""
try:
get_yolo_manager().delete_weight(name)
reload_detector()
return {
"ok": True,
"name": name,
"soft_delete": True,
"message": "已逻辑删除(本地文件保留,仅从列表隐藏)",
}
except FileNotFoundError as e:
raise HTTPException(404, str(e)) from e
except ValueError as e:
raise HTTPException(400, str(e)) from e
@router.post("/weights/restore")
def restore_weight(body: ActivateRequest) -> dict:
"""恢复逻辑删除的权重。"""
try:
status = get_yolo_manager().restore_weight(body.name)
info = reload_detector()
status.update(info)
status["ok"] = True
return status
except FileNotFoundError as e:
raise HTTPException(404, str(e)) from e
@router.post("/mode")
def set_mode(body: DemoModeRequest) -> dict:
try:
status = get_yolo_manager().set_demo_mode(body.demo_mode)
info = reload_detector()
status.update(info)
status["ok"] = True
return status
except ValueError as e:
raise HTTPException(400, str(e)) from e
@router.get("/visualization")
def visualization() -> dict:
return get_yolo_manager().visualization()
@router.post("/stats/reset")
def reset_stats() -> dict:
get_yolo_manager().reset_stats()
return {"ok": True}
@router.get("/capability")
def capability() -> dict:
return {
"ultralytics": yolo_available(),
"detector": get_detector().info(),
"manager": get_yolo_manager().status(),
}