ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

树莓派+特斯拉:本地车牌识别系统实战,从模型量化到车机集成

树莓派+特斯拉:本地车牌识别系统实战,从模型量化到车机集成 1. 这个项目到底在折腾什么先说清楚这个项目在干什么。特斯拉全系车型原厂都不带行车记录仪的车牌抓拍功能哨兵模式虽然能录视频但录下来的都是原始画面事后想找某个特定车牌只能一帧一帧拖进度条眼睛都看花了。这个开源项目的思路很直接用树莓派挂一个摄像头模块跑一个轻量级的车牌检测加识别模型把识别结果通过本地网络推给车机或者手机实现车停着也在自动记录进出车辆车牌的效果。说白了就是给特斯拉补上一块它原厂没有的能力——车牌级别的结构化记录。适合谁看如果你手上有树莓派4B或者树莓派5平时喜欢折腾嵌入式项目又恰好是特斯拉车主那这个项目基本就是为你量身定做的。就算你不是特斯拉车主这套车牌识别的技术栈放到小区门口、停车场道闸、公司门禁这些场景里一样能用只是触发方式和供电方案要改一改。我实测下来整套系统的核心难点不在模型本身而在于树莓派这种算力有限的设备上怎么把检测和识别跑得又快又稳。网上很多教程直接拿YOLOv5的完整版往上怼结果树莓派4B跑起来一帧要两秒多车牌早开走了。所以这个项目的价值在于它做了一系列工程上的取舍把整个链路压到了可用的程度。提示这个项目涉及的是本地车牌识别所有数据都在你自己的设备上处理不涉及任何云端上传隐私性是有保障的。2. 整体方案设计与选型逻辑2.1 为什么是树莓派而不是其他开发板选树莓派做这个项目核心原因有三个。第一是生态成熟树莓派的摄像头模块驱动、Python库、系统镜像都极其完善你不需要花大量时间在底层驱动上。第二是算力够用树莓派4B的博通BCM2711四核A72处理器配合VideoCore VI GPU跑一个量化后的轻量模型是能接受的。第三是供电方便特斯拉的USB接口或者点烟器转USB都能直接给树莓派供电不需要额外的电源管理模块。有人会问为什么不选Jetson Nano或者RK3588这类NPU开发板。答案很简单成本和功耗。Jetson Nano满载功耗能到10W以上夏天车内温度本来就高散热是个大问题。树莓派4B满载大概5W左右树莓派5稍微高一点但也在可控范围内。而且这个项目对算力的需求并没有那么夸张车牌识别是一个相对窄的任务不需要通用大模型那种算力。至于STM32或者RP2040这类单片机算力根本不够跑神经网络只能做简单的图像传输所以不在考虑范围内。2.2 检测加识别的两阶段架构整个系统采用的是两阶段方案先检测车牌位置再对车牌区域做字符识别。为什么不直接用端到端的OCR因为端到端方案在树莓派上要么精度不够要么速度太慢。两阶段的好处是检测阶段可以用非常轻量的模型识别阶段只处理裁剪出来的小图计算量大幅降低。检测阶段我推荐用YOLOv5n或者YOLOv8n这两个模型参数量都在200万左右经过INT8量化后在树莓派4B上能做到5到8帧每秒。识别阶段用LPRNet或者CRNN这两个都是专门为车牌识别设计的轻量网络输入是32x100左右的小图单帧推理时间在30毫秒以内。这里有个关键取舍检测模型负责找到车牌识别模型负责读懂车牌。两个模型各司其职互不干扰。如果你把两个任务塞进一个模型模型会变得臃肿而且训练难度大幅上升。2.3 数据流与触发机制整个数据流是这样的摄像头持续采集画面检测模型对每一帧做推理如果检测到车牌且置信度超过阈值就把车牌区域裁剪出来送给识别模型识别结果连同时间戳一起写入本地数据库同时通过HTTP接口推送到车机或者手机端。触发机制有两种模式。一种是常开模式摄像头一直工作适合停车监控场景。另一种是移动侦测模式只有画面发生变化时才启动检测省电但可能漏掉快速通过的车辆。我建议用常开模式配合一个简单的帧差法做预筛选既省算力又不漏检。注意特斯拉的USB接口在车辆休眠后会断电如果你要24小时监控需要从保险盒取常电这个操作有一定风险建议找专业改装店处理。3. 硬件准备与关键细节3.1 树莓派型号选择与供电方案树莓派4B和树莓派5都能跑这个项目但体验有差异。树莓派4B的USB接口是USB 2.0如果你用USB摄像头带宽可能成为瓶颈。树莓派5升级到了USB 3.0同时PCIe接口可以外接NVMe固态硬盘系统响应速度明显更快。如果预算允许我建议直接上树莓派5。供电方面特斯拉Model 3和Model Y的中控扶手箱里有两个USB-C接口能提供大概15W的功率给树莓派5供电是够的。但要注意车辆锁车后这些接口会断电。如果你只是想在行车过程中记录那没问题如果要停车监控就得从OBD接口或者保险盒取电。我自己的方案是用一个USB-C PD诱骗器加一个降压模块从保险盒取12V常电降到5V 3A给树莓派供电。这个方案的好处是稳定不会因为车辆休眠而断电。但接线一定要做好绝缘和保险车内高温环境下线材老化很快。3.2 摄像头模块的选型对比摄像头是整个系统的眼睛选不好后面全白搭。我整理了一个对比表格摄像头型号接口类型分辨率帧率夜视能力价格区间推荐场景OV5647CSI500万1080p30一般30-50元入门测试IMX219CSI800万1080p30较好60-90元日常使用IMX477CSI1230万1080p60好200-300元高质量需求USB免驱摄像头USB200万1080p30取决于型号50-150元灵活安装CSI接口的摄像头直接插在树莓派的排线座上延迟低CPU占用少。USB摄像头安装灵活但会占用USB带宽而且树莓派4B的USB 2.0接口带宽有限同时接摄像头和4G模块可能会卡。我实测下来IMX219是性价比最高的选择。500万像素的OV5647在夜间噪点明显车牌识别率会下降。IMX477效果最好但价格偏高而且树莓派4B的ISP处理能力有限发挥不出它的全部实力。3.3 散热与防护车内环境对电子设备很不友好夏天暴晒后车内温度能到60度以上。树莓派5的发热比4B大不少必须加散热片或者主动风扇。我建议用金属外壳加散热硅胶垫的方案比塑料外壳加风扇更可靠因为风扇在高温下寿命会缩短。防护方面摄像头要选带红外补光的型号否则夜间完全没法用。外壳最好选IP65以上的防水盒走线的地方用防水接头。如果你不想折腾可以直接买现成的车载摄像头外壳把树莓派主板塞进去。4. 软件环境搭建与模型部署4.1 系统镜像选择与基础配置树莓派官方系统我推荐用Raspberry Pi OS Lite 64位版本不带桌面环境省内存省CPU。如果你习惯用Ubuntu树莓派5上可以装Ubuntu 24.04但要注意摄像头驱动在Ubuntu上的支持不如官方系统完善。系统烧录完成后第一件事是换源。国内访问官方源速度很慢换成清华或者中科大的镜像源apt安装速度能快十倍。具体操作是编辑/etc/apt/sources.list和/etc/apt/sources.list.d/下的文件把raspbian.raspberrypi.org替换成mirrors.tuna.tsinghua.edu.cn/raspbian。然后开启SSH和摄像头接口。在raspi-config里找到Interface Options把Camera和SSH都打开。如果你是无屏幕安装可以在boot分区放一个空的ssh文件来开启SSH。4.2 Python环境与依赖安装不要用系统自带的Python建议用Miniconda创建一个独立环境。这样做的原因是OpenCV、ONNX Runtime这些库的版本依赖比较复杂独立环境可以避免污染系统Python。wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh bash Miniconda3-latest-Linux-aarch64.sh conda create -n lpr python3.9 conda activate lpr然后安装核心依赖pip install opencv-python-headless pip install onnxruntime pip install numpy pip install picamera2 pip install flask这里有个坑树莓派上不要装完整的opencv-python要装opencv-python-headless因为完整版依赖GUI库在Lite系统上会报错。另外ONNX Runtime要选ARM64版本pip会自动识别但如果你手动下载whl文件一定要确认架构。4.3 模型转换与量化训练好的模型通常是PyTorch的.pt格式需要转成ONNX才能在树莓派上跑。转换命令如下import torch model torch.load(best.pt, map_locationcpu) dummy_input torch.randn(1, 3, 640, 640) torch.onnx.export(model, dummy_input, lpr.onnx, opset_version11)转成ONNX后还要做INT8量化。量化的目的是把FP32的权重压缩成INT8模型体积缩小四倍推理速度提升两到三倍。ONNX Runtime提供了量化工具from onnxruntime.quantization import quantize_dynamic, QuantType quantize_dynamic(lpr.onnx, lpr_int8.onnx, weight_typeQuantType.QUInt8)量化会带来一定的精度损失实测下来车牌识别准确率大概下降1到2个百分点但速度提升非常明显。如果你的场景对精度要求极高可以用FP16代替INT8速度提升小一些但精度损失也小。提示量化后的模型在树莓派5上的推理速度比树莓派4B快大约40%如果预算允许升级到树莓派5的收益是很明显的。5. 核心代码实现与参数调优5.1 摄像头采集与预处理摄像头采集用picamera2库这是树莓派官方推荐的库比老版的picamera更稳定。采集到的画面是RGB格式需要转成模型需要的输入格式。from picamera2 import Picamera2 import cv2 import numpy as np picam2 Picamera2() config picam2.create_preview_configuration(main{size: (640, 480)}) picam2.configure(config) picam2.start() frame picam2.capture_array() frame cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)预处理包括缩放、归一化、通道转换。YOLO系列模型的输入是640x640所以要把画面缩放到这个尺寸。归一化是把像素值从0-255映射到0-1之间。通道转换是因为OpenCV读进来是BGR模型需要RGB。这里有个细节保持宽高比。如果直接把画面拉伸到640x640车牌会变形检测精度会下降。正确做法是等比例缩放然后填充灰边。5.2 检测模型的推理与后处理ONNX Runtime的推理代码很简洁import onnxruntime as ort session ort.InferenceSession(lpr_int8.onnx) input_name session.get_inputs()[0].name output session.run(None, {input_name: blob})后处理是YOLO系列最麻烦的部分。输出是一个多维数组需要做置信度过滤、非极大值抑制、坐标还原。置信度阈值我建议设0.5太低会误检太高会漏检。NMS的IOU阈值设0.45这个值是经过大量测试得出的经验值。坐标还原要注意模型输出的是相对于640x640输入图的坐标要映射回原始画面尺寸。如果你做了填充还要减去填充的偏移量。5.3 识别模型的推理与字符解码识别模型输入是裁剪出来的车牌小图尺寸通常是32x100。预处理包括灰度化、直方图均衡化、归一化。直方图均衡化能显著提升逆光和夜间场景的识别率。gray cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY) gray cv2.equalizeHist(gray) gray cv2.resize(gray, (100, 32)) gray gray.astype(np.float32) / 255.0 gray np.expand_dims(gray, axis[0, 1])LPRNet的输出是每个字符位置的概率分布需要用CTC解码。CTC解码的核心思想是合并重复字符和去除空白符。比如输出序列是京A-1-1-2-3-3CTC会合并成京A123。5.4 参数调优的实战经验调参这块我踩过不少坑分享几个关键点。检测阈值不要设太高0.5是个比较平衡的值但如果你发现漏检严重可以降到0.4。NMS的IOU阈值在车牌场景下可以设低一点0.4左右因为车牌之间通常不会重叠。识别模型的输入尺寸也很关键。32x100是标准尺寸但如果你发现识别率低可以试试48x144代价是推理时间增加约50%。直方图均衡化在夜间场景下效果非常明显但在强光下可能适得其反可以根据环境亮度动态决定是否启用。注意树莓派的CPU温度超过80度会降频推理速度会骤降。建议在代码里加一个温度监控超过75度就主动降低帧率。6. 常见问题与排查实录6.1 摄像头无法识别或画面全黑这是最常见的问题原因通常有三个。第一是排线没插紧CSI排线很容易松动重新插拔一次试试。第二是摄像头接口没开启在raspi-config里确认Camera选项是enabled状态。第三是供电不足树莓派5对电源要求比较高用5V 3A以下的电源可能导致摄像头工作异常。排查步骤先用libcamera-hello命令测试摄像头如果这个命令能出画面说明硬件没问题问题在代码里。如果这个命令也报错那就是硬件或者驱动的问题。6.2 推理速度慢到无法接受树莓派4B上如果推理一帧超过500毫秒基本就没法用了。速度慢的原因可能是模型没量化、输入尺寸太大、CPU降频。先确认模型是INT8量化的然后检查输入尺寸是不是640x640最后用vcgencmd measure_temp看温度。如果温度正常但速度还是慢可以试试多线程推理。ONNX Runtime支持设置线程数options ort.SessionOptions() options.intra_op_num_threads 4 session ort.InferenceSession(lpr_int8.onnx, options)树莓派4B是四核设4个线程能充分利用CPU。但要注意线程数不是越多越好超过核心数反而会因为上下文切换导致性能下降。6.3 车牌识别率低识别率低的原因很复杂我整理了一个排查表现象可能原因解决方法白天识别率高夜间低补光不足加红外补光灯近距离识别率高远距离低分辨率不够换高分辨率摄像头正对识别率高斜角低训练数据角度单一补充斜角训练数据蓝牌识别率高绿牌低训练数据不均衡补充新能源车牌数据静止识别率高运动模糊快门速度慢提高快门速度或降低车速我实测下来夜间识别是最大的痛点。红外补光能解决一部分问题但红外下的车牌反光特性和可见光不同模型需要专门训练。如果你不想重新训练可以在夜间把识别阈值降低接受一定的误识率。6.4 系统运行一段时间后崩溃长时间运行崩溃通常是内存泄漏或者温度过高。Python的垃圾回收机制在处理大量numpy数组时可能不及时建议在循环里手动调用gc.collect()。温度问题前面说过了加散热片或者降频。还有一个容易被忽略的原因是SD卡寿命。树莓派用SD卡做系统盘频繁读写会加速SD卡老化。建议把日志和数据库写到外接USB存储上或者用树莓派5的NVMe接口接固态硬盘。7. 特斯拉车机集成与数据展示7.1 通过本地网络推送识别结果树莓派识别到车牌后需要把结果推送到车机或者手机。最简单的方式是起一个Flask服务车机浏览器访问树莓派的IP地址就能看到识别记录。from flask import Flask, jsonify app Flask(__name__) app.route(/plates) def get_plates(): return jsonify(recent_plates)这个方案的优点是简单不需要额外的App。缺点是车机浏览器体验一般而且特斯拉的车机浏览器在行驶中是禁用的只能停车时看。7.2 数据存储与查询优化识别记录建议用SQLite存储轻量且不需要额外服务。表结构设计如下CREATE TABLE plates ( id INTEGER PRIMARY KEY AUTOINCREMENT, plate_number TEXT NOT NULL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, confidence REAL, image_path TEXT );查询优化方面给plate_number和timestamp建索引查询速度能提升十倍以上。如果数据量很大可以按天分表避免单表过大。7.3 与特斯拉USB扩展坞的配合特斯拉的USB接口数量有限如果你同时要接摄像头、树莓派、手机充电就需要一个USB扩展坞。选扩展坞要注意供电能力有些便宜的扩展坞供电不足会导致树莓派反复重启。我建议选带独立供电接口的扩展坞用点烟器给扩展坞供电树莓派从扩展坞取电。这样即使车辆其他USB口在忙树莓派的供电也不受影响。提示特斯拉Model 3和Model Y的USB-C接口支持PD协议但功率有限。如果你用树莓派5建议单独走一路供电不要和其他设备抢电。8. 我踩过的坑和最后分享几个技巧这个项目我从零开始折腾了大概三周踩的坑比预想的多。最大的坑是模型量化后的精度损失。我一开始用INT8量化白天识别率还行晚上直接掉到60%以下。后来改成FP16识别率回到90%以上速度只慢了20%左右。所以如果你的场景对夜间识别有要求不要用INT8用FP16。第二个坑是摄像头排线的可靠性。车内震动大CSI排线用久了会松动导致画面间歇性黑屏。我最后的解决方案是用热熔胶把排线接头固定住虽然丑但很稳。第三个坑是特斯拉的电源管理。我一开始从扶手箱USB取电结果发现锁车后树莓派就断电了停车监控完全没法用。后来从保险盒取常电才解决但接线一定要加保险丝否则短路可能烧毁车辆电路。最后分享一个小技巧用帧差法做预筛选。摄像头采集的相邻两帧如果差异很小说明画面没变化直接跳过检测能省下大量算力。实测下来停车场景下CPU占用能从80%降到30%左右。这个项目后续还可以扩展的方向很多比如加一个4G模块把识别结果推到云端或者用树莓派的GPIO控制一个补光灯夜间自动开启。如果你有多个树莓派还可以组网做多摄像头覆盖实现停车场级别的车牌监控。
返回列表