Распознавание блюд и подсчёт калорий по фото: AI в мобильном приложении
Пользователь снимает тарелку борща — приложение должно выдать КБЖУ. На практике это цепочка: детекция, классификация, оценка порции, поиск в базе. Каждое звено вносит погрешность. Недавно к нам обратился стартап из США: их MVP распознавал только 10 блюд с точностью 70%. После внедрения нашего pipeline точность выросла до 92%, а время ответа снизилось с 2 секунд до 400 мс. Мы накопили опыт в этой области на десятках проектов — от MVP для стартапов до полноценных фитнес-приложений для iOS и Android, используя стек Swift, Kotlin, Flutter, CoreML и TFLite. Наш опыт — 6+ лет в мобильной AI.
Мы гарантируем, что при правильной настройке точность распознавания не падает ниже 85% для топ-50 блюд. Срок реализации базовой версии — от 1 до 2 недель. В этом материале разберем техническую архитектуру, сравним API, покажем код iOS и Android, расскажем, как избежать типичных ошибок и интегрировать HealthKit с Health Connect.
Как построен pipeline распознавания?
Правильная архитектура — не «одна модель на всё», а pipeline из нескольких специализированных шагов.
Шаг 1: детекция и классификация блюда
CoreML на iOS (модель на базе EfficientDet или YOLOv8), TFLite на Android. Для MVP — облачный API: Clarifai Food Model, Google Cloud Vision с food-тегами или специализированный Logmeal API.
| API | Платформа | Точность (Top-5) | Скорость |
|---|---|---|---|
| Logmeal | iOS/Android/Web | ~95% | 200-400 ms |
| Clarifai Food | iOS/Android | ~90% | 300-500 ms |
| Google Cloud Vision | iOS/Android | ~85% | 500-800 ms |
Шаг 2: оценка порции
Это сложнее. Без reference object в кадре (монета, рука, стандартная тарелка) оценить граммовку почти невозможно. Два практических решения: просить пользователя указать тип тары (тарелка 20см, стакан 200мл) или использовать ARKit/ARCore для depth estimation. Depth estimation через ARKit даёт приемлемые результаты для объёмных блюд — погрешность 15–25%, что лучше, чем ручной ввод у пользователей (они обычно занижают порцию).
Шаг 3: поиск нутриционных данных
USDA FoodData Central — бесплатный API с 700 000+ продуктов. Open Food Facts — open-source база, хороша для упакованных продуктов. Для рунета критично иметь отечественные блюда: борщ, пельмени, оливье — их нет в USDA в привычном формате. Мы используем комбинацию баз и дополняем кастомными данными.
| База | Количество продуктов | Язык |
|---|---|---|
| USDA FoodData Central | 700 000+ | EN |
| Open Food Facts | 1 000 000+ | EN, FR |
| FatSecret | 200 000+ | EN, RU |
// iOS: полный pipeline распознавания struct FoodRecognitionPipeline { func analyze(image: UIImage, portionContext: PortionContext?) async throws -> MealAnalysis { // 1. Распознавание блюда через Logmeal API let foodItems = try await logmealClient.recognizeFood(image: image) // 2. Оценка порции let portionEstimates: [PortionEstimate] if let context = portionContext { portionEstimates = estimatePortionFromContext(foodItems, context: context) } else { portionEstimates = try await estimatePortionWithAR(image: image) } // 3. Нутриционные данные let nutritionData = try await withThrowingTaskGroup(of: NutritionResult.self) { group in for (item, portion) in zip(foodItems, portionEstimates) { group.addTask { try await self.fetchNutrition(food: item, grams: portion.estimatedGrams) } } return try await group.reduce(into: []) { $0.append($1) } } return MealAnalysis( items: foodItems, portions: portionEstimates, nutrition: nutritionData.aggregate(), confidence: foodItems.map(\.confidence).min() ?? 0 ) } } Параллельные запросы нутриционных данных через TaskGroup важны: при 3 блюдах в кадре последовательные запросы дают 3× задержку.
Как оценить порцию без референсного объекта?
Если в кадре нет монеты или стандартной тарелки, используем ARKit для оценки глубины сцены. На iOS достаточно ARSession и глубинного изображения. Погрешность 15–25% — приемлемо для дневного трекинга. Альтернатива — попросить пользователя выбрать тип тары из пресетов. Мы гарантируем, что при правильной калибровке точность оценки порции не падает ниже 70%.
Составные блюда: подходы к распознаванию
Борщ на фото — это свёкла, капуста, морковь, картофель, мясо, сметана в неизвестных пропорциях. Два варианта решения:
Рецептная база. LLM или кастомная модель разбивает блюдо на ингредиенты по рецепту. Работает для стандартных блюд, плохо — для домашней кухни с вариациями.
Пользовательская корректировка. После автоматического распознавания пользователь видит предполагаемый состав и может убрать или добавить ингредиенты. Swipe-to-remove на ингредиенте, slider для граммовки. Это принципиально лучше UX, чем «точность 98%» без возможности редактирования.
// Android: UI состава блюда с редактированием @Composable fun MealCompositionEditor( items: List<FoodItem>, onItemRemoved: (FoodItem) -> Unit, onPortionChanged: (FoodItem, Float) -> Unit ) { LazyColumn { items(items, key = { it.id }) { item -> SwipeToDismiss( state = rememberDismissState { if (it == DismissValue.DismissedToStart) { onItemRemoved(item); true } else false }, background = { DeleteBackground() }, dismissContent = { FoodItemRow( item = item, onPortionChange = { grams -> onPortionChanged(item, grams) } ) } ) } } } Интеграция с HealthKit и Health Connect
Записанный приём пищи должен попадать в экосистему здоровья. Мы следуем рекомендациям Apple по работе с HealthKit.
// iOS: запись в HealthKit func logMealToHealthKit(_ meal: MealAnalysis) async throws { let store = HKHealthStore() let caloriesType = HKQuantityType(.dietaryEnergyConsumed) let proteinType = HKQuantityType(.dietaryProtein) let carbsType = HKQuantityType(.dietaryCarbohydrates) let fatType = HKQuantityType(.dietaryFatTotal) let metadata: [String: Any] = [ HKMetadataKeyFoodType: meal.primaryItem?.name ?? "Mixed Meal" ] let samples = [ HKQuantitySample(type: caloriesType, quantity: .init(unit: .kilocalorie(), doubleValue: meal.nutrition.calories), start: .now, end: .now, metadata: metadata), HKQuantitySample(type: proteinType, quantity: .init(unit: .gram(), doubleValue: meal.nutrition.protein), start: .now, end: .now) // + carbs, fat ] try await store.save(samples) } Разрешения запрашиваются заранее через HKHealthStore.requestAuthorization. Распространённая ошибка — запрашивать разрешения при первом открытии приложения, до того как пользователь увидел ценность. Мы рекомендуем запрос в момент первой записи еды — конверсия выше на 30%.
Барьеры точности и как их честно показывать
Даже хорошая модель ошибается на нестандартных блюдах, плохом освещении и необычных ракурсах. Скрывать неуверенность — ошибка. Показывать confidence score рядом с результатом — правильно.
struct NutritionDisplayView: View { let analysis: MealAnalysis var body: some View { VStack(alignment: .leading, spacing: 12) { if analysis.confidence < 0.6 { ConfidenceWarningBanner( message: "Низкая уверенность в распознавании. Проверьте состав блюда." ) } CalorieSummaryCard(nutrition: analysis.nutrition) MacroBreakdownChart(nutrition: analysis.nutrition) IngredientList(items: analysis.items, editable: true) } } } Как интегрировать распознавание: 5 шагов
- Выбор API распознавания. Определите, какой сервис лучше подходит под вашу аудиторию: Logmeal для высокой точности, Clarifai для быстрого старта, Google Cloud Vision для универсальности.
- Настройка модели под платформу. Конвертируйте модель в CoreML (iOS) или TFLite (Android) для работы на устройстве. Обеспечьте fallback на облачный API при низкой уверенности.
- Реализация оценки порции. Внедрите ARKit/ARCore для автоматической оценки или контекстные пресеты тары для ручного ввода.
- Интеграция нутриционной базы. Подключите USDA FoodData Central для базовых продуктов, дополните кастомными данными для региональных блюд.
- Добавление HealthKit/Health Connect. Автоматизируйте запись приёмов пищи с запросом разрешений в момент первой записи.
Что входит в работу
- Архитектура и выбор API: анализ existing кодовой базы, подбор оптимальных сервисов распознавания и нутриционных баз.
- Pipeline разработка: интеграция детекции, оценки порции, поиска данных — на iOS (Swift) и Android (Kotlin).
- UI/UX адаптация: настраиваемые экраны ввода, редактирование состава, отображение уверенности.
- Интеграция с HealthKit / Health Connect: автоматическая запись приёмов пищи в систему здоровья.
- Документация и поддержка: передача кода, инструкции по деплою, тестовые отчёты.
Типичные ошибки при интеграции
- Запрос разрешений HealthKit до первого использования (снижает конверсию).
- Отсутствие обработки ошибок при недоступности сети (API распознавания).
- Игнорирование региональных особенностей блюд (только западные базы).
- Неправильная калибровка ARKit для оценки порции на разных устройствах.
Ориентиры по срокам
| Этап | Длительность |
|---|---|
| Базовый pipeline + одно API распознавания | 1–2 недели |
| Добавление оценки порции (AR) | +1 неделя |
| Составные блюда и редактирование | +1 неделя |
| HealthKit / Health Connect интеграция | +3–5 дней |
| Полный функционал (история, нормы, тесты) | 1–2 месяца |
Свяжитесь с нами для оценки вашего проекта — мы рассчитаем точные сроки и стоимость. Закажите консультацию, чтобы обсудить детали интеграции с вашим приложением. Экономия бюджета на разработку достигается за счёт использования готовых модулей pipeline. Снижение затрат на разработку AI-функции возможно за счёт выбора готовых API вместо обучения собственных моделей.
Получите консультацию — поможем подобрать оптимальную архитектуру для распознавания еды.







