Desert Ant Labs

Eye

Image classificationBeta

Tag every photo by what it is and what's in it, from screenshots and receipts to 558 scenes, entirely on the device.

Tag and rank images.

Find the screenshots, receipts and selfies in a camera roll, the shots where someone's eyes are closed, and the photos too sensitive to show. Eye tags every photo on the device, so no image is uploaded.

Eye groups near-duplicate shots and picks the keeper from each burst, with no one's eyes closed and the best faces. A camera roll of forty takes of the same moment becomes one photo to look at.

A photo takes 5.5ms on the Neural Engine of a Mac with an M6, so 10,000 photos take under a minute. In Chrome with WebGPU, a photo takes 41ms.

Tag a photo in 5.5ms.

Eye tags a photo in 5.5ms on the Neural Engine of an M6 Mac, and in 41ms with WebGPU in Chrome. The Core ML and LiteRT builds score the same on six public test sets.

5.5ms
Per photo
Neural Engine, Mac with an Apple M6
41ms
In Chrome
WebGPU, same Mac
98%
Screenshot precision
at the 0.5 cutoff; receipts 100%
48MB
Download
Core ML; 66MB LiteRT

One photo, the full photo analysis, on a Mac with an Apple M6.

RuntimeTime
Core ML, Neural Engine5.5ms
LiteRT, GPU (Metal)30ms
LiteRT.js, WebGPU, in Chrome41ms
LiteRT, CPU, 4 threads49ms
LiteRT.js, WebAssembly with threads, in Chrome176ms

Accuracy on public test sets, through the same scoring code for both builds

Test setCore MLLiteRT (CPU)
KonIQ-10k, aesthetic SRCC0.62880.6291
COCO val2017, person AP500.38140.3837
MIT1003, where people look, CC0.71530.7195
CUHK cropping, crop IoU0.82440.8241
WIDER Face val, AP, hard0.68060.6812
CEW, eyes open AUC0.99430.9945

Both builds give the same answers to within a few thousandths on every set. Speed is measured on one Mac with an Apple M6, and the LiteRT build is not yet measured on Android phones.

Use cases

Tag and rank images.

Sort the camera roll

Separate screenshots, receipts, documents and whiteboards from the photos people took, so a gallery app can file them away or offer to clear them out.

Keep the best of a burst

Collapse near-duplicate shots into one group and show the keeper first, with no one's eyes closed. The rest can go in one tap.

Hide sensitive photos

Blur explicit, violent or medical photos before anyone sees them, in a shared family album or a browser upload form. Use the strict cutoff to hide a photo automatically.

Search photos by what's in them

Find every photo of the dog, the beach or a receipt across 558 scenes and the photo types. It works in a web app or a Node backend, with no cloud vision API.

Crop a cover image

Pick the best frame of a video or the best square or widescreen crop of a photo for a thumbnail or a share card. Eye also turns sideways photos the right way up.

What the model does

  • One analyze call gives tags with a confidence, three scores (aesthetic, keeper and cover), and the people, pets and faces in the photo. The same call finds the best crop for any aspect ratio, a rotation fix and an embedding.
  • Tags cover the photo type (screenshot, receipt, document, ID card, whiteboard and more), quality (sharp, blurry, bokeh) and people (group shot, portrait, everyone smiling). Others cover keep or delete reasons, sensitive content and 558 scenes.
  • Every tag is calibrated so 0.5 is the recommended cutoff and 0.9 a strict one. At 0.5, a screenshot tag is right 98% of the time, a receipt tag 100%, people 95% and eyes closed 92%.
  • Scene tags are right 88% of the time at the median. The keep or delete reasons, such as forgettable or bad framing, are the least reliable, so use them for suggestions.
  • Each face gets its own tags: eyes closed, smiling, looking at the camera or away, happy, surprised. Eye analyzes up to 20 faces per photo by default.
  • Eye.duplicates, Eye.best and Eye.similar work across a library: near-duplicate groups, optionally only for photos taken seconds apart, the keeper of a set, and photos ranked by similarity.
  • Analyses save as the same JSON in Swift, Kotlin and JavaScript, so an app can store them and filter later without loading the model.
  • parts chooses what to compute: photo, layout, faces and sharpness. Each part is one or more model runs, so leave out what you don't need.
  • 48MB as Core ML for Apple platforms, on the Neural Engine, and 66MB as LiteRT for Android, Linux, Windows, Node and the browser. The SDK downloads the model on first use and caches it.
  • In the browser, Eye runs on the GPU through WebGPU where the browser has it, and on the CPU through WebAssembly otherwise.

Getting started

Add image classification to your iOS or macOS, Android or web app in a few lines of code. Eye docs.

iOS, macOS
Install
// Swift Package Manager
.package(url: "https://github.com/Desert-Ant-Labs/desert-ant-core.git", from: "4.0.0")
// target dependency
.product(name: "Eye", package: "desert-ant-core")
Example - Swift
import Eye

let eye = Eye()
let photo = try await eye.analyze(contentsOf: photoURL)

if photo.has(.screenshot) || photo.has(.receipt) { archive(photo) }
if photo.has(.sensitive, .strict) { hide(photo) }
photo.scores?.aesthetic           // 0.81: better than 81% of photos
let keeper = Eye.best(of: burst)
Build with a prompt
Add Eye from Desert Ant Labs to this Swift project (iOS, macOS).

What it does: On-device Photo Tagging and Scoring.

SDK:

Swift (iOS, macOS)
Repo: https://github.com/Desert-Ant-Labs/desert-ant-core#readme
// Swift Package Manager
.package(url: "https://github.com/Desert-Ant-Labs/desert-ant-core.git", from: "4.0.0")
// target dependency
.product(name: "Eye", package: "desert-ant-core")

Reference:
- Model page: https://desertant.com/models/eye/
- Full catalog and other models: https://desertant.com/llms.txt

Add the SDK, then follow its README for the exact API and current version. Do not invent API names or method signatures; confirm them against the README.
Android
Install
// build.gradle.kts (Maven Central)
implementation("ai.desertant:eye:4.0.0")
Example - Kotlin
import ai.desertant.eye.Eye
import ai.desertant.eye.Tags

Eye(context).use { eye ->
    val photo = eye.analyze(bitmap)
    if (photo.has(Tags.DOG) && !photo.has(Tags.BLURRY)) keep(photo)
    val groups = Eye.duplicates(library)
}
Build with a prompt
Add Eye from Desert Ant Labs to this Kotlin project (Android).

What it does: On-device Photo Tagging and Scoring.

SDK:

Kotlin (Android)
Repo: https://github.com/Desert-Ant-Labs/desert-ant-core#readme
// build.gradle.kts (Maven Central)
implementation("ai.desertant:eye:4.0.0")

Reference:
- Model page: https://desertant.com/models/eye/
- Full catalog and other models: https://desertant.com/llms.txt

Add the SDK, then follow its README for the exact API and current version. Do not invent API names or method signatures; confirm them against the README.
Web, Node.js
Install
npm i @desert-ant-labs/eye @litertjs/core   # browser
npm i @desert-ant-labs/eye                  # Node
Example - TypeScript
import { Eye, Tag } from "@desert-ant-labs/eye";

const eye = await Eye.load();
const photo = await eye.analyze(image);
if (photo.has(Tag.dog) && !photo.has(Tag.blurry)) keep(photo);
const groups = Eye.duplicates(library, { dates });
Build with a prompt
Add Eye from Desert Ant Labs to this JavaScript / TypeScript project (Web, Node.js).

What it does: On-device Photo Tagging and Scoring.

SDK:

JavaScript / TypeScript (Web, Node.js)
Repo: https://github.com/Desert-Ant-Labs/desert-ant-core#readme
npm i @desert-ant-labs/eye @litertjs/core   # browser
npm i @desert-ant-labs/eye                  # Node

Reference:
- Model page: https://desertant.com/models/eye/
- Full catalog and other models: https://desertant.com/llms.txt

Add the SDK, then follow its README for the exact API and current version. Do not invent API names or method signatures; confirm them against the README.

Specs

Speed
5.5ms a photo on the Neural Engine (M6 Mac); 41ms with WebGPU in Chrome
Accuracy
At the 0.5 cutoff: screenshots 98% precise, receipts 100%, scenes 88% at the median
Tags
Photo type, keep or delete, quality, people, faces, sensitive content, and 558 scenes
On-device size
48MB Core ML (Apple); 66MB LiteRT (Android, Linux, Windows, Node, the browser)
Platforms
iOS 18+, macOS 15+, tvOS 18+, visionOS 2+ (Core ML); Android, Linux, Windows (LiteRT); the browser and Node (LiteRT.js)

Eye is trained on photos, so scores for illustrations, screenshots and heavily edited images are less reliable. The keep or delete reasons, such as forgettable or bad framing, are the least reliable, so use them for suggestions and the strict cutoff for anything automatic.

Face analysis describes a face and doesn't identify who someone is.

FAQ

What is Eye?

Tag every photo by what it is and what's in it, from screenshots and receipts to 558 scenes, entirely on the device.

Does Eye run on device?

Yes. Eye runs on the device, with no server call, so the data stays with the user.

Which platforms does Eye support?

Eye ships as a native on-device SDK for Swift, Kotlin, JavaScript / TypeScript.

How much does Eye cost?

Each model is free up to 100k monthly active devices. Inference is unlimited. Contact us for custom licenses.

How accurate or fast is Eye?

Eye tags a photo in 5.5ms on the Neural Engine of an M6 Mac, and in 41ms with WebGPU in Chrome. The Core ML and LiteRT builds score the same on six public test sets.

Resources