| --- |
| title: PAREIDOLIA |
| emoji: ποΈ |
| colorFrom: gray |
| colorTo: indigo |
| sdk: gradio |
| sdk_version: 6.16.0 |
| app_file: app.py |
| pinned: false |
| license: apache-2.0 |
| short_description: "point at anything. find the face that was always there." |
| models: |
| - openbmb/MiniCPM-V-4_5 |
| - openbmb/VoxCPM2 |
| datasets: |
| - AndresCarreon/pareidolia-menagerie |
| tags: |
| - track:wood |
| - sponsor:openbmb |
| - achievement:offbrand |
| - achievement:sharing |
| - achievement:fieldnotes |
| - achievement:offgrid |
| - build-small-hackathon |
| - minicpm |
| - voxcpm |
| - camera |
| - multimodal |
| --- |
| |
| # ποΈ PAREIDOLIA |
|
|
| **Everything secretly has a face.** |
|
|
| Point your camera at any object. A small **MiniCPM-V** spirit-medium studies the |
| photo the way you study clouds β it finds the two bonnet bolts that were always |
| eyes, the outlet cap that was always a mouth β and the face that was hiding in |
| your fire hydrant opens its eyes, blinks at you, and tells you, in its own |
| voice, exactly what it has been putting up with. |
|
|
| > *"Forty years on this corner. Not one dog has shown me respect."* |
|
|
| Every awakened object joins the **Menagerie** β one public wall, shared by every |
| visitor, where all of them blink, glance around, and mutter. |
|
|
|  |
|
|
| *βΆοΈ [Watch the 75-second demo on YouTube](https://youtu.be/tRAISheTCT8) (works muted).* |
|
|
| ## β¨ The moment that sells it |
|
|
| You photograph your own coffee mug. Mist crosses the photo while the medium |
| works β *"there is something hereβ¦"* β then it names what it found: *"the two |
| painted notesβ¦ symmetricβ¦"* Two eyes the exact color of the glaze fade onto the |
| ceramic and **blink**. And then the mug speaks. It has noticed things about you. |
| It has been keeping a list. |
|
|
| No face is invented. The eyes land on features that are *really there* β that's |
| the whole point, and the whole name. |
|
|
| ## π§ How it works β taste from the model, facts from the code |
|
|
| A hard separation of church and state, twice over: |
|
|
| ``` |
| your photo (browser downscales; YOUR ZeroGPU quota pays for your sΓ©ance) |
| β |
| βΌ one @spaces.GPU window, ~20s |
| ββ THE MEDIUM Β· MiniCPM-V-4_5 βββββββββββββββββββββββββββββββββββ |
| β ONE structured generation (critique-then-final JSON): β |
| β privacy gate β object + condition β named VISIBLE features β |
| β ("left bonnet bolt: eye") β persona β the grudge β |
| ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββ |
| βΌ |
| ββ THE SURVEYOR Β· OpenCV, deterministic βββββββββββββββββββββββββ |
| β snaps each named feature to the strongest real anchor nearby β |
| β (Hough circles, blobs, corners; pair-coherence rules) β β |
| β the model never places a pixel; the code never invents an eyeβ |
| ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββ |
| βΌ |
| ββ THE VOICE Β· VoxCPM2 ββββββββββββββββββββββββββββββββββββββββββ |
| β voice DESIGNED from a text description β ten distinct β |
| β characters, zero reference audio β |
| ββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββββββββ |
| βΌ |
| the LIFE engine (client-side SVG): eyes tinted from the photo's own |
| palette β first blink β saccades, pupil-follow β the mouth rides the |
| audio's amplitude. The wall replays all of it forever with ZERO GPU. |
| ``` |
|
|
| The writing is governed, not vibes: a grudge-archetype bank keyed to the |
| object's *visible condition* (the_veteran/rusted, the_martyr/worn, |
| the_perfectionist/pristine, the_diva/displayedβ¦), and an iron rule that every |
| line must reference something actually in the photo. |
|
|
| Privacy is structural: the same generation gates **real human faces and NSFW** |
| before anything else runs β the refusal is simply *"It is already awake."* β |
| and nothing reaches the public wall except server-held, gate-checked records. |
| No user identity is ever stored. |
|
|
| ## π¦ Models (β 11B total β well under the 32B cap) |
|
|
| | role | model | size | license | |
| |---|---|---|---| |
| | sees the face, writes the soul | [openbmb/MiniCPM-V-4_5](https://huggingface.co/openbmb/MiniCPM-V-4_5) | 8.7B | Apache-2.0 | |
| | speaks the grudge | [openbmb/VoxCPM2](https://huggingface.co/openbmb/VoxCPM2) | 2.29B | Apache-2.0 | |
|
|
| Both models run **in-Space**. No external APIs, no remote endpoints. |
|
|
| ## π Badges |
|
|
| - **Off-Brand** β the entire UI is custom (static `web/` served by `gr.Server`; |
| zero gradio components on screen). |
| - **Off the Grid** β all inference in-Space on ZeroGPU. |
| - **Sharing is Caring** β every awakening publishes its full wake-trace (the |
| medium's JSON, the surveyor's snap deltas, the chosen voice) to |
| [AndresCarreon/pareidolia-menagerie](https://huggingface.co/datasets/AndresCarreon/pareidolia-menagerie). |
| - **Field Notes** β [FIELD_NOTES.md](FIELD_NOTES.md) β the build log, including |
| the dependency saga and what a vision model does when you ask it to find |
| eyes in a stapler (also written up as a [field report](BLOG.md)). |
|
|
| ## π Submission links |
|
|
| - **Demo video:** [youtu.be/tRAISheTCT8](https://youtu.be/tRAISheTCT8) β 75s, real awakenings + real voices, works muted. ([.mp4 mirror](https://huggingface.co/spaces/build-small-hackathon/pareidolia/resolve/main/demo/pareidolia-demo.mp4)) |
| - **Social post:** [x.com/_Andresio/status/2066372315202441312](https://x.com/_Andresio/status/2066372315202441312) |
|
|
| ## βΆοΈ Run it locally |
|
|
| ```bash |
| pip install -r requirements-dev.txt |
| PAREIDOLIA_BACKEND=mock python app.py # mock medium: no GPU, no ML deps needed |
| ``` |
|
|
| The Space runs `PAREIDOLIA_BACKEND=zerogpu`; mock returns canned awakenings |
| with realistic latency so the whole experience works on a laptop. |
|
|
| ## π Credits |
|
|
| - Models: OpenBMB **MiniCPM-V-4_5** + **VoxCPM2** (Apache-2.0). |
| - Seed-wall photos: CC0 / public-domain images via Openverse & Wikimedia |
| Commons β per-image attribution in [`seeds/eval/LICENSES.md`](seeds/eval/LICENSES.md). |
| - Type: Cormorant Garamond (SIL OFL). |
| |
| *It was in there all along.* |
| |