Mac сам меняет масштаб интерфейса, когда я снимаю или надеваю очки.
Скачать для macOS · Как это работает · SteelRework · Разработчик
Я ношу очки и хотел, чтобы без них Mac становился удобнее сам. Так появился Opticus. Приложение находит моё лицо, определяет наличие очков и переключает заранее выбранный системный масштаб.
Вся обработка идёт локально. Камера не записывается, фотографии никуда не отправляются.
|
Скачать Opticus GitHub Release · Apple Silicon · macOS 14+ |
Открыть исходники GitHub · Vision, Core ML и управление масштабом |
|
SteelRework Telegram-канал · проекты и процесс разработки |
Связаться с разработчиком Telegram · @TImXaa |
GIF идут в реальном времени. По клику открывается полная запись 720p без звука.
Я показываю лицо в восьми положениях. Сегмент на окружности засчитывается только тогда, когда нужная поза действительно распознана.
Смотреть запись калибровки без очков
Второй проход создаёт профиль того же владельца в очках. Оправа может отличаться: основная модель работает вместе с персональными признаками, а не запоминает один снимок.
Смотреть запись калибровки в очках
Я снимаю очки, решение стабилизируется, экран затемняется и macOS применяет другой режим. При повторном надевании очков возвращается исходный масштаб.
Смотреть работу автоматического масштаба
| Механика | Что происходит |
|---|---|
| Выбор владельца | Если в кадре несколько лиц, Opticus сравнивает каждое с локальными шаблонами и выбирает ближайшее |
| Распознавание очков | Core ML классифицирует увеличенную область выбранного лица |
| Персональная поправка | Калибровочные векторы учитывают моё лицо, освещение и конкретные оправы |
| Защита от скачков | Одного ошибочного кадра недостаточно для смены масштаба |
| Системный масштаб | Для состояний «в очках» и «без очков» выбираются разные режимы дисплея |
| Фоновая работа | Кружок можно скрыть, распознавание продолжит работать из строки меню |
| Диагностика | Поверх камеры показываются реальные ориентиры лица и числа, участвующие в решении |
Нажмите на этап, чтобы раскрыть его механику.
01 · Выбор владельца
Apple Vision находит все лица и строит для каждого feature print. Opticus сравнивает их с двумя локальными отпечатками владельца и выбирает минимальное расстояние. Если оно не меньше 0.85, масштаб не меняется. Код: FrameAnalyzer.analyze.
02 · Область лица
Рамка выбранного лица расширяется на 8%, ограничивается границами кадра и приводится к 256 × 256 через .scaleFill. Остальные лица в классификатор не попадают. Код: predictEyeglasses.
03 · Две оценки
Первая оценка приходит из ShuffleNet Core ML. Вторая строится по персональной калибровке: границы в областях глаз и переносицы, контраст глаз относительно щёк и симметрия. Итог:
вероятность = Core ML × 0.90 + личная оценка × 0.10
В диагностике видны обе части: модель, итог, d(очки) и d(без). Код: RecognitionSignal.fused и extractVector.
04 · Фильтр времени
Берётся медиана последних семи измерений, затем применяется EMA: 62% прошлого значения и 38% новой медианы. Один неудачный кадр во время разговора не должен дёргать интерфейс. Код: TemporalDecisionFilter.
05 · Решение и масштаб
Значение выше 0.72 означает «очки надеты», ниже 0.28 — «очки сняты». Новый результат должен удерживаться 0.55 секунды. Только после этого приложение меняет системный режим дисплея.
Камера и расчёты разделены. Превью остаётся плавным, тяжёлый анализ ограничен восемью кадрами в секунду, а Core ML использует CPU и Neural Engine.
8 поз × 3 измерения × 2 состояния = 48 векторов
Синие точки на манекене показывают группы ориентиров и привязаны к глазам, носу, губам и линии подбородка. Это учебная схема: точные координаты Vision появляются только на реальном лице и видны в GIF выше.
| Поза | Что подтверждает кадр |
|---|---|
| Прямо | ` |
| Повороты | yaw < -0.16 или yaw > 0.16 |
| Наклоны | roll > 0.15 или roll < -0.15 |
| Взгляд исподлобья | меняется pitch или геометрия ориентиров, лицо остаётся почти прямо |
| Ближе | ширина лица больше базовой на 18% |
| Дальше | ширина лица меньше базовой на 18% |
Манекен показывает нужное движение, а yaw, roll, pitch, геометрия ориентиров и размер лица определяют, можно ли принять текущий кадр. Прогресс не должен расти просто от времени.
После каждого прохода сохраняются 24 шестимерных вектора и один feature print владельца. Снимки и отрывки видео не сохраняются.
Все восемь проверок заданы в CalibrationPose.matches. Принятие кадров и сохранение профиля находятся в AppModel.swift.
- контур лица;
- точки глаз, бровей, носа и губ;
- выбранное лицо и расстояние до шаблона владельца;
- вероятность основной модели;
- итоговая вероятность;
d(очки)иd(без);yaw,roll,pitch;- текущий шестимерный вектор;
- выдержка перед переключением.
Внутренние карты активаций нейросети не выводятся. Их сотни, и для диагностики решения они бесполезны.
Готовая сборка рассчитана на Apple Silicon и macOS 14 или новее.
- Скачайте последний релиз.
- Распакуйте
Opticus-macOS.zip. - Перенесите
Opticus.appвApplications. - Разрешите доступ к камере при первом запуске.
Сборка пока не нотарифицирована. Если macOS остановит первый запуск, откройте «Системные настройки → Конфиденциальность и безопасность» и выберите «Всё равно открыть».
Windows-релиза пока нет. Текущая версия напрямую использует AppKit, Apple Vision и Core Graphics, поэтому простой перекомпиляции недостаточно. Для Windows нужны отдельные камера, face landmarks и управление системным масштабом. Фальшивую кнопку загрузки ради красивого README я добавлять не стал.
Требования: macOS 14+, Xcode Command Line Tools и Swift 6.1.
git clone https://github.com/TimXa/Opticus.git
cd Opticus
swift test
./scripts/build_app.shРезультат появится в dist/Opticus-macOS.zip.
Основные части проекта:
Sources/Opticus/
├── AppModel.swift состояние приложения и весь pipeline
├── FrameAnalysis.swift Vision, выбор лица, Core ML и признаки
├── Recognition.swift калибровка и временной фильтр
├── DisplayScaler.swift режимы дисплея macOS
├── Views.swift настройки, кружок и калибровка
└── OpticusApp.swift окна, menu bar и жизненный цикл
Swift 6 · SwiftUI · AppKit · Vision · Core ML · Core Image · SceneKit · Core Graphics
- это не Face ID и не система биометрической аутентификации;
- качество зависит от света, бликов и того, насколько лицо закрыто волосами;
- очень необычная оправа может потребовать повторной калибровки;
- приложение работает с состоянием очков на выбранном лице, а не ищет отдельные очки по всему кадру;
- автоматическая смена масштаба отключается на время калибровки.
Почему калибровка устроена именно так, разобрано в инженерных заметках. Отдельный файл лицензий сторонних компонентов нужен из-за Core ML-модели, шрифта и 3D-манекена, которые я не создавал с нуля.
| Ссылка | Куда ведёт |
|---|---|
| SteelRework | проекты, обновления и процесс разработки |
| Разработчик | личный Telegram @TImXaa |
LICENSE разрешает использовать и изменять исходный код Opticus при сохранении авторства. THIRD_PARTY_NOTICES.md выполняет то же обязательство перед авторами модели, шрифта и манекена. Эти файлы не участвуют в работе приложения, но без них публичный репозиторий был бы юридически неряшливым.

