
在保险理赔、二手车评估和车辆维修等场景中快速准确地识别汽车损坏部位一直是行业痛点。传统人工检测效率低、主观性强而基于深度学习的自动化检测方案能大幅提升评估效率和准确性。本文将完整介绍如何基于YOLOv8构建汽车损坏识别系统从环境搭建到模型训练再到可视化界面开发提供可直接复用的完整代码和数据集。本文适合有一定Python基础的开发者特别是对计算机视觉和深度学习感兴趣的技术人员。通过本教程你将掌握YOLOv8的完整工作流程包括数据准备、模型训练、性能评估和系统集成最终获得一个可实际应用的汽车损坏检测系统。1. 项目背景与技术选型1.1 汽车损坏识别的业务价值汽车损坏识别在多个行业场景中具有重要应用价值。在保险理赔环节自动化的损坏评估可以显著缩短理赔周期减少人工成本在二手车交易中客观的车辆状况评估能为交易双方提供可信依据在维修行业精准的损坏定位能指导维修方案制定。传统基于规则的图像处理方法难以应对复杂的车辆损坏情况而深度学习模型能够从大量样本中学习损坏特征实现更智能的识别。1.2 YOLOv8的技术优势YOLOv8是Ultralytics公司推出的最新目标检测算法在精度和速度方面都有显著提升。相比前代版本YOLOv8在Backbone网络、Neck结构和Head设计上都进行了优化采用更高效的CSPDarknet53作为主干网络结合SPPF模块和PAN-FPN结构在保持实时性的同时提高了检测精度。对于汽车损坏检测这种需要平衡准确率和速度的应用场景YOLOv8是理想的选择。1.3 系统架构概述本系统采用模块化设计主要包括数据预处理、模型训练、推理检测和可视化界面四个核心模块。数据预处理负责标注格式转换和数据集划分模型训练模块实现YOLOv8的定制化训练推理检测模块提供图片和视频的批量处理能力可视化界面基于PyQt5开发提供友好的用户交互体验。2. 环境配置与依赖安装2.1 基础环境要求确保系统满足以下基本要求操作系统Windows 10/11、Linux Ubuntu 18.04或macOS 10.14Python版本3.8-3.10推荐3.9内存至少8GB推荐16GB存储空间至少10GB可用空间GPU可选但推荐NVIDIA GPUCUDA 11.32.2 创建虚拟环境使用conda或venv创建独立的Python环境避免依赖冲突# 使用conda创建环境 conda create -n yolov8-car-damage python3.9 conda activate yolov8-car-damage # 或使用venv python -m venv yolov8_env source yolov8_env/bin/activate # Linux/macOS yolov8_env\Scripts\activate # Windows2.3 安装核心依赖包安装YOLOv8及相关计算机视觉库# 安装Ultralytics YOLOv8 pip install ultralytics # 安装OpenCV用于图像处理 pip install opencv-python # 安装PyQt5用于图形界面 pip install PyQt5 # 安装其他辅助库 pip install matplotlib pandas numpy pillow pip install seaborn # 用于可视化 pip install albumentations # 数据增强2.4 GPU环境配置可选如果使用GPU加速训练需要安装CUDA和cuDNN# 检查CUDA是否可用 python -c import torch; print(torch.cuda.is_available()) # 安装GPU版本的PyTorch根据CUDA版本选择 pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu1183. 数据集准备与预处理3.1 汽车损坏数据集介绍本系统使用专门标注的汽车损坏数据集包含多种损坏类型划痕Scratch凹陷Dent破碎Break锈蚀Rust车灯损坏Light Damage数据集应包含不同角度、光照条件和损坏程度的车辆图像确保模型的泛化能力。3.2 数据格式转换将标注数据转换为YOLOv8所需的格式# 数据格式转换脚本 import os import json from pathlib import Path def convert_coco_to_yolo(coco_json_path, output_dir): 将COCO格式标注转换为YOLOv8格式 with open(coco_json_path, r) as f: coco_data json.load(f) # 创建类别映射 categories {cat[id]: cat[name] for cat in coco_data[categories]} # 按图像分组标注 image_annotations {} for ann in coco_data[annotations]: image_id ann[image_id] if image_id not in image_annotations: image_annotations[image_id] [] image_annotations[image_id].append(ann) # 为每张图像创建YOLO格式的txt文件 for image_info in coco_data[images]: image_id image_info[id] image_name image_info[file_name] width image_info[width] height image_info[height] txt_content [] if image_id in image_annotations: for ann in image_annotations[image_id]: category_id ann[category_id] bbox ann[bbox] # [x, y, width, height] # 转换为YOLO格式中心点坐标和相对宽高 x_center (bbox[0] bbox[2] / 2) / width y_center (bbox[1] bbox[3] / 2) / height w bbox[2] / width h bbox[3] / height txt_content.append(f{category_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) # 保存YOLO格式标注文件 txt_path Path(output_dir) / f{Path(image_name).stem}.txt with open(txt_path, w) as f: f.write(\n.join(txt_content)) # 使用示例 convert_coco_to_yolo(car_damage_coco.json, labels)3.3 数据集目录结构创建标准的数据集目录结构car_damage_dataset/ ├── images/ │ ├── train/ # 训练图像 │ ├── val/ # 验证图像 │ └── test/ # 测试图像 ├── labels/ │ ├── train/ # 训练标注 │ ├── val/ # 验证标注 │ └── test/ # 测试标注 └── dataset.yaml # 数据集配置文件3.4 数据集配置文件创建YOLOv8数据集配置文件# dataset.yaml path: /path/to/car_damage_dataset # 数据集根目录 train: images/train # 训练图像路径 val: images/val # 验证图像路径 test: images/test # 测试图像路径 # 类别信息 nc: 5 # 类别数量 names: [scratch, dent, break, rust, light_damage] # 类别名称 # 下载命令/URL可选 download: None4. YOLOv8模型训练4.1 模型选择与配置YOLOv8提供多种规模的预训练模型from ultralytics import YOLO # 根据需求选择模型规模 model_size yolov8n # 可选: n, s, m, l, x # 加载预训练模型 model YOLO(f{model_size}.pt) # 训练配置 training_config { data: dataset.yaml, epochs: 100, imgsz: 640, batch: 16, device: cuda, # 或 cpu workers: 4, optimizer: auto, lr0: 0.01, # 初始学习率 lrf: 0.01, # 最终学习率 momentum: 0.937, weight_decay: 0.0005, warmup_epochs: 3.0, warmup_momentum: 0.8, box: 7.5, # 框损失权重 cls: 0.5, # 分类损失权重 dfl: 1.5, # DFL损失权重 }4.2 启动模型训练使用YOLOv8的高级训练接口# 开始训练 results model.train( datadataset.yaml, epochs100, imgsz640, batch16, devicecuda, workers4, saveTrue, exist_okTrue, pretrainedTrue, optimizerauto, lr00.01, patience10, # 早停耐心值 projectcar_damage_detection, nameyolov8s_exp1, valTrue, # 开启验证 save_period10, # 每10个epoch保存一次 ) # 或者使用命令行方式 # yolo taskdetect modetrain modelyolov8s.pt datadataset.yaml epochs100 imgsz6404.3 训练过程监控实时监控训练指标和损失函数import matplotlib.pyplot as plt from ultralytics.utils import plots # 绘制训练损失曲线 def plot_training_results(results_path): 绘制训练结果图表 results plots.plot_results(results_path) plt.show() # 实时回调函数监控训练进度 class TrainingCallback: def on_train_epoch_end(self, trainer): print(fEpoch {trainer.epoch}/{trainer.epochs} completed) print(fBox loss: {trainer.loss_items[0]:.4f}) print(fClass loss: {trainer.loss_items[1]:.4f}) print(fDFL loss: {trainer.loss_items[2]:.4f}) # 在训练配置中添加回调 training_config[callbacks] TrainingCallback()4.4 模型评估与验证训练完成后评估模型性能# 加载最佳模型 best_model YOLO(runs/detect/yolov8s_exp1/weights/best.pt) # 在验证集上评估 metrics best_model.val( datadataset.yaml, imgsz640, batch16, conf0.25, # 置信度阈值 iou0.6, # IoU阈值 devicecuda ) print(fmAP50: {metrics.box.map50:.4f}) print(fmAP50-95: {metrics.box.map:.4f}) print(fPrecision: {metrics.box.mp:.4f}) print(fRecall: {metrics.box.mr:.4f})5. 推理检测与结果可视化5.1 单张图像检测实现单张汽车图像的损坏检测import cv2 from ultralytics import YOLO import matplotlib.pyplot as plt class CarDamageDetector: def __init__(self, model_path): self.model YOLO(model_path) self.class_names [scratch, dent, break, rust, light_damage] self.colors [(255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255)] def detect_single_image(self, image_path, conf_threshold0.25): 检测单张图像 # 执行推理 results self.model(image_path, confconf_threshold) # 处理结果 result results[0] image cv2.imread(image_path) image cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 绘制检测框 for box in result.boxes: xyxy box.xyxy[0].cpu().numpy() conf box.conf[0].cpu().numpy() cls int(box.cls[0].cpu().numpy()) # 绘制边界框 cv2.rectangle(image, (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])), self.colors[cls], 2) # 添加标签 label f{self.class_names[cls]}: {conf:.2f} cv2.putText(image, label, (int(xyxy[0]), int(xyxy[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.colors[cls], 2) return image, result # 使用示例 detector CarDamageDetector(best.pt) result_image, detections detector.detect_single_image(test_car.jpg) # 显示结果 plt.figure(figsize(12, 8)) plt.imshow(result_image) plt.axis(off) plt.title(Car Damage Detection Results) plt.show()5.2 批量图像处理实现批量图像的自动化检测import os from pathlib import Path def batch_detect_images(input_dir, output_dir, model_path, conf_threshold0.25): 批量检测图像 detector CarDamageDetector(model_path) input_path Path(input_dir) output_path Path(output_dir) output_path.mkdir(exist_okTrue) # 支持的图像格式 image_extensions [.jpg, .jpeg, .png, .bmp] for image_file in input_path.iterdir(): if image_file.suffix.lower() in image_extensions: print(fProcessing: {image_file.name}) # 执行检测 result_image, detections detector.detect_single_image( str(image_file), conf_threshold ) # 保存结果 output_file output_path / fdetected_{image_file.name} result_image_bgr cv2.cvtColor(result_image, cv2.COLOR_RGB2BGR) cv2.imwrite(str(output_file), result_image_bgr) # 保存检测结果到文本文件 result_txt output_path / fdetected_{image_file.stem}.txt with open(result_txt, w) as f: for box in detections.boxes: xyxy box.xyxy[0].cpu().numpy() conf box.conf[0].cpu().numpy() cls int(box.cls[0].cpu().numpy()) f.write(f{detector.class_names[cls]} {conf:.4f} f{xyxy[0]:.1f} {xyxy[1]:.1f} {xyxy[2]:.1f} {xyxy[3]:.1f}\n) # 批量处理示例 batch_detect_images(input_images, output_results, best.pt)5.3 视频流实时检测实现摄像头或视频文件的实时检测import cv2 import time class VideoDamageDetector: def __init__(self, model_path, source0): self.detector CarDamageDetector(model_path) self.cap cv2.VideoCapture(source) self.fps 0 self.frame_count 0 self.start_time time.time() def process_frame(self, frame): 处理单帧图像 # 转换颜色空间 frame_rgb cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 执行推理 results self.detector.model(frame_rgb) result results[0] # 绘制检测结果 for box in result.boxes: xyxy box.xyxy[0].cpu().numpy() conf box.conf[0].cpu().numpy() cls int(box.cls[0].cpu().numpy()) # 绘制边界框和标签 cv2.rectangle(frame, (int(xyxy[0]), int(xyxy[1])), (int(xyxy[2]), int(xyxy[3])), self.detector.colors[cls], 2) label f{self.detector.class_names[cls]}: {conf:.2f} cv2.putText(frame, label, (int(xyxy[0]), int(xyxy[1])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.detector.colors[cls], 2) return frame def run(self): 运行视频检测 while True: ret, frame self.cap.read() if not ret: break # 处理帧 processed_frame self.process_frame(frame) # 计算并显示FPS self.frame_count 1 if self.frame_count 30: self.fps 30 / (time.time() - self.start_time) self.start_time time.time() self.frame_count 0 cv2.putText(processed_frame, fFPS: {self.fps:.1f}, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) # 显示结果 cv2.imshow(Car Damage Detection, processed_frame) # 退出条件 if cv2.waitKey(1) 0xFF ord(q): break self.cap.release() cv2.destroyAllWindows() # 使用示例 video_detector VideoDamageDetector(best.pt, sourcetest_video.mp4) video_detector.run()6. PyQt5图形界面开发6.1 主界面设计创建用户友好的图形界面import sys from PyQt5.QtWidgets import (QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QPushButton, QLabel, QFileDialog, QTextEdit, QWidget, QSlider, QSpinBox) from PyQt5.QtCore import Qt, QThread, pyqtSignal from PyQt5.QtGui import QPixmap, QImage import cv2 class DetectionThread(QThread): 检测线程避免界面卡顿 finished pyqtSignal(object) def __init__(self, detector, image_path): super().__init__() self.detector detector self.image_path image_path def run(self): result_image, detections self.detector.detect_single_image(self.image_path) self.finished.emit((result_image, detections)) class CarDamageApp(QMainWindow): def __init__(self): super().__init__() self.detector None self.current_image None self.init_ui() def init_ui(self): 初始化用户界面 self.setWindowTitle(汽车损坏识别检测系统) self.setGeometry(100, 100, 1200, 800) # 中央部件 central_widget QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout QHBoxLayout() central_widget.setLayout(main_layout) # 左侧控制面板 control_panel self.create_control_panel() main_layout.addWidget(control_panel, 1) # 右侧显示区域 display_panel self.create_display_panel() main_layout.addWidget(display_panel, 2) def create_control_panel(self): 创建控制面板 panel QWidget() layout QVBoxLayout() # 模型加载按钮 self.load_model_btn QPushButton(加载模型) self.load_model_btn.clicked.connect(self.load_model) layout.addWidget(self.load_model_btn) # 图像选择按钮 self.load_image_btn QPushButton(选择图像) self.load_image_btn.clicked.connect(self.load_image) layout.addWidget(self.load_image_btn) # 置信度阈值设置 layout.addWidget(QLabel(置信度阈值:)) self.conf_slider QSlider(Qt.Horizontal) self.conf_slider.setRange(10, 90) # 0.1-0.9 self.conf_slider.setValue(25) # 默认0.25 self.conf_slider.valueChanged.connect(self.update_conf_label) layout.addWidget(self.conf_slider) self.conf_label QLabel(0.25) layout.addWidget(self.conf_label) # 检测按钮 self.detect_btn QPushButton(开始检测) self.detect_btn.clicked.connect(self.start_detection) self.detect_btn.setEnabled(False) layout.addWidget(self.detect_btn) # 结果显示区域 layout.addWidget(QLabel(检测结果:)) self.result_text QTextEdit() self.result_text.setReadOnly(True) layout.addWidget(self.result_text) panel.setLayout(layout) return panel def create_display_panel(self): 创建显示面板 panel QWidget() layout QVBoxLayout() # 图像显示标签 self.image_label QLabel() self.image_label.setAlignment(Qt.AlignCenter) self.image_label.setMinimumSize(640, 480) self.image_label.setText(请选择图像文件) layout.addWidget(self.image_label) panel.setLayout(layout) return panel def load_model(self): 加载模型文件 model_path, _ QFileDialog.getOpenFileName( self, 选择模型文件, , 模型文件 (*.pt) ) if model_path: try: self.detector CarDamageDetector(model_path) self.result_text.append(模型加载成功!) self.detect_btn.setEnabled(True) except Exception as e: self.result_text.append(f模型加载失败: {str(e)}) def load_image(self): 加载图像文件 image_path, _ QFileDialog.getOpenFileName( self, 选择图像文件, , 图像文件 (*.jpg *.jpeg *.png *.bmp) ) if image_path: self.current_image image_path pixmap QPixmap(image_path) scaled_pixmap pixmap.scaled(640, 480, Qt.KeepAspectRatio) self.image_label.setPixmap(scaled_pixmap) self.result_text.append(f已加载图像: {image_path}) def update_conf_label(self, value): 更新置信度阈值显示 conf value / 100.0 self.conf_label.setText(f{conf:.2f}) def start_detection(self): 开始检测 if not self.detector or not self.current_image: self.result_text.append(请先加载模型和图像!) return conf_threshold self.conf_slider.value() / 100.0 # 在子线程中执行检测 self.detection_thread DetectionThread(self.detector, self.current_image) self.detection_thread.finished.connect(self.on_detection_finished) self.detection_thread.start() self.result_text.append(开始检测...) def on_detection_finished(self, result): 检测完成回调 result_image, detections result # 转换图像格式用于显示 height, width, channel result_image.shape bytes_per_line 3 * width q_img QImage(result_image.data, width, height, bytes_per_line, QImage.Format_RGB888) pixmap QPixmap.fromImage(q_img) scaled_pixmap pixmap.scaled(640, 480, Qt.KeepAspectRatio) self.image_label.setPixmap(scaled_pixmap) # 显示检测结果 self.result_text.append(检测完成!) for i, box in enumerate(detections.boxes): xyxy box.xyxy[0].cpu().numpy() conf box.conf[0].cpu().numpy() cls int(box.cls[0].cpu().numpy()) self.result_text.append( f目标 {i1}: {self.detector.class_names[cls]} f(置信度: {conf:.3f}) f位置: [{xyxy[0]:.1f}, {xyxy[1]:.1f}, {xyxy[2]:.1f}, {xyxy[3]:.1f}] ) def main(): app QApplication(sys.argv) window CarDamageApp() window.show() sys.exit(app.exec_()) if __name__ __main__: main()6.2 界面功能扩展增强图形界面的功能性# 在CarDamageApp类中添加以下方法 def create_menu_bar(self): 创建菜单栏 menubar self.menuBar() # 文件菜单 file_menu menubar.addMenu(文件) open_action QAction(打开图像, self) open_action.setShortcut(CtrlO) open_action.triggered.connect(self.load_image) file_menu.addAction(open_action) save_action QAction(保存结果, self) save_action.setShortcut(CtrlS) save_action.triggered.connect(self.save_result) file_menu.addAction(save_action) # 视图菜单 view_menu menubar.addMenu(视图) zoom_in_action QAction(放大, self) zoom_in_action.setShortcut(Ctrl) zoom_in_action.triggered.connect(self.zoom_in) view_menu.addAction(zoom_in_action) zoom_out_action QAction(缩小, self) zoom_out_action.setShortcut(Ctrl-) zoom_out_action.triggered.connect(self.zoom_out) view_menu.addAction(zoom_out_action) def save_result(self): 保存检测结果 if not hasattr(self, last_result_image): self.result_text.append(没有可保存的结果!) return save_path, _ QFileDialog.getSaveFileName( self, 保存结果图像, , PNG图像 (*.png);;JPEG图像 (*.jpg) ) if save_path: cv2.imwrite(save_path, self.last_result_image) self.result_text.append(f结果已保存到: {save_path}) def zoom_in(self): 放大图像 current_pixmap self.image_label.pixmap() if current_pixmap: new_size current_pixmap.size() * 1.2 scaled_pixmap current_pixmap.scaled(new_size, Qt.KeepAspectRatio) self.image_label.setPixmap(scaled_pixmap) def zoom_out(self): 缩小图像 current_pixmap self.image_label.pixmap() if current_pixmap: new_size current_pixmap.size() * 0.8 scaled_pixmap current_pixmap.scaled(new_size, Qt.KeepAspectRatio) self.image_label.setPixmap(scaled_pixmap)7. 模型优化与性能提升7.1 数据增强策略通过数据增强提升模型泛化能力from ultralytics import YOLO import albumentations as A def get_augmentation_pipeline(): 定义数据增强管道 return A.Compose([ A.HorizontalFlip(p0.5), A.RandomBrightnessContrast(p0.2), A.HueSaturationValue(p0.2), A.RandomGamma(p0.2), A.Blur(blur_limit3, p0.1), A.MedianBlur(blur_limit3, p0.1), A.ToGray(p0.1), A.ChannelShuffle(p0.1), ], bbox_paramsA.BboxParams(formatyolo, label_fields[class_labels])) # 在训练配置中启用数据增强 training_config[augment] True training_config[hsv_h] 0.015 # 图像色调增强 training_config[hsv_s] 0.7 # 图像饱和度增强 training_config[hsv_v] 0.4 # 图像亮度增强 training_config[fliplr] 0.5 # 水平翻转概率7.2 模型剪枝与量化优化模型大小和推理速度def optimize_model(model_path, output_path): 模型优化剪枝和量化 model YOLO(model_path) # 导出为ONNX格式自动优化 model.export(formatonnx, imgsz640, simplifyTrue) # 进一步优化ONNX模型 import onnx from onnxsim import simplify onnx_model onnx.load(f{model_path.stem}.onnx) simplified_model, check simplify(onnx_model) onnx.save(simplified_model, output_path) print(f优化后的模型已保存到: {output_path}) # 使用示例 optimize_model(best.pt, optimized_model.onnx)7.3 多尺度训练与测试提升模型对不同尺度目标的检测能力# 多尺度训练配置 training_config[multi_scale] True training_config[imgsz] [320, 640] # 多尺度训练 # 多尺度推理 def multi_scale_inference(model, image_path, scales[0.5, 1.0, 1.5]): 多尺度推理 all_results [] original_image cv2.imread(image_path) for scale in scales: # 调整图像尺寸 new_width int(original_image.shape[1] * scale) new_height int(original_image.shape[0] * scale) resized_image cv2.resize(original_image, (new_width, new_height)) # 执行推理 results model(resized_image) all_results.append((scale, results[0])) # 合并多尺度结果需要实现融合逻辑 return merge_multi_scale_results(all_results, original_image.shape)8. 系统部署与集成8.1 创建可执行文件使用PyInstaller打包为独立应用# 创建spec文件 pyi-makespec --onefile --windowed car_damage_app.py # 修改spec文件添加数据文件 # 在Analysis部分添加 # datas[(best.pt, .), (ui/*.ui, ui)] # 打包应用 pyinstaller car_damage_app.spec8.2 Docker容器化部署创建Dockerfile用于生产环境部署FROM python:3.9-slim # 设置工作目录 WORKDIR /app # 安装系统依赖 RUN apt-get update apt-get install -y \ libgl1-mesa-glx \ libglib2.0-0 \ rm -rf /var/lib/apt/lists/* # 复制依赖文件 COPY requirements.txt . # 安装Python依赖 RUN pip install --no-cache-dir -r requirements.txt # 复制应用代码和模型 COPY . . # 暴露端口如果需要Web服务 EXPOSE 8000 # 启动命令 CMD [python, car_damage_app.py]8.3 Web服务接口创建REST API接口供其他系统调用from flask import Flask, request, jsonify from werkzeug.utils import secure_filename import os import cv2 app Flask(__name__) app.config[UPLOAD_FOLDER] uploads app.config[MAX_CONTENT_LENGTH] 16 * 1024 * 1024 # 16MB # 全局检测器实例 detector None def init_detector(): global detector detector CarDamageDetector(best.pt) app.route(/api/detect, methods[POST]) def detect_damage(): 汽车损坏检测API接口 if image not in request.files: return jsonify({error: No image file}), 400 file request.files[image] if file.filename : return jsonify({error: No selected file}), 400 # 保存上传的文件 filename secure_filename(file.filename) filepath os.path.join(app.config[UPLOAD_FOLDER], filename) file.save(filepath) try: # 执行检测 conf_threshold float(request.form.get(confidence, 0.25)) result_image, detections detector.detect_single_image(filepath, conf_threshold) # 构建响应 results [] for i, box in enumerate(detections.boxes): xyxy box.xyxy[0].cpu().numpy() conf box.conf[0].cpu().numpy() cls int(box.cls[0].cpu().numpy()) results.append({ id: i 1, class: detector.class_names[cls], confidence: float(conf), bbox: { x1: float(xyxy[0]), y1: float(xyxy[1]), x2: float(xyxy[2]), y2: float(xyxy[3]) } }) return jsonify({ status: success, results: results, image_size: result_image.shape[:2] }) except Exception as e: return jsonify({error: str(e)}), 500 finally: # 清理临时文件 if os.path.exists(filepath): os.remove(filepath) if __name__ __main__: init_detector() os.makedirs(app.config[UPLOAD_FOLDER], exist_okTrue) app.run(host0.0.0.0, port8000, debugFalse)9.