On-device few-shot annotation and dataset organization for iPadOS and macOS.
Point Censor at a folder of images, PDFs, CSVs, or Excel files. Draw a few boxes and labels, or classify a few whole files, and Censor finds the rest — entirely on-device, with no bundled models and no network calls.
See docs/Censor-White-Paper.md for the full design rationale.
- Import — point at a folder; PDFs, images, CSVs, and Excel files are scanned (each PDF page becomes its own labelable unit).
- Annotate — draw a box and assign its label in one action, on a handful of seed files. A Rapid Fire mode lets you place several boxes first, then label them in a fast pass, then advance to the next file.
- Propagate — an on-device few-shot matcher (Vision object-region proposals + feature-print embeddings, no bundled model) finds boxes that visually match your labeled exemplars across the rest of the folder.
- Review — confirm, reject, or adjust each proposed box. Confirming grows a category's exemplar set; rejecting tightens its match threshold — an active-learning loop driven entirely by your review decisions, no prompting required.
- Autoscan — the same idea at the whole-file level, including CSV/Excel: classifies files against categories you've already seeded, and clusters whatever's left by similarity (visual feature-print for images/PDFs, on-device sentence-embedding of column headers for tabular data — schema only, no cell content is read).
- Export — cropped-by-category folders, whole-files-by-category folders, or a detection manifest (COCO JSON / YOLO / Create ML JSON). Censor doesn't train a model itself; export is where its job ends.
- Xcode with iPadOS 26 / macOS 26 SDKs
- XcodeGen (
brew install xcodegen)
xcodegen generate
open Censor.xcodeprojBuild and run the Censor target for either macOS or iPadOS (no iPhone/watch target — the
annotation workflow assumes a larger canvas).
Single SwiftUI codebase targeting a shared multiplatform destination, no external dependencies —
only system frameworks (SwiftUI, SwiftData, Vision, PDFKit, NaturalLanguage, Compression, ImageIO).
State is modeled with SwiftData across Workspace, DocumentItem, Category, Annotation (box
labels), and DocumentLabel (whole-file labels). The on-device matching engine sits behind a
RegionMatcher protocol specifically so an alternate backend (e.g. a cloud vision-language model,
for users willing to trade privacy for open-vocabulary recall) could be added later without
reworking the rest of the app — no such backend exists today.
Notably, .xlsx support is a from-scratch, dependency-free reader: a minimal ZIP central-directory
parser plus raw-DEFLATE inflate (via the system Compression framework) and a targeted XML walk,
since there's no built-in high-level unzip API usable on both iOS and macOS.
- Autoscan's similarity thresholds are untuned starting points, not calibrated against real
data — expect to adjust the constants in
Core/Vision/AutoscanEngine.swiftonce you see it running on an actual mixed folder. .xlsxparsing assumes the first sheet isxl/worksheets/sheet1.xml(true for virtually every workbook from Excel/Numbers/Sheets), falling back to the lexicographically-firstsheet*.xmlif not — it does not resolve sheet order viaxl/workbook.xmlrelationships.- The CSV/XLSX header readers and the ZIP/inflate logic were verified against hand-built real fixture files during development, but not against a broad corpus of real-world spreadsheets.
- This project was developed in an environment where
xcodebuildwas unavailable — all Swift source was verified viaswiftc -typecheckon both the macOS and iOS Simulator SDKs, not a full Xcode build or on-device run. Build and test in Xcode before relying on it.