Inspiration
We were presented with a powerful cause that also presented a technical challenge for our team - this, paired with Antoine's passion for impact, inspired us to pursue this track for the greater good.
What it does
The web app scans two different lenses and measures them in order to generate a 3D model of a frame to be 3D printed for cost-efficiency to make them accessible for people around the world.
How we built it
Iris is a React and TypeScript web app, built with Vite. It runs entirely in the browser: photos are processed locally in a Web Worker with OpenCV.js, and nothing is uploaded. The user photographs a loose lens next to an object of known size, either a standard bank card (85.6 × 54 mm) or a printed ArUco marker, and the app works out the lens's real-world dimensions from that photo.
Straighten. The app finds the card or marker. It refits the reference's edges to sub-pixel straight lines, because the whole scale depends on those four corners. It then computes the perspective transform that turns the photo into a top-down view at a known pixels-per-millimetre scale.
Isolate. In the straightened image, anything that differs from the table colour, or has an edge, is a barrier. Flood-filling the table from outside leaves the lens. The table colour is modelled as a smooth gradient, and the search is repeated at coarser blurs, so uneven lighting and textured surfaces such as wood don't confuse it.
Measure. The traced outline is converted to millimetres and smoothed, then width A, height B and the perimeter are computed from it. The app shows a check image with the outline, A, B, the perimeter and a 10 mm scale bar, so the user can confirm the trace by eye. The millimetre outline is exported as a 1:1 SVG and as JSON for the frame generator, which builds the 3D-printable frame.
It's classical computer vision, plus a Python-generated test set. The test photos are perspective-warped scenes with known lens sizes, and the app measures them to within about 0.3 mm.
Challenges we ran into
Turning a photo into a trustworthy measurement was harder than expected. Our first reference, a printed marker, wasn't recognised when it came from a different generator, so we switched to something everyone already has: a bank card. Real tables then caused trouble. Wood grain and uneven lighting made the lens disappear into the background, and clear lenses are almost invisible against a surface. We solved this by teaching the app to ignore texture and lighting gradients, and by adding a "what the scanner saw" view - our way of debugging it. That view shows exactly why a photo fails, so we could fix problems instead of guessing.
Accomplishments that we're proud of
Anyone with a phone and a bank card can now measure a lens. There is nothing to buy, print or install, and the photo never leaves the device. On our test photos, which have known lens sizes, the app measures within about 0.3 mm. It handles tinted and clear lenses, tilted shots, and wood or fabric surfaces. It also refuses to give a number when it isn't sure, with a clear message instead of a wrong answer. We built the whole measuring pipeline with classical computer vision, with no AI model or training data. And best of all, it is free of charge!
What we learned
Real-world conditions matter more than clever algorithms: lighting, table texture and camera angle decided whether our approach worked. Giving the app one object of known size is a simple trick that makes a phone photo precise. And testing against fake photos with known answers, plus honest error messages, made us far faster at finding what was broken. We also learned to be upfront about limits: our accuracy numbers come from test photos, not yet from real lenses.
What's next for Iris
We plan on training an AI model with PyTorch that will essentially recognize different objects around the lens so it can always know to pick the lens for scanning as well as improve its accuracy (which currently is 0.5 to 1 mm).
Built With
- clipper-lib
- js-aruco2
- manifold-3d
- netlify
- opencv.js
- python
- react19
- three.js
- typescript
- vite
Log in or sign up for Devpost to join the conversation.