MicroROS-Pi5 + Coral Edge TPU — model binaries
Edge TPU (
.tflite) binaries used by the
MicroROS-Pi5_Coral_TPU
project — a Raspberry Pi 5 + Coral USB Accelerator + micro-ROS robot car that does
person following with Re-ID identity lock (Nav2 path planning + active gimbal framing)
and
two-tape lane following driven by an Edge TPU segmentation net.
Two groups of binaries live here rather than in the git repo:
- Re-ID pairs (
reid*/, ~85 MB) — co-compiled Edge TPU artifacts with no official
upstream download. Documented below.
- Baseline models (
objcls/, signcls/, line_seg/, line_geom/, line_imit/,
~10 MB) — retrainable artifacts of the project's own PyTorch → int8 PTQ →
edgetpu_compiler pipeline (training/ in the repo). See
Baseline models.
Why "co-compiled" matters (read this before mixing files)
Each subdirectory is one edgetpu_compiler co-compilation of two networks that share
the same 8 MB of on-chip SRAM: a person detector (det_reid_edgetpu.tflite) and an
appearance embedder (emb_reid_edgetpu.tflite). The compiler decides how to split
cache between them.
⚠️ A det/emb pair from different directories will not work correctly together.
Always take both files from the same directory. Mixing them means the two models fight
over the SRAM cache and per-inference latency figures below no longer hold.
The detector is the same source in every pair (Coral's stock
ssd_mobilenet_v2_coco_quant_postprocess, filtered to the person class); only the
embedder differs.
Variants
Latency = median single embed() invoke, measured on real hardware (Pi 5 + Coral USB).
"Swap rate" = fraction of frames where some bystander scored ≥ the target — i.e. how often
identity would be confused — measured on 952 frames recorded from the actual robot
(low, ground-level, upward-looking camera), not on a public benchmark.
| Directory | Embedder | embed() | Swap rate | Notes |
|---|
reid_youtu/ | Youtu ReID (ResNet50) | 60 ms (~4.4 Hz) | 4 % | Most accurate. Default. Multi-source training (Market-1501 + DukeMTMC + MSMT17 + CUHK03). |
reid_youtu_p70/ | Youtu ReID pruned 70 % | 15.6 ms (~18 Hz) | 13 % | Best speed/accuracy trade-off; noticeably snappier gimbal tracking. |
reid/ | MobileNetV1 embedding extractor | 3.7 ms | — | Generic ImageNet features, not a trained Re-ID model. Weak; legacy fallback. |
reid_mnv2/ | MobileNetV2 ×1.0 | 3.8 ms | — | Market-1501 only. See warning below. |
reid_osnet05/ | OSNet ×0.5 | 8.6 ms | — | Market-1501 only. See warning below. |
reid_osnet075/ | OSNet ×0.75 | 12.6 ms | — | Market-1501 only. See warning below. |
⚠️ Market-1501-only models fail on a ground-level camera
reid_mnv2, reid_osnet05, reid_osnet075 score well on Market-1501 (OSNet ×0.75 is
rank-1 93.7 %) but were measured unusable on this robot: with the camera sitting on
the floor looking up at people, bystanders scored 0.72–0.89 against a target at 0.99 —
overlapping ranges, so no threshold separates them.
The multi-source Youtu models push bystanders down to 0.12–0.47 on the same footage.
The difference is training-data viewpoint diversity, not model capacity or benchmark score.
Lesson: Market-1501 rank-1 does not predict usability at your deployment viewpoint.
A ground-level upward view is out-of-distribution for surveillance-style Re-ID datasets.
Re-evaluate on footage from your own camera pose.
Keep these three only if your camera is at normal (eye-level or overhead) height.
Input / preprocessing (differs per embedder!)
All embedders take a 1×256×128×3 person crop and output an L2-normalised vector.
Preprocessing is not uniform — branch on input_details[0]['dtype']:
| Embedder | dtype | Preprocessing |
|---|
reid_youtu*, reid | uint8 | Feed raw RGB pixels — normalisation is baked into the graph. |
reid_mnv2, reid_osnet* | int8 | Do ImageNet normalisation (px/255 - mean)/std in Python, then quantise with the input scale/zero-point. |
Crop convention: crops should be tight vertical strips of the torso. Width is taken as
min(box_width, box_height / 2) about the box centre — narrow boxes are used as-is and
never widened. Stretching an arbitrary box to 128×256 (e.g. when arms are spread, or the
person is clipped by the frame edge) distorts the embedding badly — in testing the same
person dropped from 0.99 to 0.80, below a bystander at 0.72.
Usage
From the project repo, one command fetches everything:
1git clone https://github.com/jiaheguo521/MicroROS-Pi5_Coral_TPU.git
2cd MicroROS-Pi5_Coral_TPU
3./deploy/fetch_models.sh # downloads all variants by default
4./deploy/fetch_models.sh reid_youtu_p70 # or just one
5./deploy/fetch_models.sh line_seg # baseline models work the same way
Or grab a single pair directly:
1huggingface-cli download jiaheguo521/microros-pi5-coral-tpu-models \
2 reid_youtu/det_reid_edgetpu.tflite reid_youtu/emb_reid_edgetpu.tflite --local-dir ./models
Thresholds are specific to each embedding space and must be re-calibrated when you switch
variants — see the project README's field-tuning guide.
Baseline models (lane following / classification)
Built by the repo's training/build_*.py pipeline: PyTorch → ONNX → onnx2tf int8 PTQ →
edgetpu_compiler. Every model passes the op-mapping gate — 1 Edge TPU subgraph, 0 CPU
ops — so the whole graph runs on-chip. Each directory ships model_edgetpu.tflite +
meta.json (+ labels.txt for classifiers).
| Directory | Task | Backbone / arch | Size | Notes |
|---|
line_seg/ | Two-tape lane segmentation (64×64 mask) | Tiny MobileNetV2-style encoder + nearest-upsample decoder | 345 KB | Drives follow_lane_tpu; fine-tuned with hand-labeled frames + floor-seam negatives. Field-tested: 16 min continuous lane keeping. |
objcls/ | General object classification (ImageNet, 1000 classes) | EfficientNet-EdgeTPU-S (timm tf_efficientnet_es), PTQ only | 7.0 MB | ~10.9 ms/invoke measured on Coral USB. |
signcls/ | Traffic-sign classification (GTSRB + background class) | EfficientNet-EdgeTPU-S fine-tuned | 2.9 MB | ~2.2 ms/invoke measured. Background class keeps it quiet off-sign. |
line_geom/ | Line-following, geometric regression baseline | Tiny custom CNN | 97 KB | Legacy comparison baseline for follow_line_tpu --mode geom. |
line_imit/ | Line-following, imitation-learning baseline | Tiny custom CNN | 97 KB | Legacy comparison baseline for follow_line_tpu --mode imit. |
Preprocessing contract: int8 input/output. Normalisation is done in Python, never
in-graph (meta.json carries input_size + mean255/std255; the node computes
(rgb - mean)/std, then quantises with the input scale/zero-point). BGR→RGB is an OpenCV
call — an in-graph reverse fails to compile for the Edge TPU. See edgetpu_infer.py in the
repo for the reference loader (it also auto-downloads a missing model dir from here).
Sources & licensing
| Component | Origin | License |
|---|
| Detector (all pairs) | Coral ssd_mobilenet_v2_coco_quant_postprocess | Apache-2.0 |
reid_youtu* embedder | person_reid_youtu_2021nov (Tencent Youtu Lab, via OpenCV Zoo) | Apache-2.0 |
reid/ embedder | Coral mobilenet_v1_1.0_224_quant_embedding_extractor | Apache-2.0 |
reid_mnv2, reid_osnet* embedders | Torchreid Market-1501 pretrained | MIT (weights trained on Market-1501 — research use) |
objcls/ | timm tf_efficientnet_es ImageNet-pretrained, PTQ by this project | Apache-2.0 |
signcls/ | Same backbone fine-tuned on GTSRB by this project | Apache-2.0 (GTSRB terms apply) |
line_seg/, line_geom/, line_imit/ | Trained from scratch by this project on its own recorded/synthetic data | Apache-2.0 |
Quantisation (INT8 PTQ) and Edge TPU co-compilation in this repo were done by the project
author; the pruned Youtu variants use structured pruning + label-free distillation.
Upstream licenses and dataset terms still apply — in particular Market-1501 is intended
for non-commercial research.
Privacy note
Person Re-ID identifies and follows a specific individual. Deploy it only with the informed
consent of the people being tracked, and check the rules that apply where you operate.