Spaces:
Running
Running
| title: Reachy Mini Face Detection | |
| emoji: π€ | |
| colorFrom: blue | |
| colorTo: indigo | |
| sdk: static | |
| pinned: false | |
| tags: | |
| - reachy_mini | |
| - reachy_mini_python_app | |
| # Reachy Mini β Face & Expression Detection | |
| A small [Reachy Mini](https://huggingface.co/docs/reachy_mini) app that watches | |
| the camera, detects a face and a simple facial expression, and replies with a | |
| random expressive movement (head + antennas + body). | |
| - **Happy** (a smile is detected) β quick nods, antenna wiggles, cheerful bobs. | |
| - **Neutral** (a face, no smile) β curious tilts, gentle look-arounds. | |
| - **No face** β a slow idle "breathing" motion. | |
| The design keeps the detection and behaviour logic completely separate from the | |
| robot SDK, so you can develop and test the whole thing on your laptop. | |
| ## Project layout | |
| ``` | |
| face_detection/ | |
| βββ detector.py # Face + expression detection (OpenCV Haar cascades) | |
| βββ behavior.py # Expression -> random Movement (pure logic, no SDK) | |
| βββ main.py # ReachyMiniApp glue + daemon entry point | |
| βββ local_preview.py # Run on a laptop webcam, no robot required | |
| index.html # Boilerplate for Hugging Face Space | |
| style.css # Boilerplate for Hugging Face Space | |
| tests/ # Unit tests for detector + behaviour | |
| ``` | |
| ## Requirements | |
| - Python 3.12+ | |
| - [`uv`](https://docs.astral.sh/uv/) for environments and packaging | |
| ## Quick start (local, no robot) | |
| ```bash | |
| uv venv --python 3.12 | |
| uv pip install -e ".[dev]" | |
| # Run the test suite (TDD) | |
| uv run pytest | |
| # Try it live on your webcam β prints the detected expression and the | |
| # movement the robot *would* perform. Press 'q' to quit. | |
| uv run face-detection-preview | |
| ``` | |
| ## Running on the robot | |
| See [PUBLISHING.md](PUBLISHING.md) for packaging, installing and publishing the | |
| app to a Reachy Mini via Hugging Face Spaces. | |
| ## How it works | |
| 1. The daemon launches the app and hands it a connected `ReachyMini` instance. | |
| 2. Each loop iteration grabs a camera frame (`mini.media.get_frame()`). | |
| 3. `FaceDetector` finds the largest face and classifies its expression. | |
| 4. `MovementPlanner` picks a random movement for that expression. | |
| 5. The app sends it to the robot with `goto_target(...)`. | |
| 6. On stop, the daemon returns the robot to its default pose. | |