<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ankita</title>
    <description>The latest articles on DEV Community by Ankita (@ankita562).</description>
    <link>https://dev.to/ankita562</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4156633%2F667b8360-b0d7-47c6-a94e-5e1595956c5e.jpg</url>
      <title>DEV Community: Ankita</title>
      <link>https://dev.to/ankita562</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ankita562"/>
    <language>en</language>
    <item>
      <title>I Built an Offline Face Finder So My Friends Can Stop Scrolling the Group Chat.</title>
      <dc:creator>Ankita</dc:creator>
      <pubDate>Sun, 04 Oct 2026 14:46:15 +0000</pubDate>
      <link>https://dev.to/ankita562/i-built-an-offline-face-finder-so-my-friends-can-stop-scrolling-the-group-chat-31gf</link>
      <guid>https://dev.to/ankita562/i-built-an-offline-face-finder-so-my-friends-can-stop-scrolling-the-group-chat-31gf</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;We took a one-day trip to Mangalore, and the moment we got back, the photos started flooding the group chat. My friend let's name her Poo wanted to post a few on Instagram, but first she had to scroll through all of our pictures to find the ones she was in. It took about two hours.&lt;/p&gt;

&lt;p&gt;That's when I thought: what if something could do this for us? Finding "the photos with my face in them" is a job a computer is good at. But it would mean handing my friends' faces to someone else's server, and I wasn't willing to do that. So I built FaceGotcha for Poo and the rest of our group: a version that runs entirely on your own laptop and finds your photos for you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FaceGotcha&lt;/strong&gt; is a "where am I in all these photos?" machine. You give it a few photos of your face and a giant pile of group photos, and it hands back only the ones you're in. Nothing is uploaded anywhere.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl49th1jzqercqozux1t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl49th1jzqercqozux1t8.png" alt="The four steps of FaceGotcha: pick up to 5 photos of you, add a photo folder, press Find my photos, then swipe the maybes and download a zip" width="799" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The whole thing in five steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pick up to 5 clear photos of yourself.&lt;/li&gt;
&lt;li&gt;Throw in the photo pile: a folder, like an unzipped WhatsApp export.&lt;/li&gt;
&lt;li&gt;Press &lt;strong&gt;Find my photos&lt;/strong&gt; (the app cheerfully announces that it's "ignoring photos of food...").&lt;/li&gt;
&lt;li&gt;Swipe through only the uncertain ones. Swipe right for "that's me" (cue the GOTCHA! stamp) and left for "nope". It's like a dating app, except every match is you.&lt;/li&gt;
&lt;li&gt;Download a zip of your photos.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In my test of 55 WhatsApp photos, 26 were matched automatically, 9 needed my opinion, and 20 were ignored. Your original photos are never touched.&lt;/p&gt;

&lt;p&gt;Faces are biometric data, and these are my friends' faces. So the one rule was: nothing leaves the laptop. No accounts, no cloud, no API keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/_mOHaZB9odU" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fehhtcbeunpiou7gi8krw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fehhtcbeunpiou7gi8krw.png" alt="The FaceGotcha start screen with a progress tracker along the top and cards for adding your photos and the photo pile" width="799" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdl9besjq9yehzksenz8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frdl9besjq9yehzksenz8.png" alt="The numbers after a search: a colour bar showing how every photo was sorted" width="680" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/Ankita562" rel="noopener noreferrer"&gt;
        Ankita562
      &lt;/a&gt; / &lt;a href="https://github.com/Ankita562/facegotcha" rel="noopener noreferrer"&gt;
        facegotcha
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Find the photos you're in from a group-chat photo dump. Fully local face matching with open models (OpenCV YuNet + SFace). No cloud, no uploads.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/Ankita562/facegotcha/docs/banner.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAnkita562%2Ffacegotcha%2FHEAD%2Fdocs%2Fbanner.png" width="520" alt="FaceGotcha: a polaroid seen through a smiling magnifying glass"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Find the photos you're in, from a group-chat photo dump, fully offline&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Drop in a few photos of your face and a folder of group photos. FaceGotcha finds the ones you appear in, lets you &lt;strong&gt;swipe&lt;/strong&gt; through the uncertain ones, and gives you a zip. It runs on your own computer with open-source face models, so nobody's face data is ever uploaded anywhere.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Built for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01" rel="nofollow"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#demo" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#why-i-built-it" rel="noopener noreferrer"&gt;Why I built it&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#the-flow" rel="noopener noreferrer"&gt;The flow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#how-it-works-under-the-hood" rel="noopener noreferrer"&gt;How it works under the hood&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#open-source-pieces" rel="noopener noreferrer"&gt;Open-source pieces&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#why-open-and-local-matters-here" rel="noopener noreferrer"&gt;Why open and local matters here&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#setup-on-your-computer" rel="noopener noreferrer"&gt;Setup on your computer&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Ankita562/facegotcha#how-to-use-it" rel="noopener noreferrer"&gt;How to use it&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#getting-photos-out-of-whatsapp" rel="noopener noreferrer"&gt;Getting photos out of WhatsApp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#command-line-version" rel="noopener noreferrer"&gt;Command-line version&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#settings" rel="noopener noreferrer"&gt;Settings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#how-well-does-it-work" rel="noopener noreferrer"&gt;How well does it work?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#limitations" rel="noopener noreferrer"&gt;Limitations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#privacy" rel="noopener noreferrer"&gt;Privacy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#looking-ahead" rel="noopener noreferrer"&gt;Looking ahead&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#project-structure" rel="noopener noreferrer"&gt;Project structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#built-with" rel="noopener noreferrer"&gt;Built with&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/Ankita562/facegotcha#license-and-contact" rel="noopener noreferrer"&gt;License and contact&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Video: &lt;a href="https://drive.google.com/file/d/1sbdd88orENvaOkqviMm3ljYHQgyU6LAl/view?usp=sharing" rel="nofollow noopener noreferrer"&gt;Watch the demo video&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Ankita562/facegotcha/docs/start.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAnkita562%2Ffacegotcha%2FHEAD%2Fdocs%2Fstart.png" width="52%" alt="The start screen"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/Ankita562/facegotcha/docs/numbers.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2FAnkita562%2Ffacegotcha%2FHEAD%2Fdocs%2Fnumbers.png" width="33%" alt="The numbers after a search"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why I built it&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;One friend in my group has the phone with the best camera…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/Ankita562/facegotcha" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;Two small open models do the heavy lifting. Both come from the OpenCV Zoo and run on the CPU, so no GPU is needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;YuNet&lt;/strong&gt; finds every face in a photo.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SFace&lt;/strong&gt; turns each face into a fingerprint of 128 numbers. Faces of the same person land close together, and faces of different people land far apart.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenCV&lt;/strong&gt; runs them, and &lt;strong&gt;Flask&lt;/strong&gt; serves a little web page at &lt;code&gt;127.0.0.1&lt;/code&gt;, so other devices on the network can't open it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The scoring works like a bouncer at a door. A photo scoring 0.53 or higher walks straight in. Between 0.38 and 0.53, it gets an ID check, which means it comes to you for a swipe. Below 0.38, it's turned away.&lt;/p&gt;

&lt;p&gt;I added that middle band because OpenCV's suggested single cut-off (0.363) let the wrong people in during my first test:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Auto-matched&lt;/th&gt;
&lt;th&gt;Wrong person in it&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;OpenCV's default cut-off (0.363)&lt;/td&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;My cut-off with a review band (0.53 and 0.38)&lt;/td&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The swipe review is where I spent the most design effort. It's one photo and one gesture at a time, with undo on one key (Z). A "nope" doesn't delete anything: the photo moves to a Rejected album you can browse or download. The page also has a progress tracker along the top that ticks off each step, a scrolling reel of your matches, and a stats bar showing how every photo was sorted. Confetti appears when you find your photos, because finding your photos should feel like winning.&lt;/p&gt;

&lt;p&gt;I built this with AI assistance (Claude) for writing and explaining the code. I designed the idea, tested it on my own photos, and tuned the cut-offs from the scores.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Honest limits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is a small test on one person's face, not a benchmark, and the cut-offs were tuned on that one sample.&lt;/li&gt;
&lt;li&gt;It missed one photo of me, a group shot that scored 0.176. No cut-off could catch it without flooding the review pile with wrong people.&lt;/li&gt;
&lt;li&gt;Small faces in compressed group shots are the hardest case.&lt;/li&gt;
&lt;li&gt;A photo counts as a match if &lt;em&gt;any&lt;/em&gt; face in it matches, which is why the review step matters.&lt;/li&gt;
&lt;li&gt;The stats bar shows how photos were sorted, not an accuracy score. The app has no answer key, so I counted the real accuracy by hand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What's next:&lt;/strong&gt; finding photos of &lt;em&gt;two&lt;/em&gt; people at once (me and my best friend, together and solo), and collecting every photo of a friend for a birthday post.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;A face-sorting app has a problem most apps don't: it has to look at every one of your friends' faces. Sending the whole group chat to a cloud service just to find my face would be like photocopying everyone's face to find mine, including people who never agreed to that.&lt;/p&gt;

&lt;p&gt;Open models made a different design possible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy:&lt;/strong&gt; the models run on your own machine, so face data never leaves it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost:&lt;/strong&gt; no API keys, rate limits, or per-photo charges. The only download is two small model files, and after that it works offline.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control:&lt;/strong&gt; I could see what the models do, change the cut-offs, and swap in a different open model without asking anyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reuse:&lt;/strong&gt; both models are open source (YuNet is MIT-licensed and SFace is Apache 2.0, according to their LICENSE files in OpenCV Zoo), so anyone can run, change, and build on this project.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The honest trade-off: a big cloud service would probably be more accurate out of the box. Mine needs reference photos, a tuned cut-off, and a human to settle the borderline cases, and for photos of my friends, I'll take that deal.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
  </channel>
</rss>
