# cv_cli **Repository Path**: fuzzy-thirty-nine/cv_cli ## Basic Information - **Project Name**: cv_cli - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-21 - **Last Updated**: 2026-06-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Cv_Cli — 纯 Rust 车牌识别 CLI [![Rust](https://img.shields.io/badge/Rust-2021-000000?logo=rust)](https://www.rust-lang.org) [![ONNX Runtime](https://img.shields.io/badge/ONNX%20Runtime-2.0.0--rc.12-005571?logo=onnx)](https://github.com/pykeio/ort) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) **Cv_Cli** 是一个纯 Rust 实现的车牌识别命令行工具,利用 ONNX Runtime 加载 YOLOv8-pose 检测模型和 LPRNet 识别模型,实现端到端的车牌检测与字符识别,**无需 Python 运行时依赖**。 ## 效果预览 ``` $ cv_cli --image demo.jpg 🚀 检测模型: models\pose\stage2n\weights\best.onnx 🔤 识别模型: models\rec\stage4_full\model.onnx 🖥️ 推理设备: CUDA GPU(可用 --cpu 强制 CPU) ⏳ 加载 ONNX Runtime 和模型... 完成 [CUDA (GPU)] 📄 demo.jpg ┌──────────────────────────────────────────────────────────┐ │ 车牌识别结果 (纯 Rust) │ └──────────────────────────────────────────────────────────┘ 📄 demo.jpg 🚗 车牌 号码: 京A12345 检测: 98.7% 识别: 99.2% 耗时: 45.3ms ``` ## 目录 - [功能特性](#功能特性) - [环境要求](#环境要求) - [快速开始](#快速开始) - [1. 编译](#1-编译) - [2. 准备模型](#2-准备模型) - [3. 运行](#3-运行) - [使用指南](#使用指南) - [参数说明](#参数说明) - [使用示例](#使用示例) - [输出格式](#输出格式) - [项目结构](#项目结构) - [技术架构](#技术架构) - [推理管线](#推理管线) - [关键技术细节](#关键技术细节) - [对比 Python 版本](#对比-python-版本) - [常见问题](#常见问题) - [图形界面(Tauri GUI)](#图形界面tauri-gui) ## 功能特性 - **纯 Rust 推理** — 基于 ONNX Runtime(`ort` crate),不依赖 Python 或 PyTorch - **YOLOv8-pose + 透视校正** — 利用关键点(4 顶点)做透视变换,矫正倾斜车牌 - **LPRNet + CTC 解码** — 轻量级车牌字符识别网络 - **CUDA GPU 加速** — 自动检测 CUDA,失败回退 CPU - **三种输入方式** — 单张图片 (`--image`)、目录批量 (`--dir`)、URL 下载 (`--url`) - **三种输出格式** — `table`(卡片表格)、`json`(结构化 JSON)、`simple`(简洁纯文本) - **彩色终端输出** — 使用 `colored` crate 实现差异化高亮 - **CUDA/CPU 自动切换** — 支持 `--cpu` 强制 CPU 推理 - **调试模式** — `--debug` 导出中间结果,便于与 Python 对照验证 - **Tauri 桌面 GUI** — Vue 3 + TypeScript 图形界面,可视化整条推理流水线 ## 环境要求 - **Rust** 1.75+(推荐使用 [rustup](https://rustup.rs/) 安装) - **ONNX Runtime** — 由 `ort` crate 自动管理,无需手动安装 - **CUDA(可选)** — CUDA 12.x + cuDNN,开启 GPU 加速 ### 验证 CUDA 支持 `ort` 使用 `ort::ep::CUDA` 提供 CUDA EP。启动时若 CUDA 不可用会自动回退 CPU: ```text ⚠️ CUDA EP 不可用 (CUDA error: ...),回退 CPU ``` ## 快速开始 ### 1. 编译 ```bash git clone Cv_Cli cd Cv_Cli cargo build --release ``` 编译产物位于 `target/release/cv_cli.exe`(Windows)或 `target/release/cv_cli`(Linux/macOS)。 ### 2. 模型文件 ONNX 模型已随项目打包在 `models/` 目录中,无需额外下载: ``` models/ ├── pose/stage2n/weights/best.onnx # YOLOv8-pose 关键点检测 (~11.8 MB) └── rec/stage4_full/model.onnx # LPRNet 字符识别 (~1.5 MB) ``` 可通过 `--detect-model` / `--rec-model` 指定其他模型路径。 > **自定义模型**:若需使用自己训练的 PyTorch `.pt` 权重,先用 `ultralytics` 导出: > ```python > from ultralytics import YOLO > model = YOLO("best.pt") > model.export(format="onnx", opset=19) > ``` > LPRNet 需使用 torch.onnx.export 手动导出。 ### 3. 运行(CLI) ```bash # 单张图片 cv_cli --image test.jpg # 目录批量 cv_cli --dir ./test_images/ # URL 图片 cv_cli --url https://example.com/car.jpg # 强制 CPU cv_cli --image test.jpg --cpu ``` ### 4. 图形界面(Tauri GUI) 项目附带一个基于 **Tauri 2 + Vue 3 + TypeScript** 的桌面图形界面,可视化展示整条推理流水线的每个步骤: ``` 📷 输入图片 → 🔍 YOLO 检测 → 🔄 透视校正 → 📝 LPRNet 识别 → ✅ 识别结果 ``` **启动开发模式:** 需要先安装 GUI 依赖,然后在**两个终端**中分别运行前端开发服务器和 Tauri 桌面窗口: ```bash # 终端 1:安装依赖并启动 Vite 开发服务器 cd gui npm install npm run dev # 启动前端热更新 → http://localhost:1420 # 终端 2:编译并启动 Tauri 桌面窗口 cd gui npx tauri dev # 编译 Rust 后端 + 打开桌面窗口 ``` **构建发行版:** ```bash cd gui npx tauri build # 生成安装包 → gui/src-tauri/target/release/bundle/ ``` > **注意**:GUI 自动复用 `models/` 目录下的 ONNX 模型文件,无需额外配置。 > Windows 10+ 已内置 WebView2 运行时,无需额外安装。 ## 使用指南 ### 参数说明 | 参数 | 缩写 | 说明 | 默认值 | |------|------|------|--------| | `--image ` | `-i` | 单张图片路径 | — | | `--dir ` | `-d` | 图片目录路径 | — | | `--url ` | `-u` | 图片 URL | — | | `--detect-model ` | `-m` | YOLOv8-pose ONNX 模型路径 | 自动检测 | | `--rec-model ` | `-c` | LPRNet ONNX 模型路径 | 自动检测 | | `--format ` | `-f` | 输出格式:`table` / `json` / `simple` | `table` | | `--cpu` | — | 强制使用 CPU 推理 | CUDA(自动) | | `--debug` | — | 导出中间结果供对照调试 | 关闭 | ### 使用示例 **基本识别:** ```bash cv_cli --image photos/car.jpg ``` **批量处理并输出 JSON:** ```bash cv_cli --dir ./parking_lot/ --format json > results.json ``` **处理网络图片并简洁输出:** ```bash cv_cli --url https://www.example.com/car.png --format simple ``` **指定模型路径 + CPU 推理:** ```bash cv_cli --image test.jpg --detect-model my_models/det.onnx --rec-model my_models/rec.onnx --cpu ``` **调试模式(导出预处理中间结果):** ```bash cv_cli --image test.jpg --debug ``` ### 输出格式 #### table(默认) ``` 📄 car.jpg 🚗 车牌 号码: 京ABC123 检测: 96.5% 识别: 98.1% 耗时: 42.1ms 📊 共 12 张图片 总耗时 4.2s 平均 350.0ms/张 ``` #### json ```json { "images": [ { "file": "car.jpg", "plates": [ { "plate_no": "京ABC123", "rect": [120, 340, 380, 420], "detect_conf": 0.965, "rec_prob": 0.981 } ], "time_ms": 42.1 } ] } ``` #### simple ``` ✓ car.jpg 京ABC123 — night.jpg 未检测到车牌 ✗ blurry.jpg 无法打开图片 📊 3 张图片 | 共 0.1s | 平均 33.3ms/张 ``` ## 项目结构 ``` Cv_Cli/ ├── Cargo.toml # Rust 项目配置与依赖(lib + bin) ├── Cargo.lock # 依赖锁定文件 ├── README.md # 本文件 ├── models/ # ONNX 模型文件(随项目打包) │ ├── pose/stage2n/weights/best.onnx # YOLOv8-pose 关键点检测 │ └── rec/stage4_full/model.onnx # LPRNet 字符识别 ├── scripts/ │ └── predict.py # [备选] Python 推理脚本 ├── src/ │ ├── lib.rs # 库入口:导出 pipeline + display │ ├── main.rs # CLI 入口:clap 参数解析、输入分发、主流程 │ ├── pipeline.rs # 纯 Rust 推理管线:ONNX 加载、预处理、推理、后处理 │ └── display.rs # 输出格式化:table / json / simple 三种模式 └── gui/ # Tauri 桌面图形界面 ├── package.json # 前端依赖(Vue 3 + TypeScript + Vite) ├── vite.config.ts # Vite 配置(端口 1420) ├── index.html # 前端 HTML 入口 ├── src/ # Vue 3 前端源码 │ ├── main.ts # Vue 入口 │ ├── App.vue # 主布局:流水线步骤指示器 + 左右分栏 │ ├── types.ts # TypeScript 类型定义 │ ├── style.css # 全局暗色主题样式 │ └── components/ │ ├── PipelineSteps.vue # 水平流水线步骤指示器 │ ├── ImageInput.vue # 图片路径输入 + CPU/GPU 开关 │ ├── ImageViewer.vue # 原始图片 + 检测框叠加显示 │ ├── RoiViewer.vue # 透视校正 ROI 展示 │ └── ResultCard.vue # 识别结果卡片 └── src-tauri/ # Tauri Rust 后端 ├── Cargo.toml # 依赖 cv_cli 库 ├── tauri.conf.json └── src/ ├── main.rs # Tauri 入口 └── lib.rs # 3 个 Tauri 命令 + 图像绘制/编码工具 ``` ## 技术架构 ### 推理管线 ``` ┌──────────────────────┐ │ 输入图片 (image) │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ Letterbox 缩放 │ │ 640×640 + 灰边填充 │ │ NCHW 归一化 │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ YOLOv8-pose ONNX │ │ 输出 [1, 13, 8400] │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ 后处理 + NMS │ │ 置信度阈值 0.25 │ │ IoU 阈值 0.45 │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ 关键点重排序 │ │ CCPD → LT/RT/RB/LB │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ 透视变换 (warp) │ │ 自实现 8×8 线性求解 │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ LPRNet ONNX │ │ 94×24 输入 │ │ 输出 [T, C] logits │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ CTC 解码 │ │ Best-path decoding │ │ 去重去 blank │ └────────┬─────────────┘ │ ┌────────▼─────────────┐ │ 车牌号码 + 置信度 │ └──────────────────────┘ ``` ### 关键技术细节 | 模块 | 文件 | 功能 | |------|------|------| | **预处理** | `pipeline.rs:113-153` | Letterbox 缩放至 640×640,BGR 归一化,NCHW 排版 | | **检测** | `pipeline.rs:155-216` | YOLOv8-pose 后处理:坐标解码 + 关键点提取 | | **NMS** | `pipeline.rs:99-109` | 非极大值抑制,按置信度降序筛选 | | **顶点重排序** | `pipeline.rs:219-244` | CCPD 格式 (RB,LB,LT,RT) → (LT,RT,RB,LB) | | **透视校正** | `pipeline.rs:247-372` | 自实现 `getPerspectiveTransform`(Gauss-Jordan 消元)+ 双线性插值 `warpPerspective` | | **LPRNet** | `pipeline.rs:375-391` | 缩放至 94×24,BGR 归一化至 [-1, 1] | | **CTC 解码** | `pipeline.rs:395-419` | Best-path decoding,支持 68 字符集(31 省 + 24 字母 + 10 数字) | **字符集**(`pipeline.rs:74`): ``` 皖沪津渝冀晋蒙辽吉黑苏浙京闽赣鲁豫鄂湘粤桂琼川贵云藏陕甘青宁新 ABCDEFGHJKLMNPQRSTUVWXYZ0123456789 ``` ### 依赖说明 | 依赖 | 用途 | |------|------| | [`clap`](https://crates.io/crates/clap) | CLI 参数解析(derive 模式) | | [`ort`](https://crates.io/crates/ort) | ONNX Runtime Rust 绑定,CPU + CUDA EP | | [`ndarray`](https://crates.io/crates/ndarray) | N 维数组,ONNX 输入输出编排 | | [`image`](https://crates.io/crates/image) | 图片解码、缩放、像素操作 | | [`reqwest`](https://crates.io/crates/reqwest) | HTTP 下载(blocking 模式) | | [`serde` / `serde_json`](https://crates.io/crates/serde) | JSON 序列化 | | [`colored`](https://crates.io/crates/colored) | 终端彩色输出 | | [`anyhow`](https://crates.io/crates/anyhow) | 错误处理与上下文 | ## 对比 Python 版本 项目同时包含一个基于 Python 的推理后端(`scripts/predict.py` + `src/detect.rs`),以下是两者对比: | 维度 | 纯 Rust 版本 (pipeline.rs) | Python 版本 (detect.rs) | |------|--------------------------|----------------------| | **运行时** | 无额外依赖 | 需 Python + torch + ultralytics | | **模型格式** | ONNX | PyTorch `.pt` | | **启动速度** | ~1-2 秒加载模型 | ~5-10 秒导入 torch | | **性能** | 同等(均使用 CUDA) | 同等 | | **部署** | 单二进制文件 | Python 环境配置复杂 | | **GPU 支持** | CUDA EP 自动/回退 CPU | CUDA 自动/回退 CPU | | **批量处理** | 支持 | 支持 | | **透视校正** | 自实现(纯 Rust) | OpenCV `getPerspectiveTransform` | > **推荐使用纯 Rust 版本**(默认入口 `main.rs` + `pipeline.rs`),仅当需要自定义 PyTorch 模型结构时使用 Python 版本。 ## 常见问题 ### Q: 找不到 ONNX Runtime(`ort` 报错) `ort` crate 在编译时会自动下载对应平台的 ONNX Runtime shared library。若下载失败,尝试: ```bash # 设置代理(如需要) $env:HTTP_PROXY = "http://proxy:port" $env:HTTPS_PROXY = "http://proxy:port" cargo clean && cargo build --release ``` ### Q: CUDA 不可用 / GPU 推理失败 ```bash # 使用 CPU 推理 cv_cli --image test.jpg --cpu ``` 确认已安装 CUDA 12.x 及 cuDNN,且 ONNX Runtime 的 CUDA EP 版本匹配。 ### Q: 检测不到车牌 - 确认图片清晰,车牌未严重遮挡 - 尝试调整摄像头角度,避免车牌过度倾斜(透视校正可矫正一定角度,但非无限) - 检查模型文件是否正确(YOLOv8-pose 需输出 4 个关键点) ### Q: `--debug` 模式的使用 调试模式会导出透视校正后的 ROI 图像到 `debug_out/` 目录: ``` debug_out/ └── roi_rust.png # 校正后的车牌区域 ``` 同时输出 JSON 格式的中间数据,便于与 Python 版本的 `tools/debug_compare.py` 逐项对照。 ### Q: 如何编译 release 版本? ```bash cargo build --release strip target/release/cv_cli.exe # Windows # 或 strip target/release/cv_cli # Linux/macOS ``` ## 图形界面(Tauri GUI) 项目提供基于 **Tauri 2** 的桌面图形界面,将 CLI 的推理管线可视化呈现。 ### 界面预览 ``` ┌─────────────────────────────────────────────────────────────┐ │ 🚗 车牌识别流水线 [✓ 模型就绪] [CUDA (GPU)] │ ├─────────────────────────────────────────────────────────────┤ │ 📷 输入 ──→ 🔍 检测 ──→ 🔄 校正 ──→ 📝 识别 ──→ ✅ 结果 │ │ [✓] [✓] [✓] [✓] [✓] │ ├──────────────────────────┬──────────────────────────────────┤ │ [图片路径输入] │ [透视校正 ROI] │ │ [开始识别] │ │ │ │ ┌──────────────────────────┐ │ │ ┌──────────────────┐ │ │ 京A12345 │ │ │ │ 原始图片 + 检测框 │ │ │ 检测: ████████░░ 85.3% │ │ │ │ (bbox + 关键点) │ │ │ 识别: ██████████ 98.1% │ │ │ └──────────────────┘ │ │ 耗时: 45.3ms │ │ │ │ └──────────────────────────┘ │ └──────────────────────────┴──────────────────────────────────┘ ``` ### 功能 | 功能 | 说明 | |------|------| | **图片输入** | 支持输入本地图片路径,可切换 CPU/GPU 模式 | | **流水线可视化** | 水平步骤指示器,实时显示各阶段处理状态 | | **检测框叠加** | 原始图片上绘制绿色 bbox + 红色关键点 + 蓝色顶点连线 | | **透视校正 ROI** | 展示经过校正后的 94×24 车牌区域 | | **识别结果卡片** | 大号车牌字体 + 检测/识别置信度进度条 + 耗时统计 | | **错误提示** | 路径错误、模型缺失、无检测结果等情况均有友好提示 | ### 技术栈 | 层 | 技术 | |----|------| | 桌面框架 | **Tauri 2** | | 前端 | **Vue 3** + **TypeScript** + **Vite 6** | | 后端 | **Rust**(通过 `tauri::command` 调用 `cv_cli` 库) | | 图片编码 | Rust `image` crate:JPEG/PNG → Base64 传前端 | | 检测绘制 | `draw_rect_thick` + `draw_circle_filled` + Bresenham 画线(纯像素操作) | ### 管道命令 ```typescript // 前端调用示例 import { invoke } from "@tauri-apps/api/core"; const result = await invoke("process_image", { path: "D:\\car.jpg", useCpu: false, }); // result: { image_base64, detection, roi_base64, plate_number, ... } ``` --- **Cv_Cli** — 计算机视觉课程实践项目。基于 YOLOv8-pose + LPRNet 的车牌识别系统,使用 Rust 和 ONNX Runtime 实现端到端推理管线,并提供 Tauri 桌面 GUI 可视化流水线各步骤。