ESP32 examples that use the pure-Rust purecv
computer-vision library under no_std.
Each example is its own crate in this Cargo workspace and shares the esp
toolchain and flashing setup in .cargo/config.toml.
| Crate | What it shows |
|---|---|
matrix-demo |
Builds purecv matrices on the heap, adds them, and logs the contents over serial (ESP32-S3). |
gaussian-blur-demo |
Embeds a grayscale image, runs purecv::imgproc::gaussian_blur under no_std, and streams the blurred result back over serial as base64 (ESP32-S3). |
calib3d-demo |
Camera pose estimation: projects known 3D points through a known pose, then recovers it with purecv::calib3d::solve_pnp (rodrigues + PnP) and logs true vs recovered (ESP32-S3). |
The examples depend on the published purecv
crate from crates.io, built with default features disabled for no_std. It's
declared once in the workspace [workspace.dependencies], and each example opts
in with purecv.workspace = true:
# Cargo.toml (workspace root)
[workspace.dependencies]
purecv = { version = "0.7", default-features = false }This repo is standalone — just clone it and build; Cargo fetches purecv
from crates.io. No sibling checkout is required.
To test the examples against a local, unreleased
purecv(e.g. while working on a new module), temporarily point the workspace dependency at a path:purecv = { path = "../purecv", default-features = false }.
-
The Espressif Rust toolchain (
espup), with the environment sourced so the Xtensa linker is onPATH:. $HOME\export-esp.ps1 # Windows PowerShell
-
espflashfor flashing and the serial monitor.
From the workspace root, with a board connected over USB:
cargo run -p matrix-demo --releaseThis builds, flashes, and opens the serial monitor.
An ESP32 has no filesystem, so the input image is embedded into the firmware at build time and the output is streamed back over serial as base64 for the host to reconstruct.
Convert an image to headerless 8-bit grayscale. With GIMP: open the image →
Image → Mode → Grayscale → Image → Scale Image to 96×96 →
Image → Flatten Image → File → Export As AR.data (choose "Raw image
data"). The file must be exactly W×H bytes (9216 for 96×96). If you change the
size, update the W/H constants in
gaussian-blur-demo/src/bin/main.rs.
cargo run -p gaussian-blur-demo --release *>&1 | Tee-Object run.logThe blurred image is printed between ---BEGIN OUTPUT 96x96--- and
---END OUTPUT--- markers as base64. Let it finish, then Ctrl+C.
$b64 = ((Get-Content run.log) | ForEach-Object {
if ($_ -match '[A-Za-z0-9+/=]{40,}') { $matches[0] }
}) -join ''
$bytes = [Convert]::FromBase64String($b64)
[IO.File]::WriteAllBytes((Join-Path $PWD 'output.data'), $bytes) # relative paths go to the process CWD, not $PWD — always qualify
"$($bytes.Length) bytes" # expect 9216Open output.data in GIMP (File → Open → Raw image data, Grayscale, 96×96,
offset 0) to view the blurred result.
Each example is a workspace member and an ESP binary crate, so it needs three files — copying only two silently breaks the build:
Cargo.toml— withpurecv.workspace = trueand the esp-hal deps.build.rs— copy it from an existing example. It emits the-Tlinkall.xlinker argument; without it the app descriptor is mislinked andespflashfails with "appdesc segment not found".src/bin/main.rs— the example code.
Then add the crate name to members in the workspace Cargo.toml.
Image-processing examples also need a larger heap: gaussian_blur allocates a
W×H×8-byte f64 working buffer, so bump esp_alloc::heap_allocator! accordingly
(the blur demo uses 200 KB).