FaceOFF
App iOS per Ass. Talea: rileva e sfoca i volti on-device, con pennello manuale, ripristino e filigrana logo.
Cos’è
FaceOFF è un’utility iOS pensata per Ass. Talea: scegli una foto dalla libreria e i volti vengono sfocati automaticamente sul dispositivo, senza upload e senza backend.
Serve a chi condivide immagini di eventi, colonie o attività associative e vuole proteggere l’identità dei minori (e non solo) prima di pubblicarle.
Versione corrente: 1.2 · iPhone e iPad · iOS 17+.
Funzionalità principali
- Sfocatura automatica — Vision rileva i volti (rettangoli + landmarks) e applica un gaussian blur ellittico sulle regioni rilevate.
- Rilevamento robusto — oltre all’immagine originale, passate di esposizione/contrasto/gamma aumentano il recall su volti in ombra o controluce; i duplicati vengono filtrati con IoU.
- Sfocatura manuale — pennello a tap per coprire volti mancati o altre aree sensibili; intensità e dimensione regolabili.
- Ripristina censura — pennello inverso che riporta pixel dall’originale, utile se un’area è stata sfocata per errore.
- Filigrana logo — overlay opzionale del logo Talea in basso a destra, applicato solo in anteprima/salvataggio.
- Undo / Redo — cronologia delle ultime 10 modifiche.
- Zoom e pan — pinch-to-zoom fino a 6× per lavorare con precisione.
- Salvataggio in galleria — permesso add-only, metadata preservati (orientamento normalizzato, qualità JPEG massima).
- Tutto on-device — nessun cloud, nessuna telemetria, nessun account.
Architettura
App SwiftUI a schermo singolo con stato gestito da un @Observable ViewModel. L’elaborazione immagini vive in un actor dedicato (FaceCensoringProcessor) così Vision e Core Image restano fuori dal main thread, con CIContext GPU e autoreleasepool per contenere i picchi di memoria.
Foto (PhotosPicker)
→ FaceCensoringProcessor (actor)
→ orientamento EXIF
→ Vision multi-pass (landmarks + rectangles)
→ CIGaussianBlur + maschera ellittica
→ Preview (pinch/zoom + pennello)
→ Salvataggio in Phototeca (add-only)
Separazione netta:
| Layer | Responsabilità |
|---|---|
ContentView | UI, chrome flottante, layout iPhone/iPad |
FaceOFFViewModel | stato app, history, watermark, salvataggio |
FaceCensoringService | API async verso l’actor di elaborazione |
WatermarkService / PhotoLibraryService | overlay logo e write su Photos |
Esempi di codice
Elaborazione off-main-thread (actor)
actor FaceCensoringProcessor {
private let context: CIContext
func process(imageData: Data, blurIntensity: CGFloat = 0.45) throws -> ProcessedImageResult {
try autoreleasepool {
// EXIF → Vision → blur ellittico per ogni volto
// …
}
}
}
Blur con maschera ellittica
let blurred = image
.clampedToExtent()
.applyingFilter("CIGaussianBlur", parameters: [kCIInputRadiusKey: blurRadius])
.cropped(to: extent)
blend.setValue(blurred, forKey: kCIInputImageKey)
blend.setValue(image, forKey: kCIInputBackgroundImageKey)
blend.setValue(ellipticalMask(for: rect, in: extent), forKey: kCIInputMaskImageKey)
Dettagli sul multi-pass Vision e sul ripristino manuale nella documentazione sotto.
Stack
| Layer | Tecnologia |
|---|---|
| App | SwiftUI, Swift 6, iOS 17+ |
| Rilevamento volti | Vision (VNDetectFaceLandmarksRequest, VNDetectFaceRectanglesRequest) |
| Elaborazione | Core Image (CIGaussianBlur, CIBlendWithMask, CIRadialGradient) |
| Foto | PhotosUI + PhotoKit (add-only) |
| Pattern | @Observable ViewModel + actor off-main |
Sviluppo con agenti AI
Il codice — pipeline Vision/Core Image, ViewModel, UI iPhone/iPad e questa documentazione — è stato scritto in collaborazione con agenti AI. Il ruolo umano: definire il brief per Ass. Talea (privacy on-device, filigrana, pennelli), rivedere tradeoff (multi-pass vs memoria, maschera ellittica vs rettangolo, history limitata) e validare su device reale.