Camera detection
Camera Preview
To start using camera detection the app must first acquire the permission to open the camera from the user. This permission is not handled by the SDK.
Add the UI element that is responsible for rendering the camera frames:
var videoLayer: AVCaptureVideoPreviewLayer?
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)
}
}
Start food detection
The type of food detection is defined by the FoodDetectionConfiguration
object. To start the Food Recognition process a FoodRecognitionListener also has to be defined. The listener serves as a callback for all the different food detection processes defined by the FoodDetectionConfiguration. When the app is done with food detection, it should clear out the listener to avoid any unwanted UI updates.
Implement the delegate FoodRecognitionDelegate
:
extension PassioQuickStartViewController: FoodRecognitionDelegate {
func recognitionResults(candidates: FoodCandidates?,
image: UIImage?) {
if let candidates = candidates?.barcodeCandidates,
let candidate = candidates.first {
print("Found barcode: \(candidate.value)")
}
if let candidates = candidates?.packagedFoodCandidates,
let candidate = candidates.first {
print("Found packaged food: \(candidate.packagedFoodCode)")
}
if let candidates = candidates?.detectedCandidates,
let candidate = candidates.first {
print("Found detected food: \(candidate.name)")
}
}
}
Add the method startFoodDetection()
func startFoodDetection() {
setupPreviewLayer()
let config = FoodDetectionConfiguration(detectVisual: true,
volumeDetectionMode: .none,
detectBarcodes: true,
detectPackagedFood: true)
passioSDK.startFoodDetection(detectionConfig: config,
foodRecognitionDelegate: self) { ready in
if !ready {
print("SDK was not configured correctly")
}
}
}
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")
}
}
}
}
Stop Food Detection in viewWillDisappear
:
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
passioSDK.stopFoodDetection()
videoLayer?.removeFromSuperlayer()
videoLayer = nil
}
The FoodCandidates
object that is returned in the recognition callbacks contains three lists:
detectedCandidates
detailing the result of VISUAL detectionbarcodeCandidates
detailing the result of BARCODE detectionpackagedFoodCandidates
detailing the result of PACKAGED detection
Only the corresponding candidate lists will be populated (e.g. if you define detection types VISUAL and BARCODE, you will never receive a packagedFoodCandidates list in this callback).
Visual detection
A DetectedCandidate represents the result from running Passio's neural network, specialized for detecting foods like apples, salads, burgers etc. The properties of a detected candidate are:
name
passioID (unique identifier used to query the nutritional databse)
confidence (measure of how accurate is the candidate, ranges from 0 to 1)
boundingBox (a rectangle detailing the bounds of the recognised item within the image dimensions)
alternatives (list of alternative foods that are visually or contextually similar to the recognised food)
croppedImage (the image that the recognition was ran on)
To fetch the full nutrition data of a detected candidate use:
public func fetchFoodItemFor(passioID: PassioNutritionAISDK.PassioID, completion: @escaping (PassioNutritionAISDK.PassioFoodItem?) -> Void)
Example of an image that produces a DetectedCandidate:

Barcode detection
The SDK can detect barcodes located on the packaging of packaged foods. The BarcodeCandidate has only two properties, the value of the barcode and it's bounding box.
To fetch the full nutritional details of a DetectedCandidate use this api passing the barcode value:
public func fetchFoodItemFor(productCode: String, completion: @escaping ((PassioNutritionAISDK.PassioFoodItem?) -> Void))
Example of an image that produces multiple BarcodeCandidates:

Product food detection
Passio uses OCR to recognise names of branded foods. The packaged food detection works for users tha point the camera of their devices to the front facing side of a packaged food. The result of that process is a PackagedFoodCandidate
that only holds two values, the packaged food code and a measure of confidence.
Use the same api as in Barcode detectionto retrieve the full nutritional data passing the packaged food code as the parameter.
Example of an image that produces a PackagedFoodCandidate:

Last updated