基于YOLO与LLM的多模态智慧公安研判平台开发实战 📅 发布时间:2026/9/5 10:00:59 👁 浏览次数: 在实际智慧公安和智慧警务系统中单纯依赖单一算法或单一数据源已经难以满足复杂案情研判的需求。一个嫌疑人可能出现在多个监控视频片段中涉及人脸、行为、车辆、时间、地点等多维度信息。传统系统往往需要民警在不同子系统间反复切换、手动关联效率低下且容易遗漏关键线索。将 YOLO 目标检测、LLM 大语言模型、人脸识别和视频检索技术整合到一个统一平台正是为了解决跨模态数据融合和智能研判的难题。本文将以一个毕业设计级别的智慧公安综合研判平台为例带你从零搭建一个支持多模态分析的 Web 系统。前端使用 Vue.js 构建交互界面后端采用 Flask 提供 RESTful APIAI 算法部分集成 YOLO 进行实时目标检测、人脸识别模块处理身份比对、LLM 大模型辅助语义理解和案情摘要生成并通过视频检索技术快速定位关键片段。你将学会如何将多个 AI 模型串联成完整业务流如何处理视频流数据以及如何设计前后端接口让算法结果可视化。最终实现一个可演示、可扩展的研判平台原型。1. 理解多模态智慧研判平台的技术架构1.1 什么是多模态大模型在公安场景下的价值多模态大模型Multimodal Large Language Model是指能够同时理解和处理文本、图像、视频、音频等多种类型数据的 AI 模型。在公安研判场景中它的价值在于打破数据孤岛。例如系统可以从一段监控视频中提取出嫌疑人的人脸图片图像模态、动作描述文本模态、出现时间段时间模态和地理位置空间模态然后通过大模型的能力进行关联推理生成一段自然语言的研判报告“嫌疑人甲于 5 月 10 日 14:30 出现在 A 路口身穿黑色上衣随后在 B 商场入口再次被捕获两次出现间隔 15 分钟行为轨迹可疑。”单纯使用 YOLO 只能检测出“有什么”单纯使用人脸识别只能知道“是谁”单纯使用视频检索只能找到“在哪里”。而多模态大模型能够将这些信息串联成“谁在什么时间什么地点做了什么接下来可能去哪里”的完整叙事这正是智慧警务需要的研判能力。1.2 平台核心组件与工作流程一个完整的智慧公安研判平台包含以下核心组件前端交互层 (Vue.js)负责呈现视频流、检测结果、检索列表和研判报告。提供上传视频、查询嫌疑人、查看轨迹等交互功能。后端服务层 (Flask)提供 REST API 接收前端请求调度算法模块处理业务逻辑并返回结构化数据。算法能力层YOLO 目标检测从视频帧中实时检测行人、车辆、人脸等目标。人脸识别模块对检测到的人脸进行特征提取和身份比对。视频检索引擎基于内容如颜色、纹理、目标或元数据时间、摄像头位置快速检索相关视频片段。LLM 大模型对多模态信息进行语义理解、摘要生成和线索推理。典型工作流程如下民警上传一段案发视频或选择实时摄像头流。后端调用 YOLO 模型逐帧检测标记出关键目标如行人、车辆。对检测到的人脸调用人脸识别模块与底库进行比对识别身份。根据识别结果如嫌疑人身份证号、车辆车牌或视觉特征如衣服颜色调用视频检索模块查找历史视频中出现的所有相关片段。LLM 大模型接收所有结构化信息时间、地点、人物、行为生成一份综合研判报告。前端可视化展示检测框、识别结果、检索列表和自然语言报告。1.3 技术选型理由与版本考量YOLO 选型YOLOv5 或 YOLOv8 是常见选择。YOLOv5 社区资源丰富易于部署YOLOv8 精度更高支持实例分割。毕业设计阶段建议使用 YOLOv5s轻量版平衡速度与精度。LLM 选型考虑到本地部署成本和硬件要求可以选择较小参数规模的开源模型如 ChatGLM-6B 或 Qwen-7B它们可以在单张显卡上运行并提供足够的语义理解能力。人脸识别使用成熟的 ArcFace 或 InsightFace 框架它们提供了高质量的人脸特征提取和比对算法。视频检索对于毕业设计可以先用目标检测结果如行人重识别特征或简单特征颜色直方图实现基础检索后期可升级到深度学习特征。前后端选型Vue.js 和 Flask 都是轻量级、学习曲线平缓的框架适合快速原型开发。2. 准备开发环境与项目结构2.1 硬件与软件环境要求由于涉及多个深度学习模型建议配置如下GPU至少 NVIDIA GTX 1660 Ti 或同等算力6GB 显存以上更佳。YOLO 和 LLM 都可以利用 GPU 加速。内存16GB RAM 最低32GB 推荐。视频处理和模型加载比较耗内存。存储至少 100GB 可用空间用于存放模型文件、视频数据和数据库。操作系统Ubuntu 18.04/20.04 LTS 或 Windows 10/11。Linux 在深度学习部署上通常更顺畅。Python3.8 或 3.9 版本。避免使用过高版本以免某些库不兼容。2.2 创建项目目录结构一个清晰的项目结构是后续开发的基础。建议按以下方式组织police_judgment_platform/ ├── backend/ # Flask 后端 │ ├── app.py # Flask 主应用 │ ├── models/ # 数据模型ORM │ ├── routes/ # API 路由模块 │ ├── services/ # 业务逻辑服务 │ ├── utils/ # 工具函数如视频处理、图像预处理 │ ├── ai_models/ # AI 模型加载与推理模块 │ │ ├── yolo_detector.py │ │ ├── face_recognizer.py │ │ ├── video_retriever.py │ │ └── llm_service.py │ ├── config.py # 配置文件 │ ├── requirements.txt # Python 依赖 │ └── uploads/ # 上传文件临时目录 ├── frontend/ # Vue.js 前端 │ ├── public/ │ ├── src/ │ │ ├── components/ # Vue 组件 │ │ ├── views/ # 页面视图 │ │ ├── router/ # 路由配置 │ │ ├── api/ # 前端 API 调用封装 │ │ └── assets/ │ ├── package.json │ └── vue.config.js ├── models/ # 存放预训练模型文件 │ ├── yolo/ # YOLO 模型权重 │ ├── face/ # 人脸识别模型 │ └── llm/ # LLM 模型文件 ├── data/ # 数据集和测试数据 │ ├── videos/ # 示例视频 │ └── face_db/ # 人脸底库 └── docs/ # 项目文档2.3 安装 Python 后端依赖在backend目录下创建requirements.txt内容如下flask2.3.3 flask-cors4.0.0 flask-sqlalchemy3.0.5 opencv-python4.8.1.78 numpy1.24.3 torch2.0.1 torchvision0.15.2 ultralytics8.0.186 # 用于 YOLOv8 insightface0.7.3 # 人脸识别 transformers4.34.0 # 用于加载 LLM accelerate0.24.1 # 加速 LLM 推理 pillow10.0.1 sqlite3 # 内置库无需安装安装命令cd backend pip install -r requirements.txt注意PyTorch 的安装命令可能因系统和 CUDA 版本而异。请根据 PyTorch 官方指南 选择适合你环境的命令。例如对于 CUDA 11.8 的用户可能是pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118。2.4 初始化前端 Vue 项目在前端目录中使用 Vue CLI 创建项目确保已安装 Node.js 和 npmcd frontend npm install -g vue/cli vue create . # 选择默认配置或手动选择需要的特性如 Router, Vuex然后安装必要的依赖npm install axios element-plus --saveaxios用于向后端发送 HTTP 请求element-plus是常用的 UI 组件库可以快速构建界面。3. 实现后端 Flask 服务与 AI 算法集成3.1 搭建 Flask 应用骨架首先创建backend/app.py作为应用入口from flask import Flask from flask_cors import CORS import os def create_app(): app Flask(__name__) app.config.from_pyfile(config.py) # 允许跨域请求方便前后端分离开发 CORS(app) # 注册蓝图API 路由 from routes import video_bp, face_bp, analysis_bp app.register_blueprint(video_bp, url_prefix/api/video) app.register_blueprint(face_bp, url_prefix/api/face) app.register_blueprint(analysis_bp, url_prefix/api/analysis) # 创建上传目录 os.makedirs(app.config[UPLOAD_FOLDER], exist_okTrue) return app if __name__ __main__: app create_app() app.run(host0.0.0.0, port5000, debugTrue)配置文件backend/config.pyimport os basedir os.path.abspath(os.path.dirname(__file__)) # 基础配置 SECRET_KEY your-secret-key-change-in-production UPLOAD_FOLDER os.path.join(basedir, uploads) MAX_CONTENT_LENGTH 100 * 1024 * 1024 # 限制上传文件 100MB # 数据库配置使用 SQLite 便于演示 SQLALCHEMY_DATABASE_URI sqlite:/// os.path.join(basedir, app.db) SQLALCHEMY_TRACK_MODIFICATIONS False # AI 模型路径 MODEL_DIR os.path.join(basedir, ../models) YOLO_MODEL_PATH os.path.join(MODEL_DIR, yolo, yolov5s.pt) FACE_MODEL_PATH os.path.join(MODEL_DIR, face, buffalo_l)3.2 实现 YOLO 目标检测服务创建backend/ai_models/yolo_detector.pyimport cv2 import numpy as np from ultralytics import YOLO import os class YOLODetector: def __init__(self, model_path): # 加载 YOLO 模型 self.model YOLO(model_path) self.class_names self.model.names def detect_image(self, image_path): 对单张图片进行目标检测 results self.model(image_path) detections [] for result in results: boxes result.boxes for box in boxes: # 获取坐标、置信度和类别 x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls_id int(box.cls[0].item()) cls_name self.class_names[cls_id] detections.append({ class: cls_name, confidence: round(conf, 2), bbox: [round(x1), round(y1), round(x2), round(y2)] }) return detections def process_video(self, video_path, output_pathNone, conf_threshold0.5): 处理视频逐帧检测并返回结果 cap cv2.VideoCapture(video_path) fps cap.get(cv2.CAP_PROP_FPS) frame_count int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) # 用于存储每帧的检测结果 video_results { fps: fps, frame_count: frame_count, detections_per_frame: [] } frame_idx 0 while cap.isOpened(): ret, frame cap.read() if not ret: break # 使用 YOLO 检测当前帧 results self.model(frame, confconf_threshold) frame_detections [] for result in results: boxes result.boxes for box in boxes: x1, y1, x2, y2 box.xyxy[0].tolist() conf box.conf[0].item() cls_id int(box.cls[0].item()) cls_name self.class_names[cls_id] # 只关注人、车等关键类别 if cls_name in [person, car, truck, bus]: frame_detections.append({ class: cls_name, confidence: round(conf, 2), bbox: [round(x1), round(y1), round(x2), round(y2)] }) video_results[detections_per_frame].append({ frame_index: frame_idx, detections: frame_detections }) frame_idx 1 cap.release() return video_results3.3 实现人脸识别模块创建backend/ai_models/face_recognizer.pyimport insightface from insightface.app import FaceAnalysis import cv2 import numpy as np import os class FaceRecognizer: def __init__(self, model_path): # 初始化人脸分析应用 self.app FaceAnalysis(namebuffalo_l, rootmodel_path) self.app.prepare(ctx_id0, det_size(640, 640)) # 人脸数据库{face_id: {name: , embedding: []}} self.face_db {} self.next_face_id 1 def extract_face_features(self, image_path): 从图片中提取人脸特征 img cv2.imread(image_path) if img is None: return [] faces self.app.get(img) results [] for face in faces: # 人脸特征向量用于比对 embedding face.embedding # 人脸 bounding box bbox face.bbox.astype(int).tolist() # 人脸关键点可选 landmarks face.kps.astype(int).tolist() if hasattr(face, kps) else [] results.append({ embedding: embedding, bbox: bbox, landmarks: landmarks }) return results def register_face(self, image_path, person_name): 注册新的人脸到底库 faces self.extract_face_features(image_path) if not faces: return False, 未检测到人脸 # 使用第一张检测到的人脸 face_data faces[0] face_id self.next_face_id self.face_db[face_id] { name: person_name, embedding: face_data[embedding] } self.next_face_id 1 return True, f成功注册人脸ID: {face_id} def recognize_face(self, image_path, threshold0.6): 识别图片中的人脸 faces self.extract_face_features(image_path) recognition_results [] for face in faces: best_match None best_score 0 # 与底库中的每个人脸进行比对 for face_id, db_face in self.face_db.items(): # 计算余弦相似度 similarity self.cosine_similarity(face[embedding], db_face[embedding]) if similarity best_score and similarity threshold: best_score similarity best_match { face_id: face_id, name: db_face[name], similarity: round(similarity, 3) } recognition_results.append({ bbox: face[bbox], best_match: best_match, embedding_size: len(face[embedding]) }) return recognition_results staticmethod def cosine_similarity(embedding1, embedding2): 计算两个向量的余弦相似度 dot_product np.dot(embedding1, embedding2) norm1 np.linalg.norm(embedding1) norm2 np.linalg.norm(embedding2) return dot_product / (norm1 * norm2)3.4 设计视频检索模块创建backend/ai_models/video_retriever.pyimport os import cv2 import numpy as np from datetime import datetime class VideoRetriever: def __init__(self, video_database_path): self.video_db_path video_database_path # 视频索引{video_id: {path, metadata, keyframes}} self.video_index {} def index_video(self, video_path, metadataNone): 将视频加入检索数据库 video_id os.path.basename(video_path) # 提取关键帧特征简化版使用颜色直方图 keyframes self.extract_keyframes(video_path) self.video_index[video_id] { path: video_path, metadata: metadata or {}, keyframes: keyframes, indexed_at: datetime.now().isoformat() } return video_id def extract_keyframes(self, video_path, interval_seconds5): 提取视频关键帧特征 cap cv2.VideoCapture(video_path) fps cap.get(cv2.CAP_PROP_FPS) interval_frames int(fps * interval_seconds) keyframes [] frame_count 0 while cap.isOpened(): ret, frame cap.read() if not ret: break if frame_count % interval_frames 0: # 简化特征使用颜色直方图 hist self.compute_color_histogram(frame) keyframes.append({ frame_index: frame_count, timestamp: frame_count / fps, features: hist }) frame_count 1 cap.release() return keyframes def compute_color_histogram(self, frame, bins32): 计算图像颜色直方图作为特征 # 转换到 HSV 颜色空间 hsv cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) # 计算直方图 hist_h cv2.calcHist([hsv], [0], None, [bins], [0, 180]) hist_s cv2.calcHist([hsv], [1], None, [bins], [0, 256]) hist_v cv2.calcHist([hsv], [2], None, [bins], [0, 256]) # 归一化并拼接 hist_h cv2.normalize(hist_h, hist_h).flatten() hist_s cv2.normalize(hist_s, hist_s).flatten() hist_v cv2.normalize(hist_v, hist_v).flatten() return np.concatenate([hist_h, hist_s, hist_v]) def search_by_visual_similarity(self, query_frame, max_results10): 基于视觉相似性检索视频 query_features self.compute_color_histogram(query_frame) similarities [] for video_id, video_data in self.video_index.items(): for keyframe in video_data[keyframes]: # 计算特征相似度使用欧氏距离的倒数 distance np.linalg.norm(query_features - keyframe[features]) similarity 1 / (1 distance) # 转换为相似度分数 similarities.append({ video_id: video_id, similarity: similarity, timestamp: keyframe[timestamp], video_metadata: video_data[metadata] }) # 按相似度排序并返回前 N 个结果 similarities.sort(keylambda x: x[similarity], reverseTrue) return similarities[:max_results]3.5 集成 LLM 大模型服务创建backend/ai_models/llm_service.pyfrom transformers import AutoTokenizer, AutoModelForCausalLM import torch class LLMService: def __init__(self, model_path): # 加载 tokenizer 和模型 self.tokenizer AutoTokenizer.from_pretrained(model_path, trust_remote_codeTrue) self.model AutoModelForCausalLM.from_pretrained( model_path, torch_dtypetorch.float16, device_mapauto, trust_remote_codeTrue ) def generate_analysis_report(self, context_data): 根据多模态数据生成研判报告 # 构建提示词 prompt self.build_prompt(context_data) # 生成回答 inputs self.tokenizer(prompt, return_tensorspt) with torch.no_grad(): outputs self.model.generate( inputs.input_ids.cuda(), max_new_tokens500, temperature0.7, do_sampleTrue ) response self.tokenizer.decode(outputs[0], skip_special_tokensTrue) # 提取生成的报告部分 report self.extract_report_from_response(response, prompt) return report def build_prompt(self, context_data): 构建给 LLM 的提示词 prompt_template 你是一个公安研判专家。请根据以下案件信息生成一份综合研判报告 时间信息{time_info} 地点信息{location_info} 涉及人员{person_info} 监控视频分析结果{video_analysis} 人脸识别结果{face_recognition} 请从以下角度进行分析 1. 嫌疑人的行为轨迹分析 2. 时间空间关联性 3. 可能的作案动机推断 4. 下一步侦查建议 请用专业、简洁的语言撰写报告 return prompt_template.format( time_infocontext_data.get(time_info, 暂无), location_infocontext_data.get(location_info, 暂无), person_infocontext_data.get(person_info, 暂无), video_analysiscontext_data.get(video_analysis, 暂无), face_recognitioncontext_data.get(face_recognition, 暂无) ) def extract_report_from_response(self, full_response, prompt): 从 LLM 完整响应中提取报告部分 if prompt in full_response: return full_response.split(prompt)[1].strip() return full_response4. 设计 API 接口与前端交互4.1 实现核心 API 路由创建backend/routes/video.pyfrom flask import Blueprint, request, jsonify import os from services.video_service import process_video_upload video_bp Blueprint(video, __name__) video_bp.route(/upload, methods[POST]) def upload_video(): 上传视频文件并进行分析 if video not in request.files: return jsonify({error: 未提供视频文件}), 400 video_file request.files[video] if video_file.filename : return jsonify({error: 未选择文件}), 400 # 保存上传的文件 upload_dir current_app.config[UPLOAD_FOLDER] filename os.path.join(upload_dir, video_file.filename) video_file.save(filename) try: # 调用视频处理服务 result process_video_upload(filename) return jsonify(result) except Exception as e: return jsonify({error: f处理失败: {str(e)}}), 500 video_bp.route(/analyze/video_id) def analyze_video(video_id): 获取视频分析结果 # 这里应该从数据库查询分析结果 # 简化演示直接返回示例数据 return jsonify({ video_id: video_id, analysis: { object_detection: [], face_recognition: [], summary: 分析完成 } })创建backend/routes/face.pyfrom flask import Blueprint, request, jsonify import os from services.face_service import register_face, recognize_faces face_bp Blueprint(face, __name__) face_bp.route(/register, methods[POST]) def register_face_api(): 注册新人脸到底库 if face_image not in request.files: return jsonify({error: 未提供人脸图片}), 400 face_image request.files[face_image] person_name request.form.get(person_name, ) if not person_name: return jsonify({error: 未提供人员姓名}), 400 # 保存图片 upload_dir current_app.config[UPLOAD_FOLDER] filename os.path.join(upload_dir, fface_{person_name}.jpg) face_image.save(filename) success, message register_face(filename, person_name) if success: return jsonify({message: message}) else: return jsonify({error: message}), 400 face_bp.route(/recognize, methods[POST]) def recognize_face_api(): 识别图片中的人脸 if image not in request.files: return jsonify({error: 未提供图片}), 400 image_file request.files[image] upload_dir current_app.config[UPLOAD_FOLDER] filename os.path.join(upload_dir, temp_recognition.jpg) image_file.save(filename) results recognize_faces(filename) return jsonify({recognitions: results})4.2 构建 Vue.js 前端界面在frontend/src/views/Analysis.vue中创建主要分析页面template div classanalysis-container el-container el-header h1智慧公安综合研判平台/h1 /el-header el-main el-row :gutter20 el-col :span12 el-card classupload-section template #header span视频上传与分析/span /template el-upload classvideo-upload action/api/video/upload :on-successhandleVideoUploadSuccess :before-uploadbeforeVideoUpload acceptvideo/* el-button typeprimary点击上传视频文件/el-button template #tip div classel-upload__tip支持 mp4、avi 等格式大小不超过 100MB/div /template /el-upload div v-ifanalysisResult classresult-section h3分析结果/h3 el-tabs v-modelactiveTab el-tab-pane label目标检测 namedetection object-detection-result :resultsanalysisResult.detections / /el-tab-pane el-tab-pane label人脸识别 namefaces face-recognition-result :facesanalysisResult.faces / /el-tab-pane el-tab-pane label研判报告 namereport llm-report :reportanalysisResult.llm_report / /el-tab-pane /el-tabs /div /el-card /el-col el-col :span12 el-card classrealtime-section template #header span实时视频分析/span /template video-player :srcliveVideoUrl frame-capturedhandleFrameCaptured controls autoplay muted / div classrealtime-results h4实时检测结果/h4 el-table :datarealtimeDetections sizesmall el-table-column propclass label类别 width100 / el-table-column propconfidence label置信度 width100 / el-table-column propbbox label位置 / /el-table /div /el-card /el-col /el-row /el-main /el-container /div /template script import { ref, reactive } from vue import { ElMessage } from element-plus import ObjectDetectionResult from /components/ObjectDetectionResult.vue import FaceRecognitionResult from /components/FaceRecognitionResult.vue import LLMReport from /components/LLMReport.vue import VideoPlayer from /components/VideoPlayer.vue export default { name: AnalysisView, components: { ObjectDetectionResult, FaceRecognitionResult, LLMReport, VideoPlayer }, setup() { const activeTab ref(detection) const analysisResult ref(null) const liveVideoUrl ref() const realtimeDetections ref([]) const beforeVideoUpload (file) { const isVideo file.type.startsWith(video/) const isLt100M file.size / 1024 / 1024 100 if (!isVideo) { ElMessage.error(只能上传视频文件!) return false } if (!isLt100M) { ElMessage.error(视频大小不能超过 100MB!) return false } return true } const handleVideoUploadSuccess (response) { analysisResult.value response.data ElMessage.success(视频分析完成!) } const handleFrameCaptured (detections) { realtimeDetections.value detections } return { activeTab, analysisResult, liveVideoUrl, realtimeDetections, beforeVideoUpload, handleVideoUploadSuccess, handleFrameCaptured } } } /script style scoped .analysis-container { padding: 20px; } .upload-section, .realtime-section { height: 600px; } .video-upload { margin-bottom: 20px; } /style4.3 实现视频播放与帧捕获组件创建frontend/src/components/VideoPlayer.vuetemplate div classvideo-player video refvideoElement :srcsrc loadeddatainitializeCanvas timeupdatecaptureFrame controls autoplay muted crossoriginanonymous 您的浏览器不支持视频播放 /video canvas refcanvasElement styledisplay: none;/canvas /div /template script import { ref, onMounted, watch } from vue export default { name: VideoPlayer, props: { src: String, captureInterval: { type: Number, default: 1000 // 每1秒捕获一帧 } }, emits: [frame-captured], setup(props, { emit }) { const videoElement ref(null) const canvasElement ref(null) const canvasContext ref(null) let lastCaptureTime 0 const initializeCanvas () { if (videoElement.value canvasElement.value) { canvasElement.value.width videoElement.value.videoWidth canvasElement.value.height videoElement.value.videoHeight canvasContext.value canvasElement.value.getContext(2d) } } const captureFrame () { if (!videoElement.value || !canvasContext.value) return const currentTime Date.now() if (currentTime - lastCaptureTime props.captureInterval) return lastCaptureTime currentTime // 绘制当前帧到 canvas canvasContext.value.drawImage( videoElement.value, 0, 0, canvasElement.value.width, canvasElement.value.height ) // 获取图像数据发送给后端分析 canvasElement.value.toBlob((blob) { emit(frame-captured, blob) }, image/jpeg, 0.8) } onMounted(() { initializeCanvas() }) watch(() props.src, () { // 视频源变化时重新初始化 setTimeout(initializeCanvas, 100) }) return { videoElement, canvasElement, initializeCanvas, captureFrame } } } /script5. 系统集成测试与常见问题排查5.1 启动完整系统启动后端服务cd backend python app.py后端服务将在 http://localhost:5000 启动。启动前端开发服务器cd frontend npm run serve前端服务将在 http://localhost:8080 启动。访问系统 打开浏览器访问 http://localhost:8080即可使用智慧公安研判平台。5.2 常见问题与解决方案问题现象可能原因检查方式解决方案前端无法连接后端 API1. 后端服务未启动2. 端口被占用3. CORS 配置错误1. 检查后端服务状态2. 查看浏览器控制台错误3. 检查网络请求1. 确保后端在 5000 端口运行2. 在前端配置正确的 API 基础URL3. 确认 Flask-CORS 已正确配置YOLO 模型加载失败1. 模型文件不存在2. PyTorch 版本不兼容3. CUDA 不可用1. 检查模型文件路径2. 查看错误日志3. 测试 CUDA