Retake · by Hoverfly

Snap it.
Retake says keep or retake.

Check a photo the moment it's taken: blurry, too dark, too bright, glare, noisy, or a finger over the lens. On the device itself: Android, iOS, desktop and the web, from one Kotlin Multiplatform library.

Get started View source

Free up to 10k monthly active devices · No API key · On Maven Central · Android, iOS, desktop, web

…
blur
dark
bright
glare
noise
finger
retake.check(pixels, width, height)
Live demo

Check your own photo

This is the actual Retake library, compiled to WebAssembly and running in your browser. Pick an example or drop in a photo of your own. It's checked on this device; the photo never leaves this page.

Loading the model (~0.8 MB)…
The photo being checked
…
blur
dark
bright
glare
noise
finger
Checked in your browser
Why Retake

Catch the bad photo before it's sent

No server, no API key, no per-photo bill. A small Kotlin library that you can read, test and ship.

Six problems, one call

Blur, too dark, too bright, glare, noise and a finger over the lens. A score from 0 to 1 for each, the verdict, and a short hint to show the user.

Knows a screenshot

Screenshots, chats, documents and graphics aren't camera photos, so they count as good. On a real phone it flagged 4% of the Screenshots folder, and none of 102 app screenshots in the tests.

No dependencies

Pure Kotlin inference. There is no ONNX Runtime, TFLite, ML Kit or native code, and it runs on Android (minSdk 21), iOS, macOS, JVM desktop, JavaScript and WebAssembly, from Kotlin or Java.

Private & offline

The model ships inside the library on every platform. Photos never leave the device: no network calls, no permissions, no telemetry.

87%
Right on real photos
OpenCV rules: 53%
0.5MB
On-device
int8 weights
6
Problems
with a hint for each
0
Dependencies
no native code
On device

Real photos, real verdicts

The sample app on an Android emulator. Every check runs on the device. These are not mockups.

Retake flags a blurry photo

Blurry

retake: blur 99%

Retake flags glare

Glare

retake: glare 95%

Retake flags a finger over the lens

Finger

retake: finger 100%

Retake flags a dark photo

Dark

retake: dark 99%

Retake keeps a good photo

Good

keep it

Retake keeps a screenshot

Screenshot

not a camera photo: good

Same library on every platform

The Kotlin Multiplatform sample app, built from the published artifacts, gives the same result on Android, iOS, desktop and the web.

Retake sample on Android

Android

retake: blur 99%

Retake sample on iOS

iOS

retake: blur 99%

Retake sample on Desktop (JVM)

Desktop (JVM)

retake: blur 99%

Retake sample on Web (Wasm)

Web (Wasm)

retake: blur 99%

Install

Add it to your build

One line in your Gradle file, from Maven Central. Works in commonMain for Android, iOS, macOS, JVM desktop, JavaScript and WebAssembly. No API key, no account.

Maven Central live
// build.gradle.kts: commonMain, or any platform source set
dependencies {
    implementation("io.github.rajumark:retake:1.0.0")
}

// Gradle picks the right artifact per platform:
// retake-android · retake-jvm · retake-iosarm64 · retake-iossimulatorarm64
// retake-macosarm64 · retake-js · retake-wasm-js
Build with a prompt
Add Retake from rajumark to this Kotlin Multiplatform or Android project.

What it does: on-device photo quality check. Given a photo's pixels, it says whether the photo is good or should be retaken, with a 0..1 score for blur, dark, bright (over-exposed), glare, noise and finger (over the lens), plus a short hint per problem. Screenshots and graphics count as good. 0.5 MB, no dependencies, no network.

Install (Maven Central, no extra repository):
  build.gradle.kts (commonMain or any source set): implementation("io.github.rajumark:retake:1.0.0")
  Platforms: Android, iOS, macOS, JVM desktop, JavaScript, WebAssembly

Usage:
  val retake = Retake()                              // off the main thread, keep one instance
  val check = retake.check(argb, width, height)      // ARGB pixels; Android: retake.check(bitmap) or check(context, uri)
  if (!check.isGood) show(check.issues.first().hint) // e.g. "Blurry: hold still and tap to focus"

Repo: https://github.com/rajumark/retake#readme
Add the dependency, then follow the README for the exact API and current version.
Usage

One call per photo

Load once and reuse the instance. check() is thread-safe; run it on a background thread after a photo is taken or picked.

Kotlin
val retake = Retake()

val check = retake.check(argb, width, height)
// PhotoCheck(retake: BLUR, blur=0.991, dark=0.012, ...)
check.isGood               // false
check.issues               // [BLUR]
check.issues.first().hint  // "Blurry: hold still and tap to focus"

// Android shortcuts
retake.check(bitmap)
retake.check(context, uri) // reduced-size decode + EXIF rotation
Java
try (Retake retake = new Retake()) {
    PhotoCheck check = retake.check(argb, width, height);
    if (!check.isGood()) {
        String hint = check.getIssues().get(0).getHint();
    }
}
Use cases

Where Retake fits

Anywhere a bad photo costs time, money or a second trip.

ID and KYC checks

Ask for a retake on the phone before a blurry or glary ID photo is uploaded and rejected by a human a day later.

glare 0.95 → "Tilt the card away from the light"

Document and receipt scanners

Catch shaky, dark or glare-washed scans while the user is still holding the paper.

blur 0.99 → retake

Marketplace listings

Better product photos sell faster: nudge sellers to retake dark or blurry pictures before they post.

dark 0.99 → "Add light or turn on the flash"

Gallery cleaners

Find the blurry, dark and finger-covered shots in a camera roll so users can free space, without flagging screenshots.

screenshot → good
App ideas

20 apps you could build with Retake

Real problems Retake solves today. Pick one and ship it.

KYC capture · Check ID card photos for blur and glare before upload, so verification passes the first time.

Expense receipts · Make sure every receipt photo is sharp and readable before it reaches accounting.

Document scanner · Warn about shaky or glary pages while the user is still holding the paper.

Seller listing helper · Nudge marketplace sellers to retake dark or blurry product photos.

Insurance claims · Accident and damage photos that are good enough to assess, the first time.

Property inspections · Field agents get told on the spot when a room photo is too dark or blurred.

Gallery cleaner · Find blurry, dark and finger-covered shots to delete, without touching screenshots.

Best-shot picker · From a burst, keep the sharpest, best-exposed photo automatically.

Profile photo check · Dating and social apps ask for a retake before a blurry selfie becomes a profile picture.

Proof of delivery · Drivers can't submit a dark or shaky doorstep photo.

Telehealth photos · Patients send skin or wound photos that a doctor can actually use.

Homework upload · Students' photographed worksheets are readable before the teacher opens them.

Menu and food apps · Restaurants upload dish photos that look good, not grainy.

Field service reports · Technicians' before/after photos are clear enough to prove the work.

Plant and crop apps · Make sure a leaf photo is sharp before running a disease model on it.

Accessibility camera · Tell blind and low-vision users "too dark" or "your finger is on the lens".

Camera app tips · Show a gentle "hold still" or "too bright" tip right after the shutter.

Smart backup · Skip uploading blurry duplicates and finger shots to save cloud storage.

Photography lessons · Explain what went wrong with each practice shot.

Pre-check for other models · Run OCR, face or plant models only on photos good enough to give a reliable answer.

Quality

Honest numbers

Real phone photos from the LIVE In the Wild Challenge database, hand-labelled before the model was tested on them and scored once; plus 7,428 test photos with generated defects, never used for training.

RetakeOpenCV rules (Laplacian + histogram)CLIP ViT-B/32 zero-shot
Real photos: verdict right86.6%52.7%19.4%
Real app screenshots wrongly flagged (102)0——
Generated defects: verdict right / issue F192.0% / 0.88872.2% / 0.5175.3% / 0.40
Real blur ranking (BID, 586 photos): AUC0.8620.8370.789
Size0.5 MB—~350 MB

The OpenCV rules and CLIP had their lines tuned on the validation set, to be fair to them. The rules can't detect a finger, and still flag about half of all good photos; CLIP flags almost every photo for something. In the pure-Kotlin library a 1040 × 780 photo takes about 90 ms on a laptop JVM and about 235 ms in a browser; an 800 px photo takes 110–150 ms in the Android sample on an emulator. Weak spots: real glare is caught less often than the other problems, and very dark night photos or deliberate motion blur can be flagged (raise the threshold to be lenient).

Reference

API at a glance

MemberDescription
Retake()Loads the bundled model. Implements AutoCloseable.
check(argb, width, height, threshold = 0.5)Checks ARGB pixels (any size; larger than 1024 px is shrunk first). Returns a PhotoCheck.
checkRgb(rgb, width, height, threshold = 0.5)The same for RGB bytes, 3 per pixel.
PhotoCheck.isGood · issues · scores · score(issue) · strongestThe verdict, the problems found (most certain first), and every score from 0 to 1.
IssueBLUR, DARK, BRIGHT, GLARE, NOISE, FINGER, each with a short hint.
Retake.check(bitmap) · Retake.check(context, uri)Android: an upright Bitmap, or a photo Uri decoded at reduced size and turned upright from its EXIF orientation.
Pricing & license

Free until you're big.

No API key, no sign-up, no license file. Add Retake to your project and ship. It stays free until your product passes 10,000 monthly active devices, and there's never a limit on how often each device runs it.

Commercial
Let's talk

For products above 10,000 monthly active devices on any platform.

  • One license per product, per model
  • Pricing that fits your scale
  • Direct support from the people who built it
  • Early access to model updates
Custom models
Built for you

A small, fast on-device model trained for your language, domain or task.

  • Image quality, document and ID checks, moderation, classification and more
  • Tuned on your use case and your users' languages
  • Shipped as a plain Kotlin library, like Retake
  • Private: your model runs on your users' devices

How devices are counted

A monthly active device is a phone, tablet or other device that runs Retake at least once in a calendar month.

The 10,000 limit applies separately to each product, each platform (Android, iOS, web…) and each Hoverfly model. Crossed it? You have 30 days to get a commercial license.

What the license does not allow

  • Selling or redistributing Retake or its model on its own, or inside another SDK
  • Extracting, modifying or fine-tuning the model weights
  • Using the model or its outputs to train or distill another model
  • Reverse engineering the model or its file format
  • Offering it as a hosted API for others

Questions about licensing? Email raju348636@gmail.com or call / WhatsApp +91 63533 21951. Full terms: Hoverfly Community License.

FAQ

Questions

What is Retake?

A Kotlin Multiplatform library (Android, iOS, macOS, JVM desktop, JavaScript, WebAssembly) that checks a photo on the device and says whether it's good or should be retaken, and why.

Which problems does it find?

Blur (out of focus, motion, hand shake), too dark, too bright (blown out), glare and reflections, heavy noise, and a finger or object covering part of the lens. Each gets a score from 0 to 1; 0.5 is the default line.

What about screenshots and graphics?

They count as good: a dark-mode screen isn't an under-exposed photo. Retake was trained with generated screenshots, chats, documents and posters for exactly this, and flags none of 102 real app screenshots.

How fast is it?

About 90 ms per photo on a laptop JVM, 110–150 ms in the Android sample on an emulator and about 235 ms in a browser, including the shrink to 1024 px. It's meant for checking a photo after it's taken, on a background thread. On Android, check(context, uri) decodes big photos at reduced size, which saves most of the decode time.

Is the Kotlin port exact?

The tests compare it with the reference (OpenCV preprocessing + the same int8 weights in PyTorch) on 13 images on every target: the same 4 detail crops, and every score within 0.00023.

How much does Retake cost?

Nothing for products with up to 10,000 monthly active devices per platform, including commercial apps. There is no API key or account, and no limit on how often it runs. Above that, a commercial license is needed; see Pricing.

Can you build a model for my app?

Yes. Hoverfly trains custom on-device models for your task and ships them as a small library like this one. Email raju348636@gmail.com or call / WhatsApp +91 63533 21951.

A note from the creator

Built by a developer, for developers.

Every model here started as a problem I hit in my own apps. I made them small, private and free to start, so you can spend your time on the part your users will love.

Raju ShingadiyaAndroid developer · creator of Hoverfly
Meet the maker
The Hoverfly family

Retake is one of nine.

Nine small on-device models, one job each. Same install, same free tier, and the same promise: nothing leaves the device.

MojiEmoji suggestionsThe right emoji for any message, in 22 languages. BeaconLanguage detectionLanguage and script of any text, Hinglish included. CommaPunctuationTurns voice-typed text into readable sentences. ComebackSmart repliesThree tap-to-send replies for every message. EmotionEmotion detection28 emotions and an overall mood, per message. GatekeeperToxicity detectionCatches abuse and threats in Indian chat. HideoutPersonal info hidingHides phones, UPI, Aadhaar and more. ChalkDoodle recognitionGuesses 345 things from pen strokes, live.
RetakePhoto quality checkBlur, dark, glare, a finger: retake or keep?You're here
View all models Hoverfly home