mica-ai-plate

HyperLPR3(standard_v20230229)中国车牌识别的 Java 复刻:纯 ONNX Runtime + openpnp/opencv,零 Python,Apache-2.0 可商用。

1. 模型规格

文件来源License大小说明
y5fu_320x_sim.onnxHyperLPR3 v20230229Apache 2.0≈6.8 MB车牌检测(YOLOv5 多任务,320 输入)
y5fu_640x_sim.onnx同上Apache 2.0≈7.4 MB车牌检测(640 输入,大图可选)
rpv3_mdict_160_r3.onnx同上Apache 2.0≈4.6 MBCRNN + SVTR 车牌字符识别(77 token CTC)
litemodel_cls_96x_r1.onnx同上Apache 2.0≈0.9 MB车牌颜色分类(3 类:黄 / 蓝 / 绿)

模型已直接入库:model-tools/plate/models/(无需下载脚本)。

模型 I/O

检测(y5fu)

输入节点input,shape [1, 3, 320, 320](640 模型为 [1, 3, 640, 640]),dtype float32
输出节点output,shape [1, 6300, 15](640 模型为 [1, 25200, 15]),dtype float32
输出含义每行 15 维:[cx, cy, w, h, obj_conf, 4 关键点 (8 维), 2 层分类 score];layer 0 = 单层车牌,layer 1 = 双层车牌

识别(rpv3)

输入节点data,shape [1, 3, 48, 160],dtype float32,归一化 (x - 127.5) / 127.5不做 BGR→RGB 转换
输出节点output,shape [1, 20, 78],dtype float32(logits,未 softmax)
输出含义20 个时间步 × 78 类(77 字符 + 1 冗余位);CTC 解码:argmax → 去重 → 去 blank(0)

颜色分类(litemodel)

输入节点data,shape [1, 3, 96, 96],dtype float32
输出节点output,shape [1, 3],dtype float32;index 0 = 黄 / 1 = 蓝 / 2 = 绿

2. 核心组件

组件职责
主引擎PlatePipeline实现 AutoCloseable,对外提供 recognizePath / recognizeBytes / recognize(Mat)
配置PlateConfigBuilder 模式,含三模型路径、输入尺寸、阈值、maxPlatesonnx
检测PlateDetectorletterBox 预处理 + 推理 + xywh2xyxy + conf*class + NMS + 坐标反算
对齐PlateAligner4 点透视校正(对齐 Python get_rotate_crop_image),高宽比 ≥ 1.5 时旋转 90°(双层牌)
识别PlateRecognizer变宽 resize + 右侧 padding 到 160 + 推理 + CTC 解码
字典PlateDictionary77 token(对齐 hyperlpr3/common/tokenize.py),blank index = 0
分类PlateClassifier仅在车牌号无法判定类型时调用(黄 / 蓝 / 绿三选一)
结果PlateResult车牌号 / 类型 / 检测与识别置信度 / 框 / 4 关键点
类型PlateType10 类枚举,对齐 Python typedef.py(索引一致)

处理流程

Path / Bytes / Mat


[PlatePipeline.recognize]
   ├─ [PlateDetector.detect]      letterBox(320/640) → ONNX → 15 维后处理 + NMS
   │                               → bbox + 4 关键点 + layerNum(单/双层)
   ├─ [PlateAligner.rotateCrop]   4 点透视校正;h/w ≥ 1.5 → 旋转 90°(双层)
   ├─ 双层牌(layerNum == 1)      按 h * 0.4 切上下两行,各识别一次后拼接
   │  单层牌                       整图识别一次
   ├─ [PlateRecognizer]           CTC 解码 → plateCode + confidence
   ├─ [PlatePipeline.codeFilter]  车牌号规则判型(WJ / 8 位 / 学 / 港澳 / 警 / 粤Z)
   │   └─ UNKNOWN 时 → [PlateClassifier] 颜色分类兜底(黄/蓝/绿,双层 → YELLOW_DOUBLE)

List<PlateResult>

3. 车牌类型(PlateType)

对齐 HyperLPR3 common/typedef.py,枚举 ordinal() 与 Python 常量值一致:

枚举Python 常量说明
UNKNOWNUNKNOWN-1*未知(交给颜色分类器兜底)
BLUEBLUE0蓝牌
YELLOW_SINGLEYELLOW_SINGLE1黄牌单层
WHITE_POLICEWHILE_SINGLE2白牌(警牌 / WJ)
GREENGREEN3绿牌新能源
HONG_KONG_MACAOBLACK_HK_MACAO4黑牌港澳
HK_SINGLEHK_SINGLE5香港单层
HK_DOUBLEHK_DOUBLE6香港双层
MACAO_SINGLEMACAO_SINGLE7澳门单层
MACAO_DOUBLEMACAO_DOUBLE8澳门双层
YELLOW_DOUBLEYELLOW_DOUBLE9黄牌双层

* UNKNOWN 在 Python 中为 -1,Java 枚举 ordinal 从 0 起,语义对齐、数值不强制一致;判型规则见 PlatePipeline.codeFilter(对齐 typedef.py::code_filter)。HK_* / MACAO_* 为完整语义保留位,当前 code_filter 规则不会产出,归属 HONG_KONG_MACAO

判型规则(codeFilter,对齐 Python code_filter

按顺序命中即返回:

  1. WJ 开头 → WHITE_POLICE
  2. 长度 = 8 → GREEN
  3. BLUE
  4. / HONG_KONG_MACAO
  5. WHITE_POLICE
  6. 粤Z 开头 → HONG_KONG_MACAO
  7. 其余 → UNKNOWN → 颜色分类器兜底(黄/蓝/绿,双层牌 → YELLOW_DOUBLE

4. 快速开始

纯 Java(零 Spring)

java
PlateConfig config = PlateConfig.builder()
    .detectionModelPath("models/y5fu_320x_sim.onnx")
    .recognitionModelPath("models/rpv3_mdict_160_r3.onnx")
    .classificationModelPath("models/litemodel_cls_96x_r1.onnx")
    .build();
try (PlatePipeline pipeline = PlatePipeline.create(config)) {
    List<PlateResult> results = pipeline.recognizePath("car.jpg");
    for (PlateResult r : results) {
        // r.getPlateCode()  == "津B6H920"
        // r.getPlateType()  == PlateType.BLUE
        // r.getRecognitionConfidence() == 0.998
    }
}

Spring Boot Starter

xml
<dependency>
    <groupId>net.dreamlu</groupId>
    <artifactId>mica-ai-plate-spring-boot-starter</artifactId>
</dependency>
yaml
mica:
  ai:
    plate:
      detection-model-path: classpath:models/y5fu_320x_sim.onnx
      recognition-model-path: classpath:models/rpv3_mdict_160_r3.onnx
      classification-model-path: classpath:models/litemodel_cls_96x_r1.onnx
      detection-input-size: 320      # 320 / 640
      detection-confidence-threshold: 0.25
      detection-nms-threshold: 0.5
      max-plates: 5
      onnx:
        device: cpu                  # cpu / gpu(⚠️ device 在 onnx 下,不是顶层)
java
@RestController
@RequiredArgsConstructor
public class DemoController {
    private final PlatePipeline pipeline;

    @PostMapping("/plate")
    public List<PlateResult> recognize(@RequestParam MultipartFile file) throws IOException {
        return pipeline.recognizeBytes(file.getBytes());
    }
}

配置项(mica.ai.plate 前缀,见 PlateProperties

配置默认值说明
enabledtrue是否启用自动装配
model-version20230229版本标识(日志用)
detection-model-path / recognition-model-path / classification-model-path三模型路径,必填,支持 classpath:
detection-input-size320检测输入边长(仅 320 / 640)
detection-confidence-threshold0.25检测置信度阈值
detection-nms-threshold0.5NMS IoU 阈值
max-plates5单图最多返回车牌数
onnx.devicecpucpu / gpu(GPU 需 classpath 换 onnxruntime_gpu
onnx.intra-op-num-threads00 = ORT 默认
onnx.inter-op-num-threads00 = ORT 默认

输出字段(PlateResult

字段类型含义
plateCodeString车牌号(双层牌为上下两行拼接)
plateTypePlateType10 类枚举,见上表;JSON 序列化用 getCode()(小写下划线)
detectionConfidencefloat检测框得分(obj_conf × class score)
recognitionConfidencefloatCTC 解码字符概率均值(双层牌为两行平均)
boundingBoxint[4]原图坐标 [x1, y1, x2, y2]
landmarksint[4][2]4 角点,左上 / 右上 / 右下 / 左下

5. License

  • 代码:Apache License 2.0
  • 模型:HyperLPR3 v20230229,Apache License 2.0可商用