YOLOv8车牌识别模型部署实战:从训练好的.pt文件到Flask Web应用(含前端界面)
当你的YOLOv8模型在测试集上表现优异时,真正的挑战才刚刚开始——如何让这个"实验室宠儿"变成人人可用的服务?我曾见过太多团队卡在模型部署这一环,最终让精心训练的模型束之高阁。本文将带你完整走通从.pt文件到生产级Web应用的最后一公里,重点解决三个核心痛点:如何设计高并发的推理服务、如何实现前后端高效交互、以及如何优化实时视频流处理。
1. 环境准备与模型封装
1.1 基础环境配置
建议使用conda创建隔离环境,避免依赖冲突:
bash复制conda create -n plate-detection python=3.9
conda activate plate-detection
pip install ultralytics flask flask-cors opencv-python gunicorn
对于生产环境,推荐使用Docker固化运行环境。这里给出一个优化后的Dockerfile:
dockerfile复制FROM nvidia/cuda:11.8.0-runtime-ubuntu22.04
RUN apt-get update && apt-get install -y python3.9 python3-pip
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY app.py model_utils.py /app/
WORKDIR /app
EXPOSE 5000
CMD ["gunicorn", "-w 4", "-b :5000", "app:app"]
1.2 模型服务化封装
直接加载.pt文件虽然简单,但在Web服务中会带来内存管理问题。我们需要将模型封装为可重用的服务类:
python复制import cv2
import numpy as np
from ultralytics import YOLO
from threading import Lock
class PlateDetector:
def __init__(self, model_path):
self.model = YOLO(model_path)
self.lock = Lock()
def detect(self, img, conf_threshold=0.5):
"""线程安全的检测方法"""
with self.lock:
results = self.model.predict(
source=img,
conf=conf_threshold,
imgsz=640,
verbose=False
)
return results[0].plot() if results else img
关键优化点:
- 使用线程锁保证多请求时的线程安全
- 关闭verbose输出减少日志污染
- 返回带标注的图像而非原始结果,简化接口
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. Flask后端服务搭建
2.1 REST API设计
采用蓝图(Blueprint)组织API路由,保持代码模块化:
python复制from flask import Blueprint, request, jsonify
from werkzeug.utils import secure_filename
import os
api = Blueprint('api', __name__)
@api.route('/detect', methods=['POST'])
def detect_image():
if 'file' not in request.files:
return jsonify({"error": "No file uploaded"}), 400
file = request.files['file']
if file.filename == '':
return jsonify({"error": "Empty filename"}), 400
conf = float(request.form.get('conf', 0.5))
img = cv2.imdecode(np.frombuffer(file.read(), np.uint8), cv2.IMREAD_COLOR)
result_img = detector.detect(img, conf)
_, buffer = cv2.imencode('.jpg', result_img)
return buffer.tobytes(), 200, {'Content-Type': 'image/jpeg'}
2.2 视频流处理优化
实时视频检测需要特殊处理以避免阻塞主线程:
python复制import time
from concurrent.futures import ThreadPoolExecutor
executor = ThreadPoolExecutor(2)
def generate_frames(camera_id=0):
cap = cv2.VideoCapture(camera_id)
while True:
success, frame = cap.read()
if no
