Slide 1

Slide 1 text

ML Kit for iOS developers Kajornsak Peerapathananont Agoda

Slide 2

Slide 2 text

Machine Learning

Slide 3

Slide 3 text

#FirebaseDevDay

Slide 4

Slide 4 text

Google Lens

Slide 5

Slide 5 text

Smart Reply

Slide 6

Slide 6 text

On-device Machine Learning

Slide 7

Slide 7 text

#FirebaseDevDay Doable, but hard.

Slide 8

Slide 8 text

#FirebaseDevDay

Slide 9

Slide 9 text

#FirebaseDevDay Get Image Image Classification Transform Interpret Get Result

Slide 10

Slide 10 text

#FirebaseDevDay Transform unsigned char *sourceBaseAddr = (unsigned char *)(CVPixelBufferGetBaseAddress(pixelBuffer)); int image_height; unsigned char *sourceStartAddr; if (fullHeight <= image_width) { image_height = fullHeight; sourceStartAddr = sourceBaseAddr; } else { image_height = image_width; const int marginY = ((fullHeight - image_width) / 2); sourceStartAddr = (sourceBaseAddr + (marginY * sourceRowBytes)); } const int image_channels = 4; assert(image_channels >= wanted_input_channels); tensorflow::Tensor image_tensor( tensorflow::DT_FLOAT, tensorflow::TensorShape( {1, wanted_input_height, wanted_input_width, wanted_input_channels})); auto image_tensor_mapped = image_tensor.tensor(); tensorflow::uint8 *in = sourceStartAddr; float *out = image_tensor_mapped.data(); for (int y = 0; y < wanted_input_height; ++y) { float *out_row = out + (y * wanted_input_width * wanted_input_channels); for (int x = 0; x < wanted_input_width; ++x) { const int in_x = (y * image_width) / wanted_input_width; const int in_y = (x * image_height) / wanted_input_height; tensorflow::uint8 *in_pixel = in + (in_y * image_width * image_channels) + (in_x * image_channels); float *out_pixel = out_row + (x * wanted_input_channels); for (int c = 0; c < wanted_input_channels; ++c) { out_pixel[c] = (in_pixel[c] - input_mean) / input_std; } } }

Slide 11

Slide 11 text

#FirebaseDevDay Interpret if (tf_session.get()) { std::vector outputs; tensorflow::Status run_status = tf_session->Run( {{input_layer_name, image_tensor}}, {output_layer_name}, {}, &outputs); if (!run_status.ok()) { LOG(ERROR) << "Running model failed:" << run_status; } else { tensorflow::Tensor *output = &outputs[0]; auto predictions = output->flat(); NSMutableDictionary *newValues = [NSMutableDictionary dictionary]; for (int index = 0; index < predictions.size(); index += 1) { const float predictionValue = predictions(index); if (predictionValue > 0.05f) { std::string label = labels[index % predictions.size()]; NSString *labelObject = [NSString stringWithUTF8String:label.c_str()]; NSNumber *valueObject = [NSNumber numberWithFloat:predictionValue]; [newValues setObject:valueObject forKey:labelObject]; } } dispatch_async(dispatch_get_main_queue(), ^(void) { [self setPredictionValues:newValues]; }); } }

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

#FirebaseDevDay

Slide 14

Slide 14 text

#FirebaseDevDay Real-world Common Use Cases

Slide 15

Slide 15 text

#FirebaseDevDay FIRVisionImage | VisionImage NS_SWIFT_NAME(VisionImage) @interface FIRVisionImage : NSObject @property(nonatomic, nullable) FIRVisionImageMetadata *metadata; - (instancetype)initWithImage:(UIImage *)image NS_DESIGNATED_INITIALIZER; - (instancetype)initWithBuffer:(CMSampleBufferRef)sampleBuffer NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; @end

Slide 16

Slide 16 text

Text Recognition - On-device - On-cloud

Slide 17

Slide 17 text

#FirebaseDevDay https://firebase.google.com/docs/ml-kit/recognize-text

Slide 18

Slide 18 text

#FirebaseDevDay FIRVisionText | VisionText NS_SWIFT_NAME(VisionText) @interface FIRVisionText : NSObject @property(nonatomic, readonly) NSString *text; @property(nonatomic, readonly) NSArray *blocks; - (instancetype)init NS_UNAVAILABLE; @end

Slide 19

Slide 19 text

#FirebaseDevDay On-device Usage let textRecognizer = vision.onDeviceTextRecognizer() textRecognizer.process(visionImage) { (text, error) in guard let text = text else { return } // do something with your text }

Slide 20

Slide 20 text

#FirebaseDevDay On-cloud Usage let textRecognizer = vision.cloudTextRecognize() textRecognizer.process(visionImage) { (text, error) in guard let text = text else { return } // do something with your text }

Slide 21

Slide 21 text

Image Labeling - On-device (400+ labels) - On-cloud (10,000+ labels)

Slide 22

Slide 22 text

#FirebaseDevDay https://firebase.google.com/docs/ml-kit/label-images

Slide 23

Slide 23 text

#FirebaseDevDay FIRVisionLabel | VisionLabel NS_SWIFT_NAME(VisionLabel) @interface FIRVisionLabel : NSObject @property(nonatomic, readonly) CGRect frame; @property(nonatomic, readonly) float confidence; @property(nonatomic, copy, readonly) NSString *entityID; @property(nonatomic, copy, readonly) NSString *label; @end

Slide 24

Slide 24 text

#FirebaseDevDay On-device Usage let labelDetector = vision.labelDetector() labelDetector.detect(in: visionImage) { (labels, error) in guard let error == nill, let labels = labels, !labels.isEmpty else { return } // do something with your labels }

Slide 25

Slide 25 text

#FirebaseDevDay On-cloud Usage let labelDetector = vision.cloudLabelDetector() labelDetector.detect(in: visionImage) { (labels, error) in guard let error == nill, let labels = labels, !labels.isEmpty else { return } // do something with your labels }

Slide 26

Slide 26 text

Face detection - On-device

Slide 27

Slide 27 text

#FirebaseDevDay

Slide 28

Slide 28 text

#FirebaseDevDay FIRVisionFace | VisionFace NS_SWIFT_NAME(VisionFace) @interface FIRVisionFace : NSObject @property(nonatomic, readonly) CGRect frame; @property(nonatomic, readonly) BOOL hasTrackingID; @property(nonatomic, readonly) NSInteger trackingID; @property(nonatomic, readonly) BOOL hasHeadEulerAngleY; @property(nonatomic, readonly) CGFloat headEulerAngleY; @property(nonatomic, readonly) BOOL hasHeadEulerAngleZ; @property(nonatomic, readonly) CGFloat headEulerAngleZ; @property(nonatomic, readonly) BOOL hasSmilingProbability; @property(nonatomic, readonly) CGFloat smilingProbability; @property(nonatomic, readonly) BOOL hasLeftEyeOpenProbability; @property(nonatomic, readonly) CGFloat leftEyeOpenProbability; @property(nonatomic, readonly) BOOL hasRightEyeOpenProbability; @property(nonatomic, readonly) CGFloat rightEyeOpenProbability; - (instancetype)init NS_UNAVAILABLE; - (nullable FIRVisionFaceLandmark *)landmarkOfType:(FIRFaceLandmarkType)type; #ifdef ENABLE_FACE_CONTOUR - (nullable FIRVisionFaceContour *)contourOfType:(FIRFaceContourType)type; #endif // ENABLE_FACE_CONTOUR @end

Slide 29

Slide 29 text

#FirebaseDevDay On-device Usage let faceDetector = vision.faceDetector() faceDetector.detect(in: visionImage) { (faces, error) in guard let error == nill, let faces = faces, !faces.isEmpty else { return } // do something with your faces }

Slide 30

Slide 30 text

#FirebaseDevDay Face Contour?

Slide 31

Slide 31 text

Landmark recognition - On-cloud

Slide 32

Slide 32 text

#FirebaseDevDay

Slide 33

Slide 33 text

#FirebaseDevDay FIRVisionCloudLandmark | VisionCloudLandmark NS_SWIFT_NAME(VisionCloudLandmark) @interface FIRVisionCloudLandmark : NSObject @property(nonatomic, copy, readonly, nullable) NSString *entityId; @property(nonatomic, copy, readonly, nullable) NSString *landmark; @property(nonatomic, readonly, nullable) NSNumber *confidence; @property(nonatomic, readonly) CGRect frame; @property(nonatomic, readonly, nullable) NSArray *locations; - (instancetype)init NS_UNAVAILABLE; @end

Slide 34

Slide 34 text

#FirebaseDevDay On-cloud Usage let landmarkDetector = vision.cloudLandmarkDetector() landmarkDetector.detect(in: visionImage) { (landmarks, error) in guard let error == nill, let landmarks = landmarks, !landmarks.isEmpty else { return } // do something with your landmarks }

Slide 35

Slide 35 text

Barcode scanning - On-device

Slide 36

Slide 36 text

#FirebaseDevDay https://firebase.google.com/docs/ml-kit/label-images

Slide 37

Slide 37 text

#FirebaseDevDay FIRVisionBarcode | VisionBarcode NS_SWIFT_NAME(VisionBarcode) @interface FIRVisionBarcode : NSObject @property(nonatomic, readonly) CGRect frame; @property(nonatomic, readonly, nullable) NSString *rawValue; @property(nonatomic, readonly, nullable) NSString *displayValue; @property(nonatomic, readonly) FIRVisionBarcodeFormat format; @property(nonatomic, readonly, nullable) NSArray *cornerPoints; @property(nonatomic, readonly) FIRVisionBarcodeValueType valueType; @property(nonatomic, readonly, nullable) FIRVisionBarcodeEmail *email; @property(nonatomic, readonly, nullable) FIRVisionBarcodePhone *phone; @property(nonatomic, readonly, nullable) FIRVisionBarcodeSMS *sms; @property(nonatomic, readonly, nullable) FIRVisionBarcodeURLBookmark *URL; @property(nonatomic, readonly, nullable) FIRVisionBarcodeWiFi *wifi; @property(nonatomic, readonly, nullable) FIRVisionBarcodeGeoPoint *geoPoint; @property(nonatomic, readonly, nullable) FIRVisionBarcodeContactInfo *contactInfo; @property(nonatomic, readonly, nullable) FIRVisionBarcodeCalendarEvent *calendarEvent; @property(nonatomic, readonly, nullable) FIRVisionBarcodeDriverLicense *driverLicense; - (instancetype)init NS_UNAVAILABLE; @end

Slide 38

Slide 38 text

#FirebaseDevDay FIRVisionBarcodeCalendarEvent | VisionBarcodeCalendarEvent NS_SWIFT_NAME(VisionBarcodeCalendarEvent) @interface FIRVisionBarcodeCalendarEvent : NSObject @property(nonatomic, readonly, nullable) NSString *eventDescription; @property(nonatomic, readonly, nullable) NSString *location; @property(nonatomic, readonly, nullable) NSString *organizer; @property(nonatomic, readonly, nullable) NSString *status; @property(nonatomic, readonly, nullable) NSString *summary; @property(nonatomic, readonly, nullable) NSDate *start; @property(nonatomic, readonly, nullable) NSDate *end; - (instancetype)init NS_UNAVAILABLE; @end

Slide 39

Slide 39 text

#FirebaseDevDay On-device Usage let barcodeDetector = vision.barcodeDetector() barcodeDetector.detect(in: visionImage) { (barcodes, error) in guard let error == nill, let barcodes = barcodes, !barcodes.isEmpty else { return } // do something with your barcodes }

Slide 40

Slide 40 text

Custom model - Tensorflow Lite

Slide 41

Slide 41 text

#FirebaseDevDay let conditions = ModelDownloadConditions(isWiFiRequired: true, canDownloadInBackground: true) let cloudModelSource = CloudModelSource( modelName: "my_cloud_model", enableModelUpdates: true, initialConditions: conditions, updateConditions: conditions ) let registrationSuccessful = ModelManager.modelManager().register(cloudModelSource)

Slide 42

Slide 42 text

Demo

Slide 43

Slide 43 text

Thank You! #FirebaseDevDay Helpful resources fb.com/FirebaseThailand fb.com/groups/FirebaseDevTH medium.com/FirebaseThailand Kajornsak Peerapathananont