# GroundLens **One photo. A locally learned palette. Five minutes outside.** Created on 6 October 2026 for Hacktoberfest Week 1: Touch Grass, by Carlosjv. GroundLens turns an outdoor photograph into a color-observation mission. Its open-source machine-learning core fits k-means++ color clusters locally, then lets you choose a learned color to notice outdoors. Mission language is a fixed template, not generated by an LLM. There are no paid inference services, API keys, accounts, trackers or external model downloads. ## Try it Open `dist/index.html` in a modern browser, or use the hosted demo linked in the DEV entry. The initial illustrated garden is explicitly synthetic. Choose an actual outdoor photo, inspect its palette or learned regions, pick a color, and start a five-minute observation pause. Return and optionally save a note. Notes remain in localStorage until erased, and can be exported as JSON. Photos stay in memory; original files and EXIF/location metadata are not saved in the notebook. To use offline: download this repository, extract it, and open `dist/index.html`. All code, styles and demo drawing are bundled. Device storage behavior on `file:` URLs varies by browser; export important notes. No camera or GPS permission is requested. ## Learning pipeline 1. Decode JPEG, PNG, WebP or AVIF up to 12 MB with browser-native image decoding; resize the longest side to at most 720 px. 2. Systematically sample at most 6,500 RGB pixels and convert sRGB to CIELAB (D65). 3. Reserve every fifth sampled pixel. Fit up to five k-means++ clusters to the other pixels with seeds 26, 91 and 2026; select the lowest training squared-distance objective. Each restart has at most 35 Lloyd iterations. 4. Predict held-out pixels by nearest center; show mean ΔE76 error and a one-mean baseline. Report palette proportions over all sampled pixels. 5. Use the learned palette to personalize a fixed outdoor observation prompt. Image segmentation displays the nearest-center assignment, with no object recognition claims. This is classical unsupervised machine learning, implemented from the algorithm in readable JavaScript, not an open-weight LLM or species classifier. No pretrained dataset is used. Learning happens anew for each image. Close pixels are correlated, so within-image holdout is a reconstruction diagnostic, not independent evidence of generalization to future photographs. ## Reproduce tests Requires Node.js 20+ (no npm install): ``` node tests/model.test.cjs ``` Seven tests cover color conversion, exact known mixtures, low-variation images, invalid inputs, deterministic optimization, split/proportion invariants and 30 seeded synthetic mixtures. Initial Node v24.19.0 run: mean held-out error 3.97 ΔE76 versus 41.88 for the single-mean baseline. These synthetic mixtures were constructed for numerical verification; they are not an ecological dataset. Runtime is environment-dependent. Exact per-case results are in `tests/results.json`. ## Limitations and honest boundaries - No outdoor field trial, user study or reduction in screen time has been measured. - Synthetic demo illustration; no claim that its plants or colors describe a real place. - Color names are nearest entries in a small hand-written vocabulary, not semantic predictions. Illumination and camera processing affect them. - No identification, navigation, foraging, health, biodiversity or environmental-quality conclusions. - Five clusters can miss small details; the systematic holdout may share image structure with training pixels. - UI and WebMCP browser validation were unavailable in the static managed preview environment at initial release; numerical model tests and JS syntax checks passed. - Nothing leaves the browser through application code. The hosting provider necessarily receives normal page requests. The offline bundle avoids those after download. ## Open development Apache-2.0. You can change the clustering, sampling, color names and missions without permission from a hosted model provider. The complete model is `dist/model.js`; the app is `dist/app.js`. The browser and Node use the same model source. AI disclosure: an autonomous AI coding agent generated the implementation, tests, documentation and submission draft at the entrant's request. There is no claim of human editing or a human-run field experiment. Algorithm attribution: k-means/Lloyd's iterative quantization and Arthur & Vassilvitskii's k-means++ initialization; sRGB/D65 CIELAB color conversion. This repository's implementation is newly written; no external source code or pretrained weights are bundled. The Apache-2.0 license text is standard. Any changes made after the challenge deadline must be explicitly labeled here. None at initial release.