Skip to main content

Edge Waste Sorting: Material Classes, the Chinese Four-Way Category and MQTT

Usage notice

The Chinese four-way mapping is a table maintained by this project, not a ruling by any authority, and city rules differ; the output must not be the sole basis for fees, penalties or compliance decisions.

What this solution does​

One trigger (a button, an HTTP call, or motion in the frame) makes the device take one image, classify the item into one of eight material classes, look up the Chinese four-way household-waste category from that class, and publish one MQTT message. An asynchronous callback receives the four-way result at the same time, so a flap, relay or lane indicator can act on it.

  • One head, two levels of answer. The model predicts eight classes: paper, cardboard, glass, metal, plastic, textile, organic, residual. The four-way category (recyclable / kitchen waste / hazardous / other) is a table lookup on the eight-class argmax, so adapting to a local rule means editing the table, not retraining.
  • One trigger, one capture. Button, HTTP or motion detection with an 800 ms debounce; a trigger that arrives while the previous one is still running is merged, not queued. A continuous mode also exists; it is rate-limited and publishes only after three consecutive frames agree on top-1.
  • Payloads are validated before publishing. Every payload passes the event schema, plus two rules JSON Schema cannot express: category must equal top3[0], and confidence must equal top3[0].confidence. Failures are counted and dropped.
  • An optional open-vocabulary track. A SigLIP 2 vision tower scored against constant text prototypes, selected at deploy time with model.track: open_vocab. It adds classes without retraining, answers in Chinese or English from the same image embedding, and yields a "not in my vocabulary" score.
  • Actuator interface with no pin binding. The runtime calls back with a category; which pin it drives is decided by integration code, so one build runs on boards with different headers.

Image bytes never leave the device; the payload carries only a path or an object-store URI.

  • Ready to run on the device

    Install the application package and it runs; a first deploy takes about 35 minutes. Measured on reComputer R2000 series (R2035-12, Hailo-8) over 7417 validation images: material top-1 0.8889, four-way top-1 0.9507 (see performance and measured data).

  • Open source

    Runtime code is Apache-2.0; the training data, TrashNet (MIT) and GC3 (CC BY 4.0), both permit redistribution.

  • Your own camera, systems and actuators

    USB / RTSP camera or a file source; results go out over MQTT, POST /trigger can be called by a kiosk or PLC gateway, and a GPIO callback drives a flap or indicator.

  • Runs entirely on site

    Capture, classification, lookup and the MQTT broker all run on the host; images stay on the device and the main chain needs no internet access.

What it looks like running on a device​

Below is the drop-area framing seen by a reCamera PoE after the waste-sorting application package was installed. Nothing is placed in front of the camera; the image is a framing reference only.

reCamera PoE framing of the drop area, with nothing placed in front of it

Classification results go straight to MQTT. Below are consecutive events captured by subscribing to waste/recamera-cvi/results:

Consecutive classification events on waste/recamera-cvi/results, each carrying the eight-class result, the four-way mapping and inference time

What hardware you need​

Three things at the drop point: a trigger, a camera, a host. With reCamera or reCamera Pro, the camera and the sorting host are the same device.

① Trigger — a button wired to the host, POST /trigger on port 8080, or motion in the frame. All three share one 800 ms debounce, produce the same event, and are told apart by the trigger field in the payload.

② Camera — any USB, RTSP or file source looking down on the drop area; any model will do. A single item must take up a usable share of the frame, with only one item in view. Items that are too small reduce classification quality, and none of the numbers under performance and measured data come from such framing.

③ Sorting host — decides which model paths you can use.

Sorting hostAcceleratorClassifier as deployedOpen-vocabulary trackWhen to choose it
reComputer J3011reComputer J3011 (Jetson Orin Nano 8GB)
Entry AI host
Orin GPUEfficientNet-Lite0 224², TensorRT FP16Not offeredOne drop point, baseline classifier only
reComputer J4012reComputer J4012 (Jetson Orin NX 16GB)
High-performance AI host
Orin GPUEfficientNet-Lite0 224², TensorRT FP16Offered (the only device class that offers it)You expect to add item classes later without retraining
reComputer Industrial R2035-12reComputer Industrial R2035-12 (Hailo-8)
Fanless industrial box
Hailo-8EfficientNet-Lite0 224², INT8 HEFNot offeredA camera is already there and the host goes in a cabinet; the HEF is compiled off-device and downloaded at deploy time, and the Hailo runtime versions must match
reComputer RK3588reComputer RK3588 Series
Cost-effective edge board
RK3588 NPUEfficientNet-Lite0 224², INT8Not offeredA camera is already there, lowest hardware cost, host in the bin housing or a kiosk; the model is converted off-device and no engine is built on the device
reCamera 2002reCamera 2002 (SG2002)
All-in-one smart camera
The camera's own TPUEfficientNet-Lite0 224², BF16Not offeredNo camera at the drop point yet, lowest hardware cost; the classifier runs on the camera, no separate host
reCamera ProreCamera Pro
High-performance smart camera
The camera's own NPU (RV1126B)EfficientNet-Lite0 224², INT8Not offeredNo camera yet and cost is not the first concern; the classifier runs on the camera

Both reComputer models come in a fanless industrial enclosure (reComputer Industrial J3011 / J4012) with the same module and runtime, for a control cabinet or outdoor housing.

The open-vocabulary column comes from the resource notes in the device catalogue: the SigLIP 2 vision tower is a 371 MB ONNX at p50 66.93 ms per image as a CPU onnxruntime offline baseline and needs an accelerator.

④ Everything else — an MQTT consumer (the package runs a local broker on 1883); if the design has a flap or lane indicator, the driver hardware plus integration code for the GPIO callback, which ships bound to no pin. The main chain needs no internet access.

Negative Selection Boundaries​

  • Zero-Shot Open Vocabulary: If you need to add new waste categories dynamically without retraining, do not choose J3011 (track not supported); choose J4012 (16GB).
  • Conveyor Motion Blur: If the conveyor moves faster than 1.5 m/s, rolling shutter cameras produce motion blur; use industrial global-shutter cameras.

How to deploy on site​

Settle the framing and trigger first, then install the software. Rated intermediate, about 35 minutes for a first deploy.

One: install the hardware, framing and trigger​

One item per image, large enough

There is no detector in this chain. Two items in one frame produce one answer, and which item it describes is undefined; items that take up too small a share of the frame classify worse. Mount the camera looking down on the drop area so a single item fills a usable share of the frame, and decide before deployment whether the trigger is a button, HTTP or motion detection.

Two: install the software​

Per-device steps are on the reference design page, where picking a configuration for your site also gives you the matching application package to download.


There are five presets: Camera + reComputer J30 / J40 (Orin), Camera + reComputer R2000 series (R2035-12, Hailo-8), Camera + reComputer RK3588, reCamera (SG2002) and reCamera Pro. The steps below cover the Orin and Hailo-8 presets; the steps for the other three are on the deployment page.

  1. Pick a preset and a host. Camera + reComputer J30 / J40 (Orin) or Camera + reComputer R2000 series (R2035-12, Hailo-8).
  2. Deploy the waste-sorting runtime (required). On Orin the TensorRT engine is built on the device during deployment (68 s on J4012); the engine is tied to the GPU architecture and TensorRT version and cannot be precompiled for distribution. On Hailo the deployment steps check three Hailo ABI gates and then download the HEF.
  3. Watch live classification (optional). The local panel on port 8080 has an MJPEG preview, health counters and the top-3 of recent results. Confirm the framing here before wiring anything.
  4. Wire the trigger and confirm one classification (required). One button press, HTTP call or motion event should produce exactly one MQTT message on waste/<stream-id>/results, with category and confidence matching top3[0].
  5. Switch to the open-vocabulary track (optional, Orin only). Set model.track: open_vocab at deploy time.

What interfaces are available​

The sorting host exposes two interfaces and one in-process callback, all served by the host itself.

  • Operations or record-keeping system — subscribe to waste/<stream-id>/results on port 1883. One JSON per classification.
  • Kiosk UI, PLC gateway or test script — POST /trigger on port 8080 triggers one capture and classification; /events returns recent results with their top-3.
  • Flap, relay or lane indicator — an asynchronous GPIO callback carries the four-way result. It is bound to no pin; the binding code is integration work.

Full interface table​

TypeWhereContentNotes
mqtt1883, waste/<stream-id>/resultstype, version, taxonomy_version, device, stream_id, frame_id, timestamp, trigger, inference_time_ms, pipeline_ms, category (class_id, class_name, china_category, china_category_zh), confidence, top3[], image_ref, model (name, backbone, input, onnx_sha256, accelerator)One per classification. Validated against the event schema before publishing
http8080, /trigger /preview.mjpg /healthz /eventsPOST /trigger fires one capture and classification (trigger recorded as http); live MJPEG; a health endpoint with inference time, trigger and debounce counts and MQTT counts; recent results with top-3Local panel, no auth
GPIO callbackIn processFour-way result, asynchronouslyactuator.enabled defaults to false. Bound to no pin

Two things to watch when reading fields:

  • The image is never in the payload. image_ref.kind is none, local or object_store. Base64 image bytes in a payload violate the contract and are rejected before publishing.
  • category always equals top3[0], and confidence always equals top3[0].confidence. Both are checked before publishing and failing payloads are counted and dropped, so consumers do not need to reconcile them.
{
"type": "waste_classification",
"version": "1.0.0",
"device": "waste-sorting-station-01",
"stream_id": "cam_inlet_01",
"timestamp": 1729000000.789,
"trigger": "sensor",
"inference_time_ms": 3.53,
"pipeline_ms": 4.12,
"category": {
"class_id": 3,
"class_name": "plastic_bottle",
"china_category": "recyclable",
"china_category_zh": "可回收物"
},
"confidence": 0.942,
"top3": [
{"class_id": 3, "class_name": "plastic_bottle", "confidence": 0.942},
{"class_id": 5, "class_name": "glass_bottle", "confidence": 0.038},
{"class_id": 1, "class_name": "metal_can", "confidence": 0.012}
]
}

The bundled MQTT broker allows anonymous connections for local commissioning; use a broker with credentials in a production deployment.

Performance and measured data​


Measured on device: baseline classifier (EfficientNet-Lite0)​

DevicePrecisionValidation imagesMaterial top-1Four-way top-1Difference from CPU fp32 on the same imagesInference p50 / p95
reComputer R2000 series (R2035-12) + Hailo-8INT8 (uint8-input HEF)74170.88890.9507+0.12 pp3.166 ms / 3.249 ms
reComputer RK3588 seriesINT8 (calib256+mmse)74170.88820.9507+0.05 pp3.165 ms / 3.857 ms
reComputer RK3588 seriesfp1674170.88820.9505+0.05 pp5.962 ms / 12.566 ms
reCamera Pro (RV1126B NPU)INT810600.87640.9566+0.19 pp5.824 ms / 6.047 ms
reCamera (SG2002 TPU)BF1610600.87920.9566+0.47 pp24.276 ms / 24.323 ms

Conditions: inference only, excluding capture and preprocessing, single stream back to back; preprocessing is shortest side 256 → centre crop 224, with normalisation baked into the model so the device takes uint8. 7417 images is the full validation set; 1060 images is every seventh image, a subset on which CPU fp32 top-1 is 0.8745 (0.8877 on the full set), so compare top-1 across image sets through the "difference from CPU fp32" column. reCamera Pro was measured with the camera's built-in application stopped; reCamera peaks at 11.6 MB resident memory.

  • Both NPU hosts have the same p50 (3.2 ms); on Hailo-8 p95 is only 0.08 ms above p50, on RK3588 INT8 it is 0.69 ms above.
  • On RK3588, INT8 and fp16 give the same material top-1 and INT8 is 1.9× faster. INT8 uses 252 calibration images, the mmse algorithm and per-channel quantisation; on a 50-image sample, normal agreed with the CPU on 0.90 and mmse on 0.98–1.00. mmse conversion takes 40–90× as long as normal (17.3 minutes vs 11.5 seconds at 256 calibration images), paid once at conversion.
  • The Hailo-8 HEF is compiled with DFC 3.31.0 at optimization_level=2 (quantisation-aware fine-tuning); the earlier optimization_level=1 HEF was 2.40 pp below CPU fp32, and the gap disappears with the current HEF.
  • On reCamera Pro, INT8 is 2.9× faster than fp16 and 4.2× faster than reCamera; INT8, fp16 and CPU fp32 are within 0.2 pp of each other on the same 1060 images.

Reproduce: evaluation/runs/2026-09-07-hailo-quant-tuning, evaluation/runs/2026-09-07-devices/results-rk3588.md, evaluation/runs/2026-09-06-m1c-rk3588-radxa, evaluation/runs/2026-09-07-recamera-pro, evaluation/runs/2026-09-07-devices/results-recamera-sg2002.md

Measured on device: Orin engine build and trigger to answer​

ItemResultDeviceConditions
TensorRT engine build68 s / 72 sreComputer J40 series (J4012) / J30 series (J3011)FP16, built on the device at deploy time
Trigger to answer4.122 msreComputer J40 series (J4012)pipeline_ms in the MQTT event for one POST /trigger, of which inference is 3.533 ms
Inference p50 / p950.992 ms / 1.265 msreComputer J40 series (J4012)The deployed engine, 1060-image validation subset, single stream back to back
Material top-10.8755, 99.91% agreement with the CPUreComputer J40 series (J4012); J30 series (J3011) re-measured bit-identicalSame 1060-image subset, CPU fp32 0.8745

Reproduce: evaluation/runs/2026-09-08-orin-nx-acceptance, evaluation/runs/2026-09-08-orin-nx-acceptance-2, evaluation/runs/2026-09-08-orin-nano-acceptance

Baseline classifier: CPU reference accuracy​

MetricValueConditions
Material top-1 (8 classes)0.8877val, 7417 images; onnxruntime 1.25.1 CPU; ONNX e9f9e847…, 13,477,056 B
Material top-50.9833Same
China four-way top-10.9500Same; lookup on the eight-class argmax
macro-F1 (7 classes with samples)0.8511textile excluded — zero samples
Material top-1, held-out test0.8802test, 7290 images
Per-image inference latency, CPUmean 16.796 ms / p50 14.724 ms / p95 28.718 mssession.run only, CPU offline baseline, batch 1, not a device figure
Images with confidence below 0.5318 (4.3%)val
ORT PTQ INT8 vs fp32 agreement0.965200 val images, per-channel + MinMax, no collapse

Four-way top-1 (0.9500) is higher than material top-1 (0.8877) because confusion among glass, metal and plastic all lands in recyclables; four-way alone overstates how well the model tells materials apart.

Reproduce: evaluation/runs/2026-09-06-m1c-cpu

Open-vocabulary track: SigLIP 2 ViT-B/16​

MetricValueConditions
Material top-1 (8 classes)0.8501val, 7417 images; English prompt set waste8-en/v1, template t02, 16-shot α=0.8, temperature 0.0075
Material top-50.9987Same
China four-way top-10.9393Same; hierarchical path (eight classes, then mapping)
macro-F1 (7 classes)0.7460Same
ECE (15 bins)0.0221Same
Open-set AUROC0.7538Mean over the 7 classes with samples, leave-one-class-out, score = 1 - max softmax
Chinese–English agreement (same image)material 0.8698 / four-way 0.9143One visual embedding, three prototype banks
Material top-1, held-out test0.8620test, 7290 images
Per-image inference latencyp50 66.93 ms / p95 91.62 msCPU offline baseline, batch 1, vision tower only, not a device figure

Against the baseline (same split):

MetricBaseline (MobileNetV3-Small)Open vocabulary (SigLIP2-B/16)
Material top-1, val0.87920.8501
Material top-1, test0.88070.8620
China four-way top-1, val0.95190.9393
macro-F1, val0.82920.7460
ECE (15 bins), val0.03080.0221
Open-set AUROCNone (a closed-set head cannot drop a class without retraining)0.7538
Chinese–English agreementNo text side0.8698 / 0.9143
Zero-shot new classesRetraining requiredEdit the prompt
CPU p50 latency1.57 ms66.93 ms

The baseline in this comparison is the superseded MobileNetV3-Small. The shipped EfficientNet-Lite0 reaches val top-1 0.8877 on this split at a CPU p50 of about 14.7 ms, which shrinks the latency ratio from 40× to 4–5×.

Reproduce: evaluation/runs/2026-09-05-w1-cpu

The SigLIP 2 vision tower measured on Rockchip NPUs (fp16, rknn-toolkit2 / librknnrt 2.3.2; the RK3588 model is a 191 MB .rknn):

DevicePer-image p50 / p95Embedding cosine vs CPU, mean / min
reComputer RK3588 series169.4 ms / 170.5 ms0.999617 / 0.998841
reComputer RK3576 series152.51 ms / 176.59 ms0.99965 / 0.99900

Reproduce: evaluation/runs/2026-09-06-m1c-rk3588-radxa, evaluation/runs/2026-09-06-rk3576-cat

Deployment footprint​

ItemSize
Baseline ONNX (efficientnet_lite0_waste8.onnx)13,477,056 B
SigLIP 2 vision tower ONNX (siglip2_vision_224.onnx)371,695,898 B
Prototype banks + calibration reportabout 155 KB total

Runtimes and key parameters​

DeviceModelPrecisionRuntimeHow the model reaches the device
reComputer J30 / J40 seriesEfficientNet-Lite0 224²FP16TensorRTEngine built on the device at deploy time, tied to GPU architecture and TensorRT version; cannot be precompiled for distribution
reComputer J40 series (optional open-vocabulary track)SigLIP 2 ViT-B/16 vision tower + constant text prototypes——model.track: open_vocab
reComputer R2000 series + Hailo-8EfficientNet-Lite0 224²INT8 (uint8 input, normalisation inside the HEF, optimization_level=2)HailoRT 4.21.0HEF compiled off-device with DFC 3.31.0, downloaded at deploy time
reComputer RK3588 seriesEfficientNet-Lite0 224²INT8 (calib256+mmse)librknnrt 2.3.2Converted off-device with rknn-toolkit2 2.3.2
reCamera ProEfficientNet-Lite0 224²INT8Camera NPU (RV1126B), RKNNConverted off-device with rknn-toolkit2 2.3.2, installed on the camera at deploy time
reCamera (SG2002)EfficientNet-Lite0 224²BF16Camera TPU, cvimodelConverted off-device with TPU-MLIR, installed on the camera at deploy time
  • Trigger debounce: 800 ms; a trigger arriving while the previous one is still running is merged, not queued
  • Continuous mode: publishes only when top-1 is the same for 3 frames in a row; trigger mode gives one answer per shot
  • actuator.enabled: default false; the GPIO callback is not bound to any pin

Known degradation​

  • textile has zero training and evaluation samples: neither source dataset has a fabric class. The eighth logit is kept (ONNX output stays 1×8), but the model has never predicted it, and every table reports n/a for it.
  • No material class maps to hazardous; it stays in the enum for schema stability and the current build never emits it.
  • organic makes up 48.9% of train and 47.1% of val; its recall (0.9791) is far above the other classes (0.70–0.88), and the model pushes uncertain items toward it.
  • residual has only 20 val samples; the open-vocabulary track reaches 0.2754 precision and leave-one-out AUROC 0.5795 on it, close to chance.
  • On the open-vocabulary track, predicting the four-way class directly from Chinese prompts gives only 0.8478; the hierarchical path (eight classes, then mapping) gives 0.9393.
  • The superseded MobileNetV3-Small collapses under INT8 on all three edge chains: Hailo DFC emulator agreement 0.115, reComputer RK3576 series 0.10, reComputer RK3588 series 0.22 (fp16 0.98–1.00); this is why the baseline moved to EfficientNet-Lite0. RK3588 INT8 results do not carry over to RK3576.
  • The SigLIP 2 vision tower fails INT8 quantisation for Hailo-8 (hailo optimize errors at layer ne_activation_mul_and_add78), so there is no HEF; the open-vocabulary track does not run on the reComputer R2000 series.
  • Both datasets are single-item photos (TrashNet on a white board, GC3 off-centre and often occluded), with no wet, crushed, stacked, backlit or partly bagged waste; accuracy at a live drop-off point will be lower than the figures in the tables.

Data and asset sources​

  • TrashNet — github.com/garythung/trashnet, MIT License, Copyright (c) 2017 Gary Thung. Based on two first-party sources: the repository's LICENSE file at commit 6fa2b87, and the license field of the official HuggingFace dataset card. MIT requires the copyright and licence notice to be kept and has no share-alike clause.
  • Garbage Classification 3 — Material Identification (Roboflow Universe) — CC BY 4.0, stated verbatim in the README.dataset.txt shipped with the export. The project path on Roboflow Universe is material-identification/garbage-classification-3.
  • SigLIP 2 — google/siglip2-base-patch16-224, revision 75de2d55…, Apache-2.0. Used by the optional open-vocabulary track only.
  • MobileNetV3-Small ImageNet starting weights (torchvision) — BSD-3-Clause.
  • Upstream runtime code — Apache-2.0.
  • Architecture diagram — drawn from the package's device catalogue and output interfaces; contains no dataset images.

External material derived from these datasets must use the following attribution string verbatim:

TrashNet — Gary Thung and Mindy Yang, https://github.com/garythung/trashnet,
MIT License, Copyright (c) 2017 Gary Thung.
Garbage Classification 3 — Material Identification / Roboflow Universe,
https://universe.roboflow.com/material-identification/garbage-classification-3,
licensed CC BY 4.0.

No dataset-derived image is committed to this package. Both licences permit redistribution.

Loading Comments...