Уявіть: у користувача 50 000 фотографій у галереї. Знайти всі світлини з певною людиною вручну – години роботи. Типова галерея містить десятки тисяч фото, і кожен знімок може включати кілька облич – без AI не обійтися. Автоматичне групування за обличчями вирішує це завдання, але потребує акуратної реалізації: точність детекції, швидкість вилучення ембедінгів і правильна кластеризація. Ми спеціалізуємося на таких пайплайнах: 8+ років у мобільній розробці, 20+ проєктів з комп'ютерним баченням. Наше рішення повністю виконується на пристрої: детекція облич (Vision/ML Kit) → вилучення ембедінгу MobileFaceNet (128-вимірний вектор) → кластеризація DBSCAN. Такий підхід забезпечує конфіденційність, швидкість та роботу офлайн. On-device обробка економить до 70% витрат на хмарну інфраструктуру порівняно з серверними рішеннями – це знижує TCO додатка.
Як працює AI-групування на пристрої?
Пайплайн складається з трьох етапів, кожен з яких оптимізований для мобільних процесорів.
Детекція облич
На iOS використовуємо VNDetectFaceRectanglesRequest з Vision framework:
let request = VNDetectFaceRectanglesRequest { req, _ in
guard let faces = req.results as? [VNFaceObservation], !faces.isEmpty else { return }
for face in faces {
let faceRect = VNImageRectForNormalizedRect(face.boundingBox, width, height)
self.extractEmbedding(from: originalImage.cropping(to: faceRect)!)
}
}
На Android – ML Kit FaceDetector (проста інтеграція) або MediaPipe FaceDetector (більше контролю). Вибір залежить від вимог до точності та розміру моделі.
Вилучення ембедінгу
Apple не надає вбудованого API для розпізнавання облич (тільки детекція). Ми використовуємо MobileFaceNet – компактна модель (1–3 MB), що працює через Core ML. Після L2-нормалізації косинусна відстань між ембедінгами однієї людини – <0.3, різних – >0.6. Поріг 0.4–0.5 добре працює на практиці.
func extractEmbedding(from faceImage: CGImage) -> [Float]? {
guard let input = try? MobileFaceNetInput(face_image: MLMultiArray(from: resize(faceImage, to: CGSize(width: 112, height: 112)))) else { return nil }
guard let output = try? facenetModel.prediction(input: input) else { return nil }
let embedding = (0..<128).map { output.embedding[$0].floatValue }
return l2Normalize(embedding)
}
func l2Normalize(_ v: [Float]) -> [Float] {
let norm = sqrt(v.reduce(0) { $0 + $1 * $1 })
return norm > 0 ? v.map { $0 / norm } : v
}
Кластеризація
Для кластеризації без заздалегідь відомого числа кластерів застосовуємо DBSCAN (алгоритм густинної кластеризації). На Swift пишемо реалізацію з використанням Accelerate/BLAS для обчислення косинусної відстані:
func dbscan(embeddings: [[Float]], eps: Float = 0.45, minPoints: Int = 2) -> [Int] {
var labels = Array(repeating: -1, count: embeddings.count)
var clusterId = 0
for i in 0..<embeddings.count {
guard labels[i] == -1 else { continue }
let neighbours = rangeQuery(embeddings: embeddings, idx: i, eps: eps)
if neighbours.count < minPoints { continue }
labels[i] = clusterId
var seeds = neighbours
while !seeds.isEmpty {
let q = seeds.removeFirst()
if labels[q] == -1 { labels[q] = clusterId }
if labels[q] != clusterId { continue }
labels[q] = clusterId
let qNeighbours = rangeQuery(embeddings: embeddings, idx: q, eps: eps)
if qNeighbours.count >= minPoints { seeds.append(contentsOf: qNeighbours) }
}
clusterId += 1
}
return labels
}
Для галерей з 20 000+ ембедінгів DBSCAN з O(n²) може працювати 10–30 секунд. Прискорення досягається через ANN (Approximate Nearest Neighbour) за допомогою FAISS (є Swift binding), знижуючи складність до O(n log n).
Детальніше про модель MobileFaceNet
MobileFaceNet – це 4-шарова згорткова мережа, що вилучає 128-вимірні ембедінги. Розмір моделі всього 1–3 MB, що ідеально для мобільних пристроїв. Навчена на датасеті MS-Celeb-1M.Чому on-device краще за серверне рішення?
| Критерій | On-device | Серверне |
|---|---|---|
| Приватність | Ембедінги не покидають пристрій | Потрібна згода на передачу біометрії |
| Швидкість | Миттєва, без затримок мережі | Залежить від з'єднання та навантаження |
| Офлайн-режим | Повна робота без інтернету | Потрібне постійне з'єднання |
| Вартість інфраструктури | Немає серверних витрат | Високі витрати на GPU та зберігання |
On-device обробка в 3–5 разів швидша для типових галерей (до 10 000 фото) та повністю відповідає GDPR, CCPA та іншим регуляціям. Витрати на хмарні обчислення скорочуються до нуля, що особливо важливо для стартапів з обмеженим бюджетом.
Порівняння моделей ембедінгів
| Модель | Розмір | Розмірність | Точність (LFW) |
|---|---|---|---|
| MobileFaceNet | 1-3 MB | 128 | 99.2% |
| FaceNet | 10-30 MB | 512 | 99.6% |
| ArcFace | 20-50 MB | 512 | 99.8% |
Для мобільних додатків оптимальний MobileFaceNet – баланс точності та продуктивності.
Продуктивність на великих галереях
Реальна галерея – 5000–50000 фото. З них обличчя є приблизно в 30–40%. Припустимо, 10000 фото з обличчями, по 2 обличчя в середньому = 20000 ембедінгів. DBSCAN обробляє їх за 10–30 секунд на iPhone 14. З FAISS – 2–3 секунди. Фонове завдання реєструємо через BGProcessingTask (iOS 13+):
BGTaskScheduler.shared.register(forTaskWithIdentifier: "com.app.faceGrouping") { task in
let bgTask = task as! BGProcessingTask
self.runFaceGrouping(completion: { bgTask.setTaskCompleted(success: true) })
bgTask.expirationHandler = { /* save progress */ }
}
Зберігання результатів
Ембедінги – біометричні дані, тому зберігаємо їх локально в Core Data з шифруванням Data Protection (.complete). Ідентифікатор мапінгу – PHAsset.localIdentifier, не саме фото. В iCloud ембедінги не синхронізуються без явної згоди користувача.
Що входить в роботу
- Аналіз – оцінка обсягу галереї, вибір моделі детекції та кластеризації.
- Проєктування – архітектура пайплайну, інтеграція з Core Data / Room.
- Реалізація – написання коду на Swift/Kotlin, навчання/калібрування порогів.
- Тестування – A/B тести на реальних галереях, перевірка точності кластеризації.
- Документація – опис API, інструкція з інтеграції, посібник з налаштування.
- Підтримка – гарантія 3 місяці, супровід при оновленнях ОС.
Наша команда з 8-річним досвідом та сертифікатами Apple/Google гарантує виконання в строк. Замовте розробку on-device AI-групування для вашого додатка. Отримайте консультацію – ми підберемо оптимальне рішення під вашу галерею.
Строки
Базовий on-device пайплайн (детекція, ембедінги, кластеризація) для середніх галерей – 2–3 тижні. Масштабована версія з FAISS, фоновою обробкою, інкрементальними оновленнями та UI – 4–5 тижнів. Зв'яжіться з нами – ми розрахуємо вартість і строки індивідуально.
FaceNet: A Unified Embedding for Face Recognition and Clustering, Schroff et al.







