--- 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.