Dự án nhận diện phương tiện, phân loại hãng xe và OCR biển số bằng C++ với ONNX Runtime + OpenCV.
Hỗ trợ input: --image, --folder, --video.
Luồng xử lý mỗi lần infer (1 ảnh / 1 frame infer):
- Vehicle detection (YOLO) trên ảnh gốc.
- Crop vehicle ROI từ bbox vehicle.
- Chạy song song 2 nhánh:
- Brand branch: batch classify hãng xe cho
car. - Plate branch:
- plate detect theo từng vehicle (multi-thread).
- map bbox plate về ảnh gốc.
- crop + preprocess plate (multi-thread).
- OCR (batch; nếu model OCR fix
batch=1thì fallback multi-thread theo từng ảnh).
- Brand branch: batch classify hãng xe cho
- Merge kết quả vehicle + plate + OCR text/conf.
- Draw overlay và xuất ảnh/video.
flowchart TD
A[Input image/folder/video] --> B[Vehicle Detection YOLO]
B --> C[Crop vehicle ROIs]
C --> D[Brand branch - batch]
C --> E[Plate branch - MT detect/map/preprocess + OCR]
D --> F[Merge]
E --> F
F --> G[Draw overlay + Save/Show]
ONNX Runtime được vendor sẵn trong third_party/onnxruntime.
Trong mode video, hệ thống dùng tracking-by-detection để gán track_id ổn định cho vehicle theo thời gian.
Hiện tại tracker được implement theo hướng ByteTrack-like:
- Predict bbox mỗi frame (để chạy tốt khi chỉ infer mỗi N frame).
- Data association 2-stage (high-score rồi low-score) + assignment toàn cục (giảm
id switch).
Ngoài track_id, hệ thống duy trì map nghiệp vụ: track_id -> {brand, plate} và chỉ “chốt” khi đủ ngưỡng:
- brand:
brand_conf > kTrackBrandAcceptConf - plate:
plate_det_conf > kTrackPlateDetAcceptConfvàocr_conf_avg > kTrackPlateOcrAcceptConf - brand/plate đều có budget số lần thử; quá ngưỡng thì dừng predict nhánh tương ứng (
kTrackBrandMaxAttempts,kTrackPlateMaxOcrAttempts)
Nếu một track đã đủ brand/plate hợp lệ, các frame sau sẽ bỏ qua phần nhận diện tương ứng để giảm compute.
Ở mode video, sau khi chọn vùng làm việc, hệ thống cho phép chọn thêm một đường ranh (2 điểm). Chỉ các track đã đi qua đường này mới bắt đầu chạy predict brand và OCR plate.
- Linux (khuyến nghị Ubuntu 22.04)
- CMake + compiler hỗ trợ C++23
- OpenCV dev
setup.sh cài sẵn:
build-essentialcmakepkg-configlibopencv-dev
./setup.sh
./build.sh
cd build
../run.sh --image ../img/1.jpegNếu script chưa executable:
chmod +x setup.sh build.sh run.shMặc định build 2 target: main và benchmark.
./build.shTùy chọn:
--build-type <type>(mặc địnhRelease)--jobs <n>--clean--target <name>(lặp được)
Ví dụ:
./build.sh --build-type Debug --jobs 8
./build.sh --clean --target benchmarkOutput:
out/build/bin/mainout/build/bin/benchmark
Ghi chú: nếu bạn từng build trên môi trường khác (ví dụ cache compiler trỏ tới *.exe), hãy chạy ./build.sh --clean để tạo cache mới.
Main:
../run.sh --image ../img/1.jpeg
../run.sh --folder ../img
../run.sh --video ../video.mp4 --show --nosaveBenchmark:
../run.sh --benchmark --image ../img/1.png --warmup 5 --runs 20Video note:
- infer theo chu kỳ
app_config::kVideoInferEveryNFrames(mặc định 5), các frame giữa chu kỳ tái dùng overlay gần nhất.
Thiết lập trong include/ocrplate/core/app_config.h:
- Model paths:
kVehicleModelPath,kPlateModelPath,kBrandCarModelPath,kOcrModelPath - Thresholds:
kVehicleConfThresh,kPlateConfThresh,kNmsIouThresh,kOcrConfAvgThresh - Video/tracking:
kVideoInferEveryNFrames, các biếnkTracker*, các biếnkTrack*AcceptConf - Budget retry:
kTrackBrandMaxAttempts,kTrackPlateMaxOcrAttempts
docker build -t ocr-plate .
docker run --rm -v "$PWD/img:/app/img" ocr-plate --image /app/img/1.jpeg
docker run --rm -v "$PWD/img:/app/img" --entrypoint /app/benchmark ocr-plate --image /app/img/1.jpeg --warmup 3 --runs 10Public headers nằm dưới include/ocrplate/* (module hoá theo folder), source nằm dưới src/*:
src/app/*: entrypoints + CLI parsingsrc/pipeline/*: pipeline infer/drawsrc/services/*: model runners (YOLO/OCR/Brand/ONNX)src/utils/*: util chung (parallel, decode, report, preprocess)src/tracking/*: tracking + identity store
Các module được build thành library targets trong CMakeLists.txt:
ocrplate_utils,ocrplate_tracking,ocrplate_services,ocrplate_pipeline