◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 7 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 7 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/Advanced
⬡ Advanced/2026-08-31Advanced

Define What Counts as a Duplicate Before Adding Embedding Search to Your Image Pipeline

My dedup check flagged two prints with identical composition but different colors as one image. Here is how I split duplicate detection into three layers, measured where perceptual hashing ends, and decided what embedding search is actually for.

Gemini API249File Search7embeddings12image processingindie development28

✦ Premium Article

The wallpaper apps I run as an indie developer include a curated ukiyo-e collection, and every new asset passes through a duplicate check before it ships. One day I tried to register two prints in a row: the same composition, pulled from the same woodblock, but printed in completely different color palettes. The check declared them identical.

To me, they are two different works. Same block, different printing — I want both in the collection. That disagreement between the machine's answer and mine is what forced me to rethink how the check was built.

The timing was interesting, because File Search had just gained multimodal search, and gemini-embedding-2 can now embed images directly. Should I throw away hash matching and move the whole check to embedding search? I went back and forth for a while. The short answer: I adopted embeddings, but refused to make them the gatekeeper. This is the reasoning, with the actual distance numbers that shaped it.

The Conclusion First: Hashes Guard the Gate, Embeddings Only Suggest

Here is the structure I landed on.

StageMethodWhat the machine may do
At registration, first gateSHA-256 (byte identity)Reject automatically
At registration, second gatedHash (64-bit perceptual hash)Hold and queue for review. Never delete
After registration, asyncEmbedding nearest-neighbor searchDisplay similar existing works. Nothing else

Notice that I did adopt embedding search — I just never granted it the power to reject. The reason is the direction of each method's errors. A hash fails by missing a transformed copy. An embedding fails by calling a distinct work a duplicate. The first failure leaves one redundant pair in your collection. The second one deletes an asset you can never get back. Deletion is irreversible, so the method whose errors point in the dangerous direction does not get to stand at the gate. That is the whole principle.

"Duplicate" Is Not One Thing: Three Layers

Midway through the redesign I realized the real problem: I had never written down what I meant by duplicate. When I finally did, it split cleanly into three layers.

LayerMeaningExampleWho can answer
Layer 1Identical fileThe same file registered twiceSHA-256, instantly
Layer 2Transformed copies of one imageRe-encodes, resizes, light cropsPerceptual hash, almost instantly
Layer 3Distinct works that look alikeAlternate printings, series pieces, similar compositionsNo algorithm. This is an editorial decision

My two prints lived in layer 3, and layer 3 is not a detection-accuracy problem at all. Whether an alternate printing of the same woodblock counts as one work or two is a question about how you want to present your collection. I had been trying to solve a curation question with a similarity metric, and that mismatch was the entire source of my confusion.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦You will be able to define what counts as a duplicate in three distinct layers, and match each layer to perceptual hashing, embedding search, or human judgment before writing any code
✦You will be able to reproduce the boundary where a 64-bit hash stops working — the gap between distance 8 and distance 29 — and set thresholds for your own collection with evidence behind them
✦You will be able to prevent the irreversible mistake of auto-deleting distinct works that merely look similar, by deciding in advance which layer machines are allowed to act on
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

⬡ Advanced2026-09-05
Two Kinds of Video Questions: Why I Send "Find It" and "Prove It Isn't There" Down Separate Paths
Agentic video understanding lets the model decide which parts of a video to watch. That works beautifully for finding things, and it quietly breaks when you need to prove something never appears. Here is how I split my questions, and the coverage check I now run first.
⬡ Advanced2026-09-24
I Stopped Asking Gemini 'Is This Right?' and Started Hiding My Answer Instead
Ask Gemini to confirm a label you already chose and it tends to agree. Here is why I compared three ways of asking, chose blind re-classification, how my answer still leaked in, and the routing code that sends only disagreements to a human.
⬡ Advanced2026-09-14
When BLOCK_NONE Changes Nothing: Telling Adjustable Gemini Blocks from the Ones You Can't Move
Some safety blocks go away when you loosen a threshold. Others never will. Here is how to read the response and decide which kind you are looking at before you touch a single setting.