AI+交通应用入门:用YOLOv8搭建车牌识别服务

AI+交通应用听起来跨度很大,但落到具体场景,很多需求可以拆成“检测目标 + 识别内容 + 提供服务”三步。
这篇教程以车牌识别为例,带你在 Linux 服务器上跑通一个可调用的 HTTP 服务,适合想验证 AI 交通应用是否可行的零基础读者。

先确认你要解决的是检测还是识别

车牌识别通常包含两个子任务:先从图片或视频帧里找到车牌位置,再把车牌上的字符读出来。
只做检测没有业务价值,只做识别又容易把背景文字误读成车牌,所以实际项目里两者要串联。

本文的适用条件是:你有基本的 Linux 命令行操作能力,服务器有可用的 Python 环境或 Docker,图片质量不过度模糊。
如果只是想做离线批量处理,可以跳过 API 封装部分,直接看推理脚本。

环境准备上,推荐使用 Docker 隔离依赖,避免和服务器上已有 Python 项目冲突。
没有 Docker 的机器也可以用 venv,但需要自己处理 OpenCV 和 PyTorch 的版本兼容问题。

# 创建项目目录
mkdir -p /opt/plate-ocr && cd /opt/plate-ocr
# 拉取带 Python 3.10 的基础镜像
docker pull python:3.10-slim

安装依赖并准备模型文件

在项目目录下新建 requirements.txt,写入以下内容。
这里锁定主版本号,避免自动升级到不兼容的版本。

ultralytics==8.2.*
paddlepaddle==2.6.*
paddleocr==2.7.*
fastapi==0.111.*
uvicorn==0.30.*
opencv-python-headless==4.9.*

然后启动容器并安装依赖:

docker run -it --name plate-ocr -p 8000:8000 \
  -v /opt/plate-ocr:/workspace \
  python:3.10-slim bash

# 容器内执行
cd /workspace
pip install -r requirements.txt

模型文件方面,YOLOv8 需要车牌检测权重。
如果你没有训练好的权重,可以先用官方通用模型验证流程,但通用模型对车牌这类小目标效果有限,正式使用需要用自己的车牌数据集微调。
PaddleOCR 首次运行会自动下载中文识别模型,需要容器能访问外网。

编写检测与识别串联脚本

新建 plate_service.py,先实现单张图片的处理逻辑。
思路是:YOLO 检测出车牌框,按坐标裁剪,再交给 PaddleOCR 识别文字。

from ultralytics import YOLO
from paddleocr import PaddleOCR
import cv2

# 替换为你自己的车牌检测权重路径
detector = YOLO("weights/plate_det.pt")
ocr = PaddleOCR(use_angle_cls=True, lang="ch")

def recognize_plate(image_path):
    img = cv2.imread(image_path)
    results = detector(img, conf=0.4)
    plates = []
    for box in results[0].boxes.xyxy.cpu().numpy():
        x1, y1, x2, y2 = map(int, box[:4])
        crop = img[y1:y2, x1:x2]
        ocr_result = ocr.ocr(crop, cls=True)
        texts = [line[1][0] for line in ocr_result[0]] if ocr_result[0] else []
        plates.append({"box": [x1, y1, x2, y2], "text": "".join(texts)})
    return plates

这段代码的关键点是 conf=0.4,置信度阈值太低会引入误检,太高会漏掉模糊车牌。
建议先用一批测试图跑一遍,观察漏检和误检比例再调整。

用 FastAPI 暴露 HTTP 接口

在同一个文件里追加接口层,让外部系统可以通过上传图片调用识别能力。

from fastapi import FastAPI, UploadFile, File
import shutil, os

app = FastAPI()

@app.post("/recognize")
async def recognize(file: UploadFile = File(...)):
    tmp_path = f"/tmp/{file.filename}"
    with open(tmp_path, "wb") as f:
        shutil.copyfileobj(file.file, f)
    try:
        result = recognize_plate(tmp_path)
    finally:
        os.remove(tmp_path)
    return {"plates": result}

启动服务:

uvicorn plate_service:app --host 0.0.0.0 --port 8000

看到 Uvicorn running on http://0.0.0.0:8000 说明服务已经监听。
用 curl 上传一张测试图验证:

curl -X POST http://127.0.0.1:8000/recognize \
  -F "file=@/workspace/test.jpg"

返回 JSON 中 plates 数组为空,说明检测阶段没有找到车牌,优先检查权重文件和置信度;
有框但 text 为空,说明裁剪区域或 OCR 语言配置有问题。

容易踩坑的地方

第一,PaddleOCR 默认下载模型需要网络,服务器无外网时会卡在下载阶段,需要提前把模型缓存目录挂载进容器。
第二,opencv-python-headless 和带 GUI 的版本不要同时安装,否则容易出现库冲突。
第三,车牌图片分辨率过低时,先做等比放大再送检测,比直接调低阈值更稳。
第四,生产环境不要把 --host 0.0.0.0 直接暴露到公网,应放在 Nginx 反向代理后面并加访问控制。

如果服务运行一段时间后内存持续上涨,优先检查是否在循环里重复创建 PaddleOCR 实例,OCR 对象应该全局初始化一次。

怎么判断这套流程是否可用

准备 20 到 50 张不同光照和角度的车牌图片,人工标注正确结果,跑一遍接口统计两个指标:检测召回率和字符准确率。
检测召回率低于预期时,先补充训练数据;
字符准确率偏低时,检查裁剪是否包含完整车牌边缘。

单张图片响应时间在 CPU 环境下通常明显慢于 GPU,如果业务要求实时视频流识别,需要评估帧率和硬件成本,不能直接套用图片接口的结论。

常见疑问方面,没有标注数据能不能直接用通用模型?
可以跑通流程,但车牌场景的准确率通常不理想,建议至少收集几百张实际场景图片做微调。
接口能不能直接处理视频?
当前示例只处理单张图片,视频需要抽帧后逐帧调用,并额外做去重逻辑。

到这里,一个最小可用的 AI+交通应用原型就完成了。
建议先按本文步骤在测试环境跑通,再根据实际图片质量调整阈值和模型,不要一开始就追求全场景覆盖。

分享到:
上一篇
AI农业无人机配置:从开箱到首飞的完整流程
下一篇
AI自动驾驶配置入门:从环境准备到参数调优的完整流程
1
系统公告

泽御云中秋国庆双节活动上线:新购8折,拼团3.99元起

尊敬的用户:
泽御云“月满中秋·礼贺国庆”双节活动现已开启,活动时间为2026年9月23日至10月10日。 活动期间可享以下福利:
1. 常规云服务器新购使用优惠码“泽御中秋国庆同乐”,符合条件的订单享8折优惠。
2. 香港精品云服务器5人拼团低至3.99元,部分4核4G套餐3人拼团年付388元,续费同价。
3. 新用户购买年付云服务器,符合活动规则可赠送2个月使用时长。
4. 老用户续费季度赠15天,续费年度赠2个月;活动期间升级配置免收配置迁移手续费。
5. 推荐好友成功下单,符合条件的推荐人可获赠7天服务器使用时长。
6. 活动期间享宕机补偿标准翻倍、简单网站迁移协助及技术工单优先处理权益。
温馨提示:优惠码不适用于拼团套餐、活动轻量产品、年付订单及续费订单;拼团套餐为独立特价活动,不与赠时类福利叠加。赠送时长不可折现、退款或跨账户转移,具体规则以活动页面说明为准。
服务中心
客服
在线客服
24小时为您服务
咨询
联系我们
联系我们,为您的业务提供专属服务。
24/7 技术支持
如果您遇到寻求进一步的帮助,请过工单与我们进行联系。
24/7 即时支持
泽御云
售前客服
泽御云
泽御云
售后客服
泽御云
技术支持
评价
您对当前页面的整体感受是否满意?
😞
非常不满意
😕
不满意
😐
一般
🙂
满意
😊
非常满意