https://github.com/Passiolife/Passio-Nutrition-AI-iOS-SDK-Distribution
Welcome to Passio Nutrition-AI iOS SDK!
Feel free to watch the video we posted with the integration directions: https://www.youtube.com/watch?v=mZZAgJ2gWpc&t=192s
When integrated into your app the SDK provides you with food recognition and nutrition assistant technology. The SDK creates a video preview layer and outputs foods recognized by our computer vision technology in the video feed of your live camera along with nutrition data related to the recognized foods.
As the developer, you have complete control of when to turn on/off the SDK and to configure the outputs which includes:
By default the SDK does not record/store any photos or videos. Instead, as the end user hovers over a food item with his/her camera phone, the SDK recognizes and identifies food items in real time. This hovering action is only transitory/temporary while the end user is pointing the camera at a particular item and is not recorded or stored within the SDK. As a developer, you can configure the SDK to capture images or videos and store them in your app.
isOpenFood = true
you agree to abide by the terms of the Open Food Facts license agreement (https://opendatacommons.org/licenses/odbl/1-0) and their terms of use (https://world.openfoodfacts.org/terms-of-use) and you will have to add to the UI the following license copy:"This record contains information from Open Food Facts (https://en.openfoodfacts.org), which is made available here under the Open Database License (https://opendatacommons.org/licenses/odbl/1-0)"
In order to use the PassioSDK your app needs to meet the following minimal requirements:
https://passio.gitbook.io/nutrition-ai/guides/ios-sdk-docs/quick-start-guide
The SDK will automatically download the models according to the SDK version, by default the SDK will download compressed files. The download is faster and lighter, and it will take several seconds to decompress on the device. To download uncompressed files and shorter processing on the device you can set a flag below to false.
PassioNutritionAI.shared.requestCompressedFiles = false
After obtaining special approval the developer can also host the models on an internal server.
var passioConfig = PassioConfiguration(key: "your_key")
passioConfig.sdkDownloadsModels = false
In that case, the models be served directly to the SDK. To find out more about this special configuration please contact us.
A fast and easy way to get started with the SDK is to test it using the Quick start project. Here are the steps:
YOUR_PASSIO_KEY
inside ImageSelectionVC.swift
and replace the SDK Key with the key you obtained by signing up at https://www.passio.ai/nutrition-aiManual Installation For Xcode lower than 14.3:
Please follow the steps in the file "LegacyManuallyAddingTheFrameworkd.md" otherwise you might get the error the below.
error project: Failed to resolve dependencies
Install Swift Package for Xcode 14.3 or newer (available on MacOS Ventura)
To allow camera usage add:
`<key>>NSCameraUsageDescription</key><string>For real-time food recognition</string>`.
1) At the top of your view controller import the PassioNutritionAISDK and AVFoundation
import PassioNutritionAISDK
import AVFoundation
2) Add the following properties to your view controller.
let passioSDK = PassioNutritionAI.shared
var videoLayer: AVCaptureVideoPreviewLayer?
3) In viewDidLoad configure the SDK with the Key you obtained by signing up at https://www.passio.ai/nutrition-ai.
override func viewDidLoad() {
super.viewDidLoad()
let key = "Your_PassioSDK_Key"
//* To obtain a key please sign up at https://www.passio.ai/nutrition-ai
let passioConfig = PassioConfiguration(key: key)
passioSDK.configure(passioConfiguration: passioConfig) { (status) in
print("Mode = \(status.mode)\nmissingfiles = \(String(describing: status.missingFiles))" )
}
}
4) You will receive the PassioStatus back from the SDK.
public struct PassioStatus {
public internal(set) var mode: PassioSDK.PassioMode { get }
public internal(set) var missingFiles: [PassioSDK.FileName]? { get }
public internal(set) var debugMessage: String? { get }
public internal(set) var activeModels: Int? { get }
}
public enum PassioMode {
case notReady
case isBeingConfigured
case isDownloadingModels
case isReadyForDetection
case failedToConfigure
}
5) In viewWillAppear
request authorization to use the camera and start the recognition:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if AVCaptureDevice.authorizationStatus(for: .video) == .authorized {
startFoodDetection()
} else {
AVCaptureDevice.requestAccess(for: .video) { (granted) in
if granted {
DispatchQueue.main.async {
self.startFoodDetection()
}
} else {
print("The user didn't grant access to use camera")
}
}
}
}
6) Add the method startFoodDetection()
func startFoodDetection() {
setupPreviewLayer()
DispatchQueue.global(qos: .userInitiated).async {
self.passioSDK.startFoodDetection(foodRecognitionDelegate: self) { (ready) in
if !ready {
print("SDK was not configured correctly")
}
}
}
}
7) Add the method setupPreviewLayer
:
// MARK: PassioSDK: setup PreviewLayer
func setupPreviewLayer() {
guard videoLayer == nil else { return }
if let videoLayer = passioSDK.getPreviewLayer() {
self.videoLayer = videoLayer
videoLayer.frame = view.bounds
view.layer.insertSublayer(videoLayer, at: 0)
}
}
8) Stop Food Detection in viewWillDisappear
:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
passioSDK.stopFoodDetection()
videoLayer?.removeFromSuperlayer()
videoLayer = nil
}
9) Implement the delegate FoodRecognitionDelegate
:
extension PassioQuickStartViewController: FoodRecognitionDelegate {
func recognitionResults(candidates: FoodCandidates?,
image: UIImage?) {
if let detectedCandidates = candidates?.detectedCandidates {
detectedCandidates.forEach {
if let pidAtt = self.passioSDK.lookupPassioIDAttributesFor(passioID: $0.passioID) {
print("Food name =\(pidAtt.name)")
}
}
}
}
}
Start by adding your key to the PassioExternalConnector class
class PassioExternalConnector
var passioKeyForSDK: String {
"YourPassioSDKKey"
}
Review the RotationViewController super class is contains all the elements for adding the PassioNutritionAISDK to a view controller.
Note: If you use the SDK only in one view you could move all the code from viewDidAppear to viewWillAppear.
It is also containing the code to support device rotations.
import UIKit
import AVFoundation
import PassioNutritionAISDK
class RotationViewController: UIViewController {
let passioSDK = PassioNutritionAI.shared
var volumeDetectionMode = VolumeDetectionMode.auto
var videoLayer: AVCaptureVideoPreviewLayer? {
didSet {
backgroundImage?.fadeOut(seconds: 0.3)
// backgroundImage?.isHidden = videoLayer == nil ? false : true
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(deviceRotated),
name: UIDevice.orientationDidChangeNotification,
object: nil)
if AVCaptureDevice.authorizationStatus(for: .video) == .authorized { // already authorized
setupVideoLayer()
startDetection()
} else {
AVCaptureDevice.requestAccess(for: .video) { (granted) in
if granted { // access to video granted
DispatchQueue.main.async {
self.setupVideoLayer()
self.startDetection()
}
} else {
print("The user didn't grant access to use camera")
}
}
}
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
backgroundImage.fadeIn(seconds: 0.2)
NotificationCenter.default.removeObserver(self,
name: UIDevice.orientationDidChangeNotification,
object: nil)
stopDetection()
videoLayer?.removeFromSuperlayer()
videoLayer = nil
passioSDK.removevideoLayer()
}
func startDetection() {
}
func stopDetection() {
}
func setupVideoLayer() {
guard videoLayer == nil else { return }
print("setupVideoLayer volumeDetectionMode == \(volumeDetectionMode)" )
if let vLayer = passioSDK.getPreviewLayerWithGravity(volumeDetectionMode: volumeDetectionMode,
videoGravity: .resizeAspectFill) {
videoLayer = vLayer
vLayer.frame = view.bounds
view.layer.insertSublayer(vLayer, at: 0)
}
}
}
viewDidLoad
configure the Nutrition Advisor with the Key.
override func viewDidLoad() {
super.viewDidLoad()
let key = "Your_Nutrition_Advisor_Key"
NutritionAdvisor.shared.initConversation { status in
// initConversation status
}
}
NutritionAdvisor.shared.sendMessage(message: message) { [weak self] advisorResponse in
/// If the response is successful, you will receive PassioAdvisorResponse
/// containing food information otherwise you will get error message
}
NutritionAdvisor.shared.sendImage(image: image) { [weak self] advisorResponse in
/// If the response is successful, you will receive PassioAdvisorResponse
/// containing food information otherwise you will get error message
}
© 2024 Passio, Inc. All rights reserved.