ติดป้ายกำกับรูปภาพด้วยโมเดลที่ฝึกด้วย AutoML บน iOS

หลังจากที่คุณฝึกโมเดลของคุณเองโดยใช้ AutoML Vision Edge ก็ใช้ในแอปเพื่อติดป้ายกำกับรูปภาพได้

การผสานรวมโมเดลที่ฝึกจาก AutoML Vision Edge ทำได้ 2 วิธี คุณสามารถ รวมโมเดลโดยคัดลอกไฟล์ของโมเดลลงในโปรเจ็กต์ Xcode ของคุณ หรือคุณ จะสามารถดาวน์โหลดแบบไดนามิกจาก Firebase

ตัวเลือกการรวมกลุ่มโมเดล
รวมกลุ่มในแอปของคุณ
  • โมเดลนี้เป็นส่วนหนึ่งของแพ็กเกจ
  • โมเดลดังกล่าวจะพร้อมใช้งานทันที แม้ว่าอุปกรณ์ iOS จะออฟไลน์อยู่
  • ไม่จำเป็นต้องมีโปรเจ็กต์ Firebase
โฮสต์กับ Firebase

ลองเลย

ก่อนเริ่มต้น

1. รวมไลบรารี ML Kit ไว้ใน Podfile:

สำหรับการรวมโมเดลกับแอป ให้ทำดังนี้ วันที่
    pod 'GoogleMLKit/ImageLabelingAutoML'
    
สำหรับการดาวน์โหลดโมเดลแบบไดนามิกจาก Firebase ให้เพิ่ม LinkFirebase การพึ่งพา:
    pod 'GoogleMLKit/ImageLabelingAutoML'
    pod 'GoogleMLKit/LinkFirebase'
    
2. หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้.xcworkspaceรหัส> Xcode รองรับ ML Kit เวอร์ชัน 13.2.1 ขึ้นไป 3. หากต้องการดาวน์โหลดโมเดล โปรดตรวจสอบว่า เพิ่ม Firebase ลงในโปรเจ็กต์ iOS หากคุณยังไม่ได้ดำเนินการ ไม่จำเป็นต้องทำขั้นตอนนี้เมื่อคุณรวมชุด โมเดล

1. โหลดโมเดล

กำหนดค่าต้นทางของโมเดลในเครื่อง

วิธีรวมโมเดลกับแอปมีดังนี้

1. แยกโมเดลและข้อมูลเมตาของโมเดลจากชุดไฟล์ ZIP ที่คุณดาวน์โหลด จากคอนโซล Firebase ลงในโฟลเดอร์ ให้ทำดังนี้
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
ทั้ง 3 ไฟล์ต้องอยู่ในโฟลเดอร์เดียวกัน เราขอแนะนำให้คุณใช้ไฟล์ ขณะที่คุณดาวน์โหลด โดยไม่ต้องแก้ไข (รวมถึงชื่อไฟล์)

2. คัดลอกโฟลเดอร์ไปยังโปรเจ็กต์ Xcode แล้วเลือก โปรดสร้างการอ้างอิงโฟลเดอร์เมื่อคุณสร้าง ไฟล์โมเดลและข้อมูลเมตา จะรวมอยู่ใน App Bundle และพร้อมใช้งานสำหรับ ML Kit

3. สร้างออบเจ็กต์ AutoMLImageLabelerLocalModel โดยระบุเส้นทางไปยัง ไฟล์ Manifest ของโมเดล:

Swift

guard let manifestPath = Bundle.main.path(
    forResource: "manifest",
    ofType: "json",
    inDirectory: "your_model_directory"
) else { return }
let localModel = AutoMLImageLabelerLocalModel(manifestPath: manifestPath)

Objective-C

NSString *manifestPath =
    [NSBundle.mainBundle pathForResource:@"manifest"
                                  ofType:@"json"
                             inDirectory:@"your_model_directory"];
MLKAutoMLImageLabelerLocalModel *localModel =
    [[MLKAutoMLImageLabelerLocalModel alloc] initWithManifestPath:manifestPath];

กำหนดค่าแหล่งที่มาของโมเดลที่โฮสต์กับ Firebase

หากต้องการใช้โมเดลที่โฮสต์จากระยะไกล ให้สร้าง AutoMLImageLabelerRemoteModel โดยระบุชื่อที่คุณกำหนดโมเดลเมื่อเผยแพร่:

Swift

let remoteModel = AutoMLImageLabelerRemoteModel(
    name: "your_remote_model"  // The name you assigned in
                               // the Firebase console.
)

Objective-C

MLKAutoMLImageLabelerRemoteModel *remoteModel =
    [[MLKAutoMLImageLabelerRemoteModel alloc]
        initWithName:@"your_remote_model"];  // The name you assigned in
                                             // the Firebase console.

จากนั้นเริ่มงานดาวน์โหลดโมเดล โดยระบุเงื่อนไขที่ ที่คุณต้องการอนุญาตให้ดาวน์โหลด หากไม่มีรุ่นนี้อยู่ในอุปกรณ์ หรือรุ่นที่ใหม่กว่า ของโมเดลพร้อมใช้งาน งานจะดาวน์โหลด จาก Firebase ได้ดังนี้

Swift

let downloadConditions = ModelDownloadConditions(
  allowsCellularAccess: true,
  allowsBackgroundDownloading: true
)

let downloadProgress = ModelManager.modelManager().download(
  remoteModel,
  conditions: downloadConditions
)

Objective-C

MLKModelDownloadConditions *downloadConditions =
    [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
                                         allowsBackgroundDownloading:YES];

NSProgress *downloadProgress =
    [[MLKModelManager modelManager] downloadModel:remoteModel
                                       conditions:downloadConditions];

แอปจำนวนมากเริ่มงานดาวน์โหลดในโค้ดเริ่มต้น แต่คุณ จากนั้นคุณจะสามารถทำได้ทุกเมื่อก่อนที่จะต้องใช้โมเดลนี้

สร้างเครื่องมือติดป้ายกำกับรูปภาพจากโมเดล

หลังจากกำหนดค่าแหล่งที่มาของโมเดลแล้ว ให้สร้างออบเจ็กต์ ImageLabeler จาก 1 ทั้งหมด

หากคุณมีเฉพาะโมเดลที่รวมภายในเครื่อง ให้สร้างผู้ติดป้ายกำกับจาก AutoMLImageLabelerLocalModel และกำหนดค่าคะแนนความเชื่อมั่น เกณฑ์ที่ต้องการกำหนด (ดูประเมินโหมดของคุณ

Swift

let options = AutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKAutoMLImageLabelerOptions *options =
    [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

หากคุณมีโมเดลที่โฮสต์จากระยะไกล คุณจะต้องตรวจสอบว่ามีการ ซึ่งดาวน์โหลดมาก่อนที่จะเรียกใช้ คุณตรวจสอบสถานะการดาวน์โหลดโมเดลได้ โดยใช้เมธอด isModelDownloaded(remoteModel:) ของตัวจัดการโมเดล

แม้ว่าคุณจะต้องยืนยันเรื่องนี้ก่อนเรียกใช้ผู้ติดป้ายกำกับเท่านั้นหากคุณ มีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมอยู่ภายใน เหมาะสมที่จะดำเนินการตรวจสอบนี้เมื่อเริ่มต้น ImageLabeler: สร้าง ผู้ติดป้ายกำกับจากโมเดลระยะไกลหากดาวน์โหลดแล้ว และจากโมเดลในเครื่อง หรือไม่เช่นนั้น

Swift

var options: AutoMLImageLabelerOptions!
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = AutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = AutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = NSNumber(value: 0.0)  // Evaluate your model in the Firebase console
                                                    // to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options: options)

Objective-C

MLKAutoMLImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[MLKAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0);  // Evaluate your model in the Firebase console
                                       // to determine an appropriate value.
MLKImageLabeler *imageLabeler =
    [MLKImageLabeler imageLabelerWithOptions:options];

หากคุณมีเฉพาะโมเดลที่โฮสต์จากระยะไกล คุณควรปิดใช้โมเดลที่เกี่ยวข้องกับ ตัวอย่างเช่น เป็นสีเทาหรือซ่อนบางส่วนของ UI จนถึง คุณยืนยันว่าดาวน์โหลดโมเดลแล้ว

คุณดูสถานะการดาวน์โหลดโมเดลได้โดยการแนบผู้สังเกตการณ์กับค่าเริ่มต้น ศูนย์การแจ้งเตือน โปรดใช้การอ้างอิงที่ไม่รัดกุมไปยัง self ในผู้สังเกตการณ์ บล็อก เนื่องจากการดาวน์โหลดอาจใช้เวลาสักครู่ และออบเจ็กต์เริ่มต้นอาจ เมื่อการดาวน์โหลดเสร็จสิ้น เช่น

Swift

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidSucceed,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel,
        model.name == "your_remote_model"
        else { return }
    // The model was downloaded and is available on the device
}

NotificationCenter.default.addObserver(
    forName: .mlkitModelDownloadDidFail,
    object: nil,
    queue: nil
) { [weak self] notification in
    guard let strongSelf = self,
        let userInfo = notification.userInfo,
        let model = userInfo[ModelDownloadUserInfoKey.remoteModel.rawValue]
            as? RemoteModel
        else { return }
    let error = userInfo[ModelDownloadUserInfoKey.error.rawValue]
    // ...
}

Objective-C

__weak typeof(self) weakSelf = self;

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              MLKRemoteModel *model = note.userInfo[MLKModelDownloadUserInfoKeyRemoteModel];
              if ([model.name isEqualToString:@"your_remote_model"]) {
                // The model was downloaded and is available on the device
              }
            }];

[NSNotificationCenter.defaultCenter
    addObserverForName:MLKModelDownloadDidFailNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

              NSError *error = note.userInfo[MLKModelDownloadUserInfoKeyError];
            }];

2. เตรียมรูปภาพอินพุต

สร้างออบเจ็กต์ VisionImage โดยใช้ UIImage หรือ CMSampleBuffer

หากคุณใช้ UIImage ให้ทำตามขั้นตอนต่อไปนี้

  • สร้างออบเจ็กต์ VisionImage ด้วย UIImage ตรวจสอบว่าได้ระบุ .orientation ที่ถูกต้อง

    Swift

    let image = VisionImage(image: UIImage)
    visionImage.orientation = image.imageOrientation

    Objective-C

    MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image];
    visionImage.orientation = image.imageOrientation;

หากคุณใช้ CMSampleBuffer ให้ทำตามขั้นตอนต่อไปนี้

  • ระบุการวางแนวของข้อมูลภาพที่มีอยู่ใน CMSampleBuffer

    วิธีดูการวางแนวรูปภาพ

    Swift

    func imageOrientation(
      deviceOrientation: UIDeviceOrientation,
      cameraPosition: AVCaptureDevice.Position
    ) -> UIImage.Orientation {
      switch deviceOrientation {
      case .portrait:
        return cameraPosition == .front ? .leftMirrored : .right
      case .landscapeLeft:
        return cameraPosition == .front ? .downMirrored : .up
      case .portraitUpsideDown:
        return cameraPosition == .front ? .rightMirrored : .left
      case .landscapeRight:
        return cameraPosition == .front ? .upMirrored : .down
      case .faceDown, .faceUp, .unknown:
        return .up
      }
    }
          

    Objective-C

    - (UIImageOrientation)
      imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                             cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored
                                                                : UIImageOrientationRight;
    
        case UIDeviceOrientationLandscapeLeft:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored
                                                                : UIImageOrientationUp;
        case UIDeviceOrientationPortraitUpsideDown:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored
                                                                : UIImageOrientationLeft;
        case UIDeviceOrientationLandscapeRight:
          return cameraPosition == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored
                                                                : UIImageOrientationDown;
        case UIDeviceOrientationUnknown:
        case UIDeviceOrientationFaceUp:
        case UIDeviceOrientationFaceDown:
          return UIImageOrientationUp;
      }
    }
          
  • สร้างออบเจ็กต์ VisionImage โดยใช้ CMSampleBuffer วัตถุและการวางแนว:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.orientation = imageOrientation(
      deviceOrientation: UIDevice.current.orientation,
      cameraPosition: cameraPosition)

    Objective-C

     MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer];
     image.orientation =
       [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                    cameraPosition:cameraPosition];

3. เรียกใช้เครื่องมือติดป้ายกำกับรูปภาพ

ไม่พร้อมกัน:

Swift

imageLabeler.process(image) { labels, error in
    guard error == nil, let labels = labels, !labels.isEmpty else {
        // Handle the error.
        return
    }
    // Show results.
}

Objective-C

[imageLabeler
    processImage:image
      completion:^(NSArray *_Nullable labels,
                   NSError *_Nullable error) {
        if (labels.count == 0) {
            // Handle the error.
            return;
        }
        // Show results.
     }];

พร้อมกัน:

Swift

var labels: [ImageLabel]
do {
    labels = try imageLabeler.results(in: image)
} catch let error {
    // Handle the error.
    return
}
// Show results.

Objective-C

NSError *error;
NSArray *labels =
    [imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.

4. รับข้อมูลเกี่ยวกับออบเจ็กต์ที่ติดป้ายกำกับ

หากการติดป้ายกำกับรูปภาพสำเร็จ จะแสดงผลอาร์เรย์ของ ImageLabel ImageLabel แต่ละรายการแสดงถึงสิ่งที่ ติดป้ายกำกับในรูปภาพ คุณสามารถดูคำอธิบายข้อความของแต่ละป้ายกำกับ (ถ้ามี ข้อมูลเมตาของไฟล์โมเดล TensorFlow Lite) คะแนนความเชื่อมั่น และดัชนี เช่น

Swift

for label in labels {
  let labelText = label.text
  let confidence = label.confidence
  let index = label.index
}

Objective-C

for (MLKImageLabel *label in labels) {
  NSString *labelText = label.text;
  float confidence = label.confidence;
  NSInteger index = label.index;
}

เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์

หากต้องการติดป้ายกำกับรูปภาพในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามดังนี้ เพื่อให้ได้อัตราเฟรมที่ดีที่สุด

  • สำหรับการประมวลผลเฟรมวิดีโอ ให้ใช้ API แบบซิงโครนัสของ results(in:) ในตัวตรวจจับ โทร เมธอดนี้จาก ของ AVCaptureVideoDataOutputSampleBufferDelegate captureOutput(_, didOutput:from:) เพื่อให้ได้ผลลัพธ์จากวิดีโอที่ระบุแบบพร้อมกัน เฟรม เก็บ ของ AVCaptureVideoDataOutput alwaysDiscardsLateVideoFrames เป็น true เพื่อควบคุมการโทรหาตัวตรวจจับ หาก เฟรมวิดีโอจะพร้อมใช้งานขณะที่ตัวตรวจจับทำงานอยู่ เฟรมนั้นจะหายไป
  • หากคุณใช้เอาต์พุตของเครื่องมือตรวจจับเพื่อวางซ้อนกราฟิก รูปภาพอินพุต รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพ ซ้อนทับในขั้นตอนเดียว การดำเนินการดังกล่าวจะแสดงบนพื้นผิวจอแสดงผล เพียงครั้งเดียวสำหรับแต่ละเฟรมอินพุตที่ประมวลผลแล้ว ดู updatePreviewOverlayViewWithLastFrame ในตัวอย่างการเริ่มต้นอย่างรวดเร็วใน ML Kit