Реализация AI-анализа осанки через камеру мобильного приложения
Фронтальная камера смартфона снимает пользователя, pose estimation модель выдаёт 17–33 ключевых точки скелета в реальном времени. Дальше — геометрия: углы между суставами, смещение центра масс, наклон плечевой линии. Это и есть анализ осанки.
Pose Estimation: выбор модели
Два основных пути на iOS — Apple Vision framework с VNDetectHumanBodyPoseRequest, и MediaPipe Pose (BlazePose). На Android — ML Kit Pose Detection или тот же MediaPipe.
Apple Vision — нативный выбор для iOS
import Vision
import AVFoundation
class PostureAnalyzer: NSObject {
private var poseRequest = VNDetectHumanBodyPoseRequest()
func analyze(sampleBuffer: CMSampleBuffer) {
let handler = VNImageRequestHandler(cmSampleBuffer: sampleBuffer, orientation: .up)
do {
try handler.perform([poseRequest])
guard let observation = poseRequest.results?.first else { return }
processBodyPose(observation)
} catch {
print("Pose detection failed: \(error)")
}
}
private func processBodyPose(_ observation: VNHumanBodyPoseObservation) {
guard
let leftShoulder = try? observation.recognizedPoint(.leftShoulder),
let rightShoulder = try? observation.recognizedPoint(.rightShoulder),
let nose = try? observation.recognizedPoint(.nose),
leftShoulder.confidence > 0.6,
rightShoulder.confidence > 0.6
else { return }
// Угол наклона плечевой линии
let shoulderDelta = leftShoulder.location.y - rightShoulder.location.y
let shoulderWidth = abs(leftShoulder.location.x - rightShoulder.location.x)
let shoulderTiltAngle = atan2(shoulderDelta, shoulderWidth) * 180 / .pi
// Смещение головы от центра плеч
let shoulderMidX = (leftShoulder.location.x + rightShoulder.location.x) / 2
let headOffset = (nose.location.x - shoulderMidX) / shoulderWidth
postureObserver?(PostureMetrics(
shoulderTilt: shoulderTiltAngle,
headOffset: headOffset
))
}
}
confidence > 0.6 — фильтр уверенности ключевой точки. Ниже — игнорируем, иначе модель «галлюцинирует» точки за кадром.
VNDetectHumanBodyPoseRequest возвращает 19 точек в нормализованных координатах [0, 1]. Координаты в Vision перевёрнуты по Y (0 = низ), а координаты UIView — 0 = верх. При отображении на экране — инвертировать Y.
MediaPipe Pose — кроссплатформенный вариант
MediaPipe BlazePose даёт 33 landmark точки включая лицо и кисти. Точнее Vision по плечам и бёдрам, но тяжелее по ресурсам. На мобиле используем Lite или Full модель (Heavy — только если устройство мощное и нет ограничений по battery).
// iOS через MediaPipe Tasks SDK
import MediaPipeTasksVision
let poseLandmarker = try PoseLandmarker(options: {
let options = PoseLandmarkerOptions()
options.runningMode = .liveStream
options.numPoses = 1
options.minPoseDetectionConfidence = 0.5
options.minPosePresenceConfidence = 0.5
options.poseLandmarkerLiveStreamDelegate = self
return options
}())
Метрики осанки: что измеряем
Хорошая осанка — это геометрия, и её можно формализовать:
| Метрика | Норма | Как считаем |
|---|---|---|
| Наклон плеч | < 5° | atan2(Δy плеч, Δx плеч) |
| Forward head posture | < 15° | угол шея–ухо–плечо |
| Наклон туловища | ±3° | вертикаль через плечи и бёдра |
| Симметрия плеч по Y | < 3% высоты | разница Y-координат плеч |
Forward head posture — самая частая проблема у пользователей за компьютером. Измеряем через угол между вектором ухо→плечо и вертикалью. В Vision: leftEar → leftShoulder вектор, угол к оси Y экрана.
Real-time анализ: производительность
Pose estimation на каждый кадр AVCaptureSession (30 fps) — слишком дорого на старых устройствах. Стратегии:
- Запускаем анализ не на каждый кадр, а через
CMSampleBuffer.sampleBufferCallbackQueueс throttling: каждые 100ms (10 fps анализа) -
VNDetectHumanBodyPoseRequest— выполняем на фоновой очереди, не main thread.VNImageRequestHandler.perform()— синхронный, блокирует поток
private let analysisQueue = DispatchQueue(label: "posture.analysis", qos: .userInitiated)
private var lastAnalysisTime: CFTimeInterval = 0
func captureOutput(_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection) {
let now = CACurrentMediaTime()
guard now - lastAnalysisTime > 0.1 else { return } // 10 fps
lastAnalysisTime = now
analysisQueue.async {
self.analyze(sampleBuffer: sampleBuffer)
}
}
Обратная связь пользователю
Два режима:
-
Real-time overlay — линии поверх камеры показывают отклонения (красные линии = плечи не ровно). ARKit
ARSCNViewили простоCAShapeLayerповерх preview layer - Сессионный анализ — пользователь держит телефон 30 секунд, получает отчёт по итогам сессии
Звуковой / тактильный сигнал при отклонении + таймер держания позы. Gamification: streak хорошей осанки за день.
Для коррекционных рекомендаций — связываем метрики с конкретными упражнениями. Forward head > 20°: упражнения на растяжку грудных мышц и укрепление задних мышц шеи — с иллюстрациями и видео.
Процесс работы
Выбор и интеграция pose estimation (Vision vs MediaPipe по требованиям). Реализация геометрических метрик осанки. Throttling и оптимизация производительности на реальных устройствах. UI: камера + overlay + отчёт. Библиотека коррекционных рекомендаций.
Ориентиры по срокам
Real-time анализ с базовыми метриками и overlay — 1–2 недели. Полное приложение с историей сессий, персональными рекомендациями и gamification — 2–4 недели.







