Skip to main content
NanoStream-OD Logo

⚡ NanoStream-OD

Ultra-Efficient, NMS-Free Patch-Streaming Object Detector for <256KB Microcontrollers & Edge Devices

PyPI Version Tests License: MIT Static SRAM Zero-NMS Target: Cortex-M

NanoStream-OD is an open-source, sub-256KB SRAM streaming object detector designed for bare-metal microcontrollers ($2 ARM Cortex-M4/M7, ESP32-S3, RISC-V). It replaces traditional frame-buffered architectures with a 16-row patch streaming FIFO and eliminates the sorting loop with Zero-NMS O(1) direct peak decoding.

Quickstart • Benchmark • Architecture • C Export • Python API


📊 Cross-Framework Benchmark Results

Tested on the standard multi-class dataset (geometric shapes + human faces) on NVIDIA Tesla T4 and bare-metal ARM Cortex-M simulator:

Model Architecture Input Resolution Parameters Flash Size (Est) Peak SRAM Footprint mAP@50 mAP@50:95 Face AP Target Hardware Tier
NanoStream-OD (MCU) 160×160 15,316 30.0 KB 228.9 KB 42.1% 17.7% 57.4% Cortex-M4/M7 (<256 KB RAM)
NanoStream-OD (Pro) 256×256 60,240 118.0 KB 585.0 KB 42.2% 20.2% 43.5% Cortex-M7 / ESP32-S3
NanoStream-OD (GPU) 320×320 152,800 298.5 KB 914.0 KB 45.7% 24.3% 42.0% Edge TPU / Micro-NPU
FOMO (Edge Impulse) 160×160 27,000 54.0 KB ~250.0 KB 5.6% 2.2% 1.0% Microcontrollers
YOLOv8n (Ultralytics) 160×160 3,006,428 6,200.0 KB > 100 MB 100.0% 96.6% 100.0% Linux SBC / GPU

🔍 Key Benchmark Findings

  1. 7.5× Higher Accuracy than FOMO (42.1% vs 5.6% mAP@50):
    • FOMO only outputs centroid classification masks without bounding box dimensions $(w, h)$, resulting in near-zero IoU overlap on real objects.
    • NanoStream-OD outputs full, calibrated bounding boxes $(x_1, y_1, x_2, y_2)$ using dual-scale CIoU + Smooth-L1 regression.
  2. 196× Parameter Reduction vs YOLOv8n (15.3k vs 3.0M params):
    • YOLO requires full-frame caching and multi-megabyte working memory unavailable on microcontrollers.
    • NanoStream-OD operates in strict 228.9 KB static BSS SRAM with zero dynamic allocation (malloc=0).

💡 Key Innovations

               CAMERA FEED (160x160 Grayscale)
                            │
               ┌────────────▼───────────┐
               │ 16-Row Strip FIFO Ring │  ◄── Strict 228.9 KB SRAM
               └────────────┬───────────┘
                            │
        ┌───────────────────┼───────────────────┐
        ▼                   ▼                   ▼
   ShiftConv Stem       P3 StageBlock       P4 StageBlock
   (16 channels)        (32 channels)       (48 channels)
        │                   │                   │
        │             Lite-FPN Neck             │
        │             (Cross-Fusion)            │
        └───────────────────┬───────────────────┘
                            │
               ┌────────────▼───────────┐
               │ Zero-NMS Dual Head     │  ◄── O(1) Direct Peak Decode
               │ (Obj + Box + Cls)      │      (No Sorting / No NMS loop)
               └────────────────────────┘
  1. Zero-NMS Spatial Dual Assignment: Single $O(1)$ threshold & $3\times3$ max-pool peak test replaces costly sorting loops and IoU pairwise intersection matrices.
  2. Patch-Streaming Ring Buffer: Ingests images in 16-row horizontal scanlines. Discards processed pixel rows immediately to fit inside Cortex-M SRAM.
  3. Power-of-Two Fixed-Point Quantization: Replaces expensive hardware FPUs / multipliers with arithmetic bit-shifts (>> s).

📦 Quickstart

Installation

pip install nanostream-od

Or install with full training and live demo dependencies:

pip install "nanostream-od[demo,train]"

🐍 Python API

Run real-time object detection in just 3 lines of Python:

import nanostream as ns
import cv2

# 1. Load pre-trained streaming detector
model = ns.load_model()

# 2. Run inference on image, video, or numpy array
detections = ns.detect(model, "test.jpg", conf_thr=0.30)

for d in detections:
    print(f"Detected {d.class_name} [{d.score*100:.1f}%] at bbox: {d.box}")

# 3. Draw HUD bounding boxes
frame = cv2.imread("test.jpg")
annotated = ns.draw_detections(frame, detections)
cv2.imwrite("annotated.jpg", annotated)

💻 Unified CLI Tools

# Print model tiers and SRAM budget analysis
nanostream info

# Launch live webcam detection demo with streaming scanline HUD
nanostream demo

# Run benchmark suite (latency & static SRAM breakdown)
nanostream benchmark

# Export trained model to bare-metal C header
nanostream export --out nanostream/mcu/model_weights.h

⚡ Bare-Metal Microcontroller C Deployment

The MCU inference kernel in nanostream/mcu/ requires zero dynamic memory allocation (malloc=0) and compiles with standard C99/C++ on ARM GCC, Clang, or Keil.

#include "nanostream_mcu.h"

int main(void) {
    // 1. Initialize static ring buffers and model weights
    nanostream_mcu_init();

    // 2. Stream 16-row horizontal camera strips as they arrive via DMA
    for (int strip_idx = 0; strip_idx < 10; strip_idx++) {
        const int8_t *strip_pixels = camera_get_strip(strip_idx);
        nanostream_mcu_push_strip(strip_pixels);
    }

    // 3. Decode detections directly in O(1) time
    mcu_detection_t detections[MAX_MCU_DETECTIONS];
    int num_dets = nanostream_mcu_decode(0.30f, detections, MAX_MCU_DETECTIONS);

    for (int i = 0; i < num_dets; i++) {
        printf("Detected Class %d (%d%%) at [%d, %d, %d, %d]\n",
               detections[i].class_id, detections[i].score_percent,
               detections[i].x1, detections[i].y1, detections[i].x2, detections[i].y2);
    }
    return 0;
}

Compile and test on host with GCC:

cd nanostream/mcu
gcc -O3 -Wall -Wextra mcu_test_runner.c nanostream_mcu.c -I . -o mcu_test
./mcu_test

📂 Repository Structure

nanostream/
├── nanostream/
│   ├── __init__.py           # Package API (load_model, detect, draw_detections)
│   ├── cli.py                # Unified CLI interface (nanostream info/demo/export)
│   ├── backbone.py           # Patch-streaming ring-buffered backbone
│   ├── config.py             # NanoStreamConfig & profile definitions (mcu/pro/gpu)
│   ├── head.py               # Zero-NMS dual-assignment detection head
│   ├── layers.py             # ShiftConv2d (multiplier-free power-of-two ops)
│   ├── model.py              # NanoStreamOD PyTorch module & stream_forward()
│   ├── export.py             # Fixed-point calibration & C header exporter
│   ├── tracker.py            # Static SRAM & Flash resource tracker
│   └── mcu/
│       ├── model_weights.h   # Generated C weights header
│       ├── nanostream_mcu.h  # Public C header API
│       ├── nanostream_mcu.c  # Multiplier-free C inference runtime (0 malloc)
│       └── mcu_test_runner.c # Standalone C host validation test
├── benchmarks/               # Cross-framework benchmark suite (NanoStream vs FOMO vs YOLO)
├── tests/                    # Comprehensive PyTest test suite (42/42 passing)
├── assets/                   # Brand logo & architecture diagrams
├── pyproject.toml            # Build metadata & entry points
└── README.md                 # Project documentation

🤝 Contributing & License

Contributions are welcome! Please submit issues or pull requests to improve hardware backends (CMSIS-NN, ESP-NN, RVV).

Licensed under the MIT License.

Metadata

Release files for nanostream-od 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nanostream-od 0.1.0
File Size Uploaded Provenance
nanostream_od-0.1.0.tar.gz 77.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for nanostream-od 0.1.0
File Interpreter ABI Platform
nanostream_od-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 154.0 kB

Release files / nanostream_od-0.1.0.tar.gz

Download URL nanostream_od-0.1.0.tar.gz
Size 77.9 kB
Tags Source
SHA-256 checksum
How to use checksums
835555ae04c7a60ae987cc612a8b311ec773562aba3b28b5aa1159ef028f24a8
BLAKE2b-256 checksum
How to use checksums
4f9093041a3444dabfb5f4e16e08c9cb8784bda8c498d0c8f1d1ae3a8095d91f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / nanostream_od-0.1.0-py3-none-any.whl

Download URL nanostream_od-0.1.0-py3-none-any.whl
Size 76.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b8f05fe3136a8ae5a78e40a324173a9da5cfdfe3b30a3ef686d8357523e1cfd9
BLAKE2b-256 checksum
How to use checksums
2c0637b03bd42e0587bb3ec3d6f44673abfa1839eac7565ec5cc550921a4be3a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Security for nanostream-od 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page