1. 项目概述

1.1 技术栈

本项目后端是一个基于 FastAPI 构建的高性能异步 API 服务,专为目标检测系统提供完整的后端支持。

核心技术组成:

  • Web 框架: FastAPI 0.104.0+

  • ASGI 服务器: Uvicorn 0.24.0+

  • 深度学习框架: Ultralytics YOLO 8.0.0+

  • 图像处理: OpenCV 4.8.0+ / Pillow 10.0.0+

  • 系统监控: psutil 5.9.0+

  • HTTP 客户端: httpx 0.25.0+

  • 数据验证: Pydantic 2.0.0+

1.2 设计理念

后端系统遵循以下核心设计原则:

  • RESTful API: 标准化的资源路由设计

  • 异步优先: 充分利用 FastAPI 的异步特性处理高并发

  • 模块化架构: 每个功能模块独立封装为路由器(Router)

  • 类型安全: 使用 Pydantic 进行严格的数据验证

  • 日志审计: 完整的操作日志记录

  • 错误处理: 统一的异常处理机制

1.3 服务端口

  • 默认端口: 10077

  • API 文档: http://localhost:10077/docs (Swagger UI)

  • ReDoc: http://localhost:10077/redoc


2. 项目目录结构

backend/
├── app.py                  # FastAPI 主应用入口
├── images.py               # 图片管理接口模块
├── videos.py               # 视频管理接口模块
├── logs.py                 # 日志管理接口模块
├── systems.py              # 系统监控接口模块
├── models_api.py           # 模型管理接口模块
├── llm.py                  # 大语言模型接口模块
├── vllm.py                 # 多模态模型接口模块
├── requirements.txt        # Python 依赖清单
├── README.md               # 项目说明文档
├── images/                 # 图片存储目录
│   ├── upload/             # 原始上传图片
│   └── detected/           # 检测结果图片
├── videos/                 # 视频存储目录
│   ├── upload/             # 原始上传视频
│   └── detected/           # 检测结果视频
├── models/                 # 模型文件存储
│   ├── yolo11n.pt          # 默认 YOLO 模型
│   └── models_info.json    # 模型元数据
└── logs/                   # 日志文件存储
    └── YYYY.MM.DD.log      # 按日期命名的日志

3. 核心模块详解

3.1 主应用模块 (app.py)

3.1.1 应用生命周期管理
from contextlib import asynccontextmanager
​
@asynccontextmanager
async def lifespan(app: FastAPI):
    """应用生命周期管理"""
    # 启动时初始化
    logger.info("目标检测系统API服务正在启动...")
    
    # 创建必要的目录
    for dir_path in [IMAGES_UPLOAD_DIR, IMAGES_DETECTED_DIR, ...]:
        dir_path.mkdir(parents=True, exist_ok=True)
    
    # 初始化模型信息文件
    if not models_info_path.exists():
        with open(models_info_path, 'w', encoding='utf-8') as f:
            json.dump([], f, ensure_ascii=False, indent=2)
    
    yield
    
    # 关闭时清理
    logger.info("目标检测系统API服务正在关闭...")
3.1.2 CORS 配置
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],          # 生产环境应限制来源
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
3.1.3 静态文件挂载
app.mount("/static/images/upload", StaticFiles(directory=str(IMAGES_UPLOAD_DIR)), name="images_upload")
app.mount("/static/images/detected", StaticFiles(directory=str(IMAGES_DETECTED_DIR)), name="images_detected")
app.mount("/static/videos/upload", StaticFiles(directory=str(VIDEOS_UPLOAD_DIR)), name="videos_upload")
app.mount("/static/videos/detected", StaticFiles(directory=str(VIDEOS_DETECTED_DIR)), name="videos_detected")
3.1.4 路由注册
app.include_router(images_router, prefix="/api/images", tags=["图片管理"])
app.include_router(videos_router, prefix="/api/videos", tags=["视频管理"])
app.include_router(logs_router, prefix="/api/logs", tags=["日志管理"])
app.include_router(systems_router, prefix="/api/systems", tags=["系统监控"])
app.include_router(models_router, prefix="/api/models", tags=["模型管理"])
app.include_router(llm_router, prefix="/api/llm", tags=["大语言模型"])
app.include_router(vllm_router, prefix="/api/vllm", tags=["多模态模型"])

3.2 图片管理模块 (images.py)

3.2.1 核心功能
  • 图片上传(支持多种格式:PNG, JPG, JPEG, GIF, BMP)

  • 图片列表获取

  • 图片预览(支持动态缩放)

  • 单张/批量下载

  • 单张/批量删除

  • YOLO 目标检测

  • 检测结果管理

3.2.2 YOLO 模型加载(CPU 模式)
def get_current_model():
    """获取当前加载的YOLO模型(使用CPU)"""
    global current_model
    if current_model is None:
        from ultralytics import YOLO
        current_model = YOLO("yolo11n.pt")
        # 强制使用CPU,确保低配设备也能稳定运行
        current_model.to('cpu')
        logger.info("已加载默认模型 yolo11n.pt (使用CPU)")
    return current_model
3.2.3 图片检测实现
@router.post("/detect/{filename}")
async def detect_image(filename: str):
    """图片目标检测"""
    filepath = IMAGES_UPLOAD_DIR / filename
    
    if not filepath.exists():
        raise HTTPException(status_code=404, detail="图片不存在")
    
    model = get_current_model()
    
    # 执行检测(使用CPU)
    results = model(str(filepath), device='cpu')
    
    detections = []
    for result in results:
        boxes = result.boxes
        for box in boxes:
            detection = {
                "class_id": int(box.cls[0]),
                "class_name": result.names[int(box.cls[0])],
                "confidence": float(box.conf[0]),
                "box": {
                    "x1": float(box.xyxy[0][0]),
                    "y1": float(box.xyxy[0][1]),
                    "x2": float(box.xyxy[0][2]),
                    "y2": float(box.xyxy[0][3])
                }
            }
            detections.append(detection)
    
    # 保存检测结果图片
    detected_filename = f"detected_{filename}"
    detected_filepath = IMAGES_DETECTED_DIR / detected_filename
    
    result_img = results[0].plot()
    cv2.imwrite(str(detected_filepath), result_img)
    
    return {
        "code": 200,
        "message": "检测成功",
        "data": {
            "filename": detected_filename,
            "detections": detections,
            "detected_url": f"/static/images/detected/{detected_filename}"
        }
    }
3.2.4 批量下载(ZIP 打包)
@router.post("/download/batch")
async def batch_download_images(filenames: List[str]):
    """批量下载图片"""
    buffer = io.BytesIO()
    
    with zipfile.ZipFile(buffer, 'w', zipfile.ZIP_DEFLATED) as zf:
        for filename in filenames:
            filepath = IMAGES_UPLOAD_DIR / filename
            if filepath.exists():
                zf.write(filepath, filename)
    
    buffer.seek(0)
    zip_filename = f"images_{datetime.now().strftime('%Y%m%d_%H%M%S')}.zip"
    
    return StreamingResponse(
        buffer,
        media_type='application/zip',
        headers={'Content-Disposition': f'attachment; filename="{zip_filename}"'}
    )

3.3 视频管理模块 (videos.py)

3.3.1 核心功能
  • 视频上传(支持 MP4, AVI, MOV, WMV, FLV, MKV)

  • 视频列表获取

  • 单张/批量下载

  • 单张/批量删除

  • 视频目标检测(逐帧处理)

  • FFmpeg 自动转码(H.264 兼容性)


3.4 系统监控模块 (systems.py)

3.4.1 核心功能
  • CPU 使用率监控

  • 内存使用情况

  • 磁盘空间统计

  • 网络流量统计

  • 系统运行时间

3.4.2 实时状态获取
import psutil

@router.get("/status")
def get_system_status():
    """获取系统资源状态"""
    # CPU 信息(采样间隔 1 秒)
    cpu_percent = psutil.cpu_percent(interval=1)
    cpu_count = psutil.cpu_count()
    
    # 内存信息
    memory = psutil.virtual_memory()
    
    # 磁盘信息
    disk = psutil.disk_usage('/')
    
    # 网络信息
    network = psutil.net_io_counters()
    
    # 系统运行时间
    boot_time = datetime.fromtimestamp(psutil.boot_time())
    uptime = datetime.now() - boot_time
    
    return {
        "code": 200,
        "message": "获取成功",
        "data": {
            "cpu": {
                "percent": cpu_percent,
                "count": cpu_count
            },
            "memory": {
                "total": memory.total,
                "used": memory.used,
                "percent": memory.percent
            },
            "disk": {
                "total": disk.total,
                "used": disk.used,
                "percent": disk.percent
            },
            "network": {
                "bytes_sent": network.bytes_sent,
                "bytes_recv": network.bytes_recv
            },
            "uptime": {
                "boot_time": boot_time.strftime("%Y-%m-%d %H:%M:%S"),
                "days": uptime.days,
                "hours": uptime.seconds // 3600,
                "minutes": (uptime.seconds % 3600) // 60
            }
        }
    }

3.5 日志管理模块 (logs.py)

3.5.1 核心功能
  • 日志列表获取

  • 日志内容预览(支持指定行数)

  • 单个/批量下载

  • 日志删除

3.5.2 日志预览实现
@router.get("/preview/{filename}")
async def preview_log(filename: str, lines: int = Query(default=100, ge=1, le=1000)):
    """预览日志内容"""
    filepath = LOGS_DIR / filename
    
    if not filepath.exists():
        raise HTTPException(status_code=404, detail="日志文件不存在")
    
    with open(filepath, 'r', encoding='utf-8') as f:
        all_lines = f.readlines()
    
    # 获取最后 N 行
    content = [line.rstrip('\n\r') for line in all_lines[-lines:]]
    
    return {
        "code": 200,
        "message": "获取成功",
        "data": {
            "filename": filename,
            "content": content,
            "total_lines": len(all_lines)
        }
    }

3.6 模型管理模块 (models_api.py)

3.6.1 核心功能
  • 模型上传(.pt 格式)

  • 模型列表获取

  • 模型信息查询/更新

  • 模型下载

  • 模型删除

  • 动态加载模型


3.7 大语言模型模块 (llm.py)

3.7.1 核心功能
  • 获取可用模型列表

  • 聊天完成接口(支持流式输出)

  • 参数可配置(temperature, max_tokens, top_p 等)


3.8 多模态模型模块 (vllm.py)

3.8.1 核心功能
  • 获取可用多模态模型列表

  • 多模态聊天接口(文本 + 图像)

  • 消息格式转换


4. API 接口规范

4.1 统一响应格式

所有接口遵循统一的 JSON 响应格式:

{
  "code": 200,
  "message": "成功",
  "data": {}
}

4.2 错误响应格式

{
  "detail": "错误信息描述"
}

常见 HTTP 状态码:

  • 200: 成功

  • 400: 请求参数错误

  • 404: 资源不存在

  • 500: 服务器内部错误

  • 504: 请求超时

4.3 文件大小限制

  • 图片文件: 最大 10MB

  • 视频文件: 最大 500MB

  • 模型文件: 最大 500MB


5. 数据库设计

5.1 模型信息存储 (models_info.json)

[
  {
    "filename": "20240321_123456_yolo.pt",
    "name": "YOLO检测模型",
    "dataset": "COCO",
    "base_model": "YOLO",
    "upload_time": "2024-03-21 12:34:56",
    "description": "基于COCO数据集训练的YOLO目标检测模型",
    "version": "1.0",
    "accuracy": 85.5
  }
]

更多推荐