跳到正文
DEV Community· Dara·· 4 小時前AI 評分49

Lens It:用一張自拍離線找出自己出現的所有活動照片

Lens It: Find Yourself in Every Event Photo With One Selfie, Without a Face Ever Leaving the Room

AI 導讀

Lens It 讓活動來賓用一張自拍,在攝影師的手提電腦上離線找出自己出現的所有照片。它使用開源 YuNet 和 SFace;作者在一部舊款 8 GB 手提電腦上測試,約 7 秒找出 5 張中的 5 張。自拍只在手提電腦記憶體中比對,不會儲存或上傳;活動到期後預設 72 h 自動刪除面部資料,也可即時清除。

正文

This is a submission for the Hacktoberfest Open-Source AI Challenge Week 2: Side Hustle.

TL;DR: Take one selfie, get every photo you're in from an event. It runs offline on the photographer's laptop with open-source face models. On my own photos it found 5 out of 5 in about 7 seconds, on an old 8 GB laptop.

What I Built

At a Nigerian wedding, a photographer can easily shoot 2,000 photos. Afterwards they share one huge gallery link, and guests scroll through maybe 40 before giving up. Aunty in orange aso-ebi never finds the three great shots she's in. She doesn't buy them, and she doesn't recommend the photographer.

So I built Lens It. It runs on the photographer's laptop, no internet needed:

  1. The photographer opens Lens It, picks the event folder, and it finds every face.
  2. They turn on their laptop's hotspot and put up the printed QR poster.
  3. A guest scans it, agrees to a short consent note, and takes a selfie. No app, no account, no mobile data.
  4. Within seconds they see watermarked previews of every photo they're in, and can download the full set.

Who pays? The photographer. Lens It itself is free for them to run. Events here usually go one of two ways:

  • Host-paid events: the couple or organiser already paid the photographer for everyone. Guests download their photos free, and "every guest gets their photos instantly, no WhatsApp chaos" becomes the photographer's selling point to the couple.
  • Pay-per-photo events: roaming photographers snap the audience and sell to each guest. Today, guests see watermarked previews and pay the photographer by bank transfer. Next (see What's Next), Lens It will handle this inside the app, offline.

I haven't had a paying customer yet. Getting a photographer to use it at a real event is what I'm working on next.

Lens It is a WANDERCOIL product.

What's Next

  • Pay-per-photo, offline. The venue has no internet, but guests' phones usually do, and bank transfer is how Nigerians already pay photographers. The guest picks photos (say 3 × ₦1,000), Lens It shows the photographer's account and an order code like LENS-4821, and the guest transfers with that code. The photographer sees the bank alert, taps "Paid ✓" on the laptop, and the guest's phone unlocks the full-quality download. No payment gateway needed. Paid previews will be small, watermarked across the middle and blurred except the guest's face, so a screenshot isn't worth stealing. Bundles and optional Paystack/Flutterwave links come later.
  • Tuning the match threshold using real-event results
  • A code-signed installer, so Windows stops showing the "unknown publisher" warning
  • Optional "moment search" ("cake cutting", "first dance") with a small open model, for laptops that can handle it

Demo

How it works

The Lens It website
The website: try it in your browser, or download the free Windows app.

Photographer setup screen
Photographer setup: name the event, pick the photo folder, choose when face data is deleted.

Printable QR poster
The printable QR poster, with the privacy notice built in.

Guest page on a phone
What guests see: a consent note first, then the selfie button.

Code

GitHub logo Wandercoil / lensit

Lens It: find yourself in every moment. Guests find their event photos with a selfie, matched offline on the photographer's laptop with open-source face models.

Lens It logo

Lens It

Find yourself in every moment.

CI Release

Offline, local-first event photo finder. A photographer indexes a shoot on their laptop; guests at the venue scan a QR code, take a selfie, and get every photo they're in — without the internet.

  • Selfies are matched in memory on the photographer's laptop and never saved or sent online.
  • Face data auto-deletes when the event expires (default 72 h), or immediately with purge.
  • Runs on CPU (tested on an 8 GB i5 laptop).

Models (open-source)

Task Model License
Face detection YuNet (opencv_zoo) Apache-2.0
Face recognition SFace (opencv_zoo) Apache-2.0

Quick start (Windows, no coding)

Download LensIt.exe from the latest release and double-click it. No Python needed. If Windows shows "Windows protected your PC", click More info → Run anyway (the app isn't code-signed yet).

Or run from source with the launcher

  1. Install Python 3.11+ from python.org and tick Add python.exe to PATH…
  • App: Python, FastAPI and OpenCV, packaged as one Windows .exe by GitHub Actions
  • Website and Try page: plain HTML/JS with ONNX Runtime Web
  • 18 automated tests run on every push; releases carry a SHA-256 checksum and a signed build attestation

How I Built It

Part What I used Licence
Face detection YuNet Apache-2.0
Face recognition SFace: 128-number face embeddings Apache-2.0 weights
Inference (app) OpenCV DNN on CPU Apache-2.0
Inference (browser) ONNX Runtime Web MIT
Local server FastAPI + Uvicorn MIT / BSD
Windows app PyInstaller, one .exe with the models built in GPL (bootloader exception)

The pipeline:

  • YuNet finds every face in a photo. SFace aligns each face and turns it into a normalised 128-number embedding.
  • All embeddings go into one NumPy array. Matching a selfie is a single dot product, with OpenCV's recommended cosine threshold of 0.363.
  • In the browser I rewrote the face alignment and YuNet decoding in JavaScript, then checked it against OpenCV: given the same landmarks, the browser produces the same embedding (cosine similarity 1.000).

Constraints I designed for: everything runs on my own laptop, an older Intel i5-6300U with 8 GB of RAM and no GPU. If it runs well there, most photographers' laptops should handle it.

Things I got right (and wrong) along the way:

  • I checked model licences before writing code. My first choice, InsightFace, ships weights for non-commercial use only, a dealbreaker for a side hustle. YuNet and SFace weights are Apache-2.0. One thing I'm not 100% sure about: SFace was trained on academic face datasets, some with non-commercial terms. Whether that affects commercial use of the trained weights isn't settled.
  • "Local AI" isn't automatically private. An early version had guests upload selfies to a hosted website, with matching done locally. That would still have sent faces over the internet. Putting the whole guest flow on the local network fixed it.
  • Small faces broke the first browser version. When I tested my own photos, a full-body shot failed to match because shrinking photos to 640 px turned my face into a few pixels. Lens It now also scans photos in overlapping zoomed-in tiles, and looks closer at full resolution when a selfie's face is small. A tiny-face test that used to fail now matches at 91%.
  • I verified the privacy features instead of just claiming them. Auto-expiry, instant deletion, the consent check and the 403 on setup screens all have automated tests.

Trust and security:

  • Every Python package is pinned with SHA-256 hashes, and the AI models are downloaded from a fixed upstream commit and checked against their hash before every use. A tampered model is refused.
  • GitHub Actions runs 18 tests on every push. Pushing a version tag makes GitHub test, build, smoke-test and publish LensIt.exe with its checksum and a signed build attestation, so anyone can prove the file was built from this repo: gh attestation verify LensIt.exe --repo Wandercoil/lensit.
  • No cookies, no analytics, no trackers, on the site or in the app.

Open source, protected brand: the code is AGPL-3.0, so anyone can use and improve it, but nobody can turn it into a closed product. "Lens It" and the logos are WANDERCOIL trademarks, so forks need their own name.

Does It Actually Work? Real-World Results

I didn't want to publish only the happy path, so I tested Lens It on my own real photos: WhatsApp group shots (one with 16 people), phone photos, Snapchat pictures, a screenshot, an AI-generated image and a wallpaper with no people. I removed any exact copy of the selfie from the set, so it couldn't "cheat".

Test Person searched In how many photos Correct Missed Wrong
1 Me (16 photos) 5 5 0 1
2 A friend (10 photos) 1 1 0 1

What worked:

  • It found me in 3-person group shots and in the 16-person group photo, and found my friend in the one photo they're in.
  • It correctly ignored everyone else, including an AI-generated image and a wallpaper. In test 2 it rightly said my photos weren't my friend.
  • It searched 16 photos in 7 seconds on my 8 GB laptop with no GPU.

What didn't, and the pattern behind it:

  • Sideways photos were invisible. At first it missed a Snapchat photo of me. The cause wasn't the filter: the photo was stored sideways, and the face detector only looks for upright faces. Lens It now also checks photos turned 90°, 180° and diagonally whenever it finds no upright face. That photo then matched me at 50%, and test 1 went from 4 of 5 to 5 of 5.
  • Wrong matches sat just above the line. The two wrong matches scored 38% and 41%, just over the 36% threshold. They were a screenshot and a Snapchat photo, both lower-quality images.
  • Across both folders, my own face scored 44–66%, while the 29 other faces had a median of 17%. Only one crossed 36%, and none crossed 45%.

So I changed the product based on the evidence:

  1. "Sure" vs "Maybe you?". Matches at 45% and above are shown as sure; 36–45% are tagged "Maybe you?". Re-running both tests with this rule, every sure match was correct, and both wrong matches landed in "Maybe".
  2. Maybe photos stay out of the download until the guest taps "✓ Me". Downloads are full-quality originals, so a guest can't accidentally take a stranger's photo.
  3. The selfie is checked first. A face that's too small or extremely blurry gets a "please retake" message instead of a bad search. (I first set the blur check too strict, until a test showed a softer selfie still matched correctly, so I relaxed it.)

Why Does Open Innovation Matter?

Selfie-based event photo search isn't new. Several cloud services already do it, including at least one in Nigeria. I won't pretend otherwise. The difference is where the AI runs, and that only works because the models are open.

1. It works where the internet doesn't. Many venues have weak or no network: halls on the edge of town, church grounds, gardens. Cloud selfie search needs every guest to upload a selfie over mobile data. Lens It runs open-weight face models on the photographer's own laptop and serves guests over the venue Wi-Fi or a hotspot. No internet connection is involved at any step.

2. Guests' faces never go to a third party. Under Nigeria's Data Protection Act, biometric data used for identification is sensitive personal data. With a cloud API, every guest's face goes to someone else's server. With Lens It:

  • The selfie travels over local Wi-Fi to the laptop, is matched in memory, and is thrown away. It is never written to disk.
  • The face index auto-deletes after 1, 3 or 7 days, or right away with one click.
  • Guests must tick a consent box before the camera opens, and the server rejects any search without consent.
  • The photographer must confirm they have the right to use the photos before indexing.
  • Setup screens only respond on the laptop itself. A guest's phone gets a 403.

3. It costs nothing to run. A cloud face API charges per image. At 2,000 photos per event, every weekend, that eats a small photographer's margin. Open models on a CPU cost nothing, so the business works even at ₦500 a photo.

4. No lock-in. There's no API key to get revoked and no price change to worry about. Anyone can tune the matching threshold or swap the model.

5. The same open models run in a browser. Because the models are open ONNX files, I could put the exact same face matching on the website with ONNX Runtime Web. Judges and photographers can try it on their own photos without installing anything, and still nothing leaves their device.

My Agent Session

I built Lens It with Claude Code over three days and saved the session with Entire (44 checkpoints, personal details removed):

The Lens It build session on Entire

Entire also links the session to the code, so entire search can explain why code exists. For example, searching "why did we rename to Lens It" finds the "Rename to Lens It" commit, and "small faces" finds "Detect small faces, warn before reload".

Some decisions the session shows:

  • Pivoting from a cloud selfie-search idea once we found the same product already existed, and choosing offline as the real difference.
  • Renaming from "Local Lens" when we found an established open-source project with that name.
  • Catching that hosted selfie upload would break the privacy promise, before it was built.

Prize Categories

  • Best Use of Entire: the full build session is shared above, and entire search explains why the code exists.
  • Best Use of GitHub Copilot: GitHub Actions tests every push, and on every release it builds, smoke-tests and publishes the Windows app with a signed build attestation.
  • Best Use of ElevenLabs: the demo video's narration was generated with ElevenLabs.

If you're a photographer (especially anywhere the venue network is bad 😅), try it and tell me what breaks.

來源:DEV Community · dev.to