Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
233 changes: 184 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,89 +4,224 @@ This project lets you capture LED positions from a camera, adjust the layout, an

![showcase](https://github.com/user-attachments/assets/01fee45c-910b-40fe-9166-78a9f6adf9c2)

(randomly dropped lights on floor)
(randomly dropped lights on the floor)

---

## ✨ New Features

* **Completely redesigned UI**
* **Smooth live webcam feed** (also visible during scanning)
* **Webcam mask overlay** to visualize brightness threshold detection
* **Automatic brightness calibration** (sets a usable default automatically)
* **Improved camera handling**

* Prevents crashes if the camera is already in use
* **Manual LED placement**

* Click directly on the camera image if detection fails
* **Live parameter updates**

* Adjust settings while mapping is running
* **WLED recovery system**

* Automatically pauses if the connection is lost
* Resume mapping without restarting

---

## Prerequisites
- Python 3.10+
- Camera accessible to the host machine
- WLED controller reachable via HTTP on your network

* Python 3.10+
* Camera accessible to the host machine
* WLED controller reachable via HTTP on your network

---

## Setup

```bash
python -m venv .venv
.venv\\Scripts\\activate # on Windows
pip install -r requirements.txt
```

---

## Running the app

```bash
python server.py
```
Open `http://localhost:8000/` in your browser. The UI provides:
- Mapping controls (WLED host, LED count, segment, camera index, frames, brightness, skip-dim toggle)
- Timing controls (prelight/capture/postlight delays) and WLED transition (`TT` in ms)
- Live progress display while mapping runs
- Grid preview & camera scatter plot
- Buttons to generate/download `ledmap.json` and `2d-gaps.json` (client-side download)

Open `http://localhost:8000/` in your browser.

---

## UI Overview

The updated interface provides:

* **Device**

* WLED host
* LED count
* Segment
* Camera
* **Capture**

* Frames per LED
* Transition
* Brightness threshold (auto + manual adjustment)
* Skip-dim toggle
* Prelight / Capture / Postlight delays
* **Live scan view**

* Brightness mask overlay
* Camera scatter plot
* **Manual interaction**

* Click to place LEDs if detection fails
* **Live progress display**
* **Grid preview editor**
* **Download tools**

* `ledmap.json`
* `2d-gaps.json`

---

## Usage Guide

### 1) Prepare WLED
- Ensure the controller is reachable (open its UI, e.g., `http://10.0.0.50/`).
- Use a single segment covering the entire strip (start 0, length = LED count).
- Use 1D LED layout in WLED (disable 2D matrix/panels). The mapper addresses LEDs linearly via `/win` using `S/S2`.
- Disable any existing LED map in WLED. Existing remaps will break index-to-LED matching.

* Ensure the controller is reachable (open its UI, e.g., `http://10.0.0.50/`).
* Use a single segment covering the entire strip (start 0, length = LED count).
* Use a 1D LED layout in WLED (disable 2D matrix/panels).
* Disable any existing LED map in WLED.

---

### 2) Map LEDs

1. Open `http://localhost:8000/`.
2. In Controls, set:
- Host (e.g., `http://10.0.0.50`)
- LEDs (your strip length)
- Segment (usually 0)
- Camera (index for your system)
- Frames/LED + Min Bright (detection tuning); enable **Skip dim LEDs** to move past LEDs that never cross the threshold
- Prelight/Capture/Postlight delays (stability tuning)
- Transition (ms) — WLED `TT`, set 0 for instant changes
3. Click **Start Mapping**. The backend will:
- Turn all LEDs off → light a single LED → off (repeats for each LED)
- Capture camera frames and store positions in `data/mapping.csv`
4. When done, **Reload CSV** if needed to refresh the UI camera/grid views.

2. Configure:

* Host (e.g., `10.0.0.50`)
* LEDs (strip length)
* Segment (usually 0)
* Camera
* Frames per LED (2–8 recommended)
* Transition (usually 0)
* Click the "Auto" button next to the brightness slider. Make sure the mask in the preview is enabled and fully covers the image with the LEDs turned off.
* Enable **Skip dim LEDs** if desired (not recommended, as you'll be prompted if detection fails)
* Adjust timing (default is very fast— increase for more accuracy)

3. Click **Start Mapping**

#### During Mapping:

* Live webcam feed stays visible and smooth
* Brightness mask overlay shows detection threshold
* You can:

* Adjust parameters live
* Manually click LED positions or skip if detection fails for individual LEDs (only if Auto-Skip is disabled)
* If WLED disconnects:

* Mapping pauses automatically
* Fix the connection and resume without restarting

4. Mapping data is saved to:

```
data/mapping.csv
```

---

### 3) Shape the grid and export
- Adjust Step/Width/Height as needed.
- Click **Apply** to re-compute the grid and update the preview.
- Click **Generate ledmap.json** to download the LED map formatted for WLED (flattened `map` with `width`/`height`).
- Click **Download 2D gaps** to download a `1/-1` grid mask.

Notes:
- `ledmap.json` and `2d-gaps.json` are not saved on the server; they download in your browser. The raw capture stays in `data/mapping.csv`.
- The UI toggle “Wire LEDs (in order)” draws a red line connecting LEDs 0→N in camera space for quick sanity checks.
* Adjust:

* Step
* Width
* Height

Export options:

* **Generate ledmap.json**

* WLED-compatible map (`map`, `width`, `height`)
* **Download 2D gaps**

* `1/-1` grid mask

> Files are downloaded in the browser (not saved server-side)

---

## CLI usage (UNTESTED SINCE LAST UPDATE, MIGHT BE BROKEN)

Run mapping directly:

## CLI usage
You can run the mapping script directly:
```bash
python scripts/map_leds.py http://wled.local 150 --camera-index 1 --output data/mapping.csv
```
Add `--skip-dim-leds` to continue past LEDs that stay under the minimum brightness threshold.

and convert to JSON:
Optional:

```bash
--skip-dim-leds
```

Convert to JSON:

```bash
python scripts/convert_mapping.py --step 15 --include-meta
```

---

## Troubleshooting
- **ModuleNotFoundError: fastapi** - install dependencies with `pip install -r requirements.txt`.
- **Camera not opened** - verify the camera index and close other apps using it.
- **WLED doesn’t light**
- Confirm host/IP is reachable and WLED UI opens.
- Verify a single segment spans the entire strip.
- Test manual URLs (see above) — ensure `&SS`, `&S/&S2`, `&A`, and `&TT` are present.
- Increase Prelight/Capture/Postlight delays if your camera needs more time.

### ModuleNotFoundError: fastapi

```bash
pip install -r requirements.txt
```

### Camera not opened

* Verify camera index
* Close other apps using the camera

### WLED doesn’t light

* Verify host/IP is reachable
* Ensure correct segment setup
* Test manual `/win` calls
* Increase timing delays if needed

### WLED disconnects mid-scan

* Mapping pauses automatically
* Reconnect/reset WLED and validate connectivity by opening the WLED Web UI
* Resume mapping without losing progress

---

## Project structure
- Backend API: `server.py`
- Mapping logic: `scripts/map_leds.py`
- Conversion/trimming logic: `scripts/convert_mapping.py`
- Frontend UI: `ui/led_viewer.html`

Contributions are welcome! Fork, branch, and open a PR.
* Backend API: `server.py`
* Mapping logic: `scripts/map_leds.py`
* Conversion: `scripts/convert_mapping.py`
* Frontend UI: `ui/led_viewer.html`

---

## Contributing

Contributions are welcome!
Fork the repo, create a branch, and open a PR 🚀
Loading