Image Labeling on iOS

You can use the FritzVisionLabelModel to label the contents of images. Fritz provides a variety of options to configure predictions.

1. Build the FritzVisionLabelModel

To create the label model, you can either include the model in your bundle or download it over the air once the user installs your app.

Include the model in your application bundle

Add the model to your Podfile

Include Fritz/VisionLabelModel in your Podfile. This will include the model file in your app bundle.

pod 'Fritz/VisionLabelModel'

Make sure to install the recent addition.

pod install

Define FritzVisionLabelModel

Define the instance of the FritzVisionLabelModel in your code. There should only be one instance that is reused for each prediction.

import Fritz

let labelModel = FritzVisionLabelModel()
@import Fritz;

FritzVisionLabelModel *labelModel = [[FritzVisionLabelModel alloc] initWithOptionalModel:nil];

Download the model over the air

Add FritzVision to your Podfile

Include Fritz/Vision in your Podfile.

pod 'Fritz/Vision'

Make sure to run a pod install with the latest changes.

pod install

Download Model

import Fritz

var labelModel: FritzVisionLabelModel?

FritzVisionLabelModel.fetchModel { model, error in
   guard let downloadedModel = model, error == nil else { return }

   labelModel = downloadedModel
}
@import Fritz;

[FritzVisionLabelModel fetchModelWithCompletionHandler:^(FritzVisionLabelModel * _Nullable model, NSError * _Nullable error) {
    // Use downloaded label model
}];

2. Create FritzVisionImage

FritzImage supports different image formats.

  • Using a CMSampleBuffer

    If you are using a CMSampleBuffer from the built-in camera, first create the FritzImage instance:

    let image = FritzVisionImage(buffer: sampleBuffer)
    
    FritzVisionImage *visionImage = [[FritzVisionImage alloc] initWithBuffer: sampleBuffer];
    // or
    FritzVisionImage *visionImage = [[FritzVisionImage alloc] initWithImage: uiImage];
    

    The image orientation data needs to be properly set for predictions to work. Use FritzImageMetadata to customize orientation for an image. By default, if you specify FritzVisionImageMetadata the orientation will be .right:

    image.metadata = FritzVisionImageMetadata()
    image.metadata?.orientation = .left
    
    // Add metdata
    visionImage.metadata = [FritzVisionImageMetadata new];
    visionImage.metadata.orientation = FritzImageOrientationLeft;
    

    Note

    Data passed in from the camera will generally need the orientation set. When using a CMSampleBuffer to create a FritzImage the orientation will change depending on which camera and device orientation you are using.

    When using the back camera in the portrait Device Orientation, the orientation should be .right (the default if you specify FritzVisionImageMetadata on the image). When using the front facing camera in portrait Device Orientation, the orientation should be .left.

    You can initialize the FritzImageOrientation with the AVCaptureConnection to infer orientation (if the Device Orientation is portrait):

    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        ...
        image.metadata = FritzVisionImageMetadata()
        image.metadata?.orientation = FritzImageOrientation(connection)
        ...
    }
    
  • Using a UIImage

    If you are using a UIImage, create the FritzVision instance:

    let image = FritzVisionImage(image: uiImage)
    

    The image orientation data needs to be properly set for predictions to work. Use FritzImageMetadata to customize orientation for an image:

    image.metadata = FritzVisionImageMetadata()
    image.metadata?.orientation = .right
    

    Note

    UIImage can have associated UIImageOrientation data (for example when capturing a photo from the camera). To make sure the model is correctly handling the orientation data, initialize the FritzImageOrientation with the image’s image orientation:

    image.metadata?.orientation = FritzImageOrientation(image.imageOrientation)
    

3. Run image labeling

Run Image Labeling Model

Use the labelModel instance you created earlier to run predictions:

labelModel.predict(image) { results, error in
  guard error == nil, let labels = result else { return }

  // Code to work with labels here!
}
FritzVisionLabelModelOptions* options = [FritzVisionLabelModelOptions new];
[labelModel predictWithImage:visionImage options:options completion:^(NSArray<FritzVisionLabel* > * _Nullable result, NSError *error) {

  // Code to work with labels here!
}];

Configure Label Prediction

Before running image labeling, you can configure the prediction with a FritzVisionLabelModelOptions object.

Settings
imageCropAndScaleOption

.scaleFit (default)

Crop and Scale option for how to resize and crop the image for the model

threshold

0.6 (default)

Confidence threshold for prediction results in the range of [0, 1].

numResults

15 (default)

Maxiumum number of results to return from prediction.

For example, to build a more lenient FritzVisionLabelModelOptions object:

let options = FritzVisionLabelModelOptions()
options.threshold = 0.3
options.numResults = 2

labelModel.predict(image, options:options) { results, error in

}
FritzVisionLabelModelOptions* options = [FritzVisionLabelModelOptions new];
options.threshold = 0.3;
options.numResults = 2;

[labelModel predictWithImage:image options:options completion:^(NSArray<FritzVisionLabel* > * _Nullable result, NSError *error) {
  // Code to work with labels here!
}];

4. Get labels in image

Once you have an array of FritzVisionLabel you can use them to access the image classifications.

 // Created from model prediction.
let labels: [FritzVisionLabel]

// Print highest confidence result
print(labels[0].label)
print(labels[0].confidence)
NSArray<FritzVisionLabel*> * labels;

// Access highest confidence result
results[0].label;
results[0].confidence;