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

หลังจากฝึกฝนตัวเอง ที่ใช้ AutoML Vision Edge และนำไปใช้ในแอปเพื่อติดป้ายกำกับได้ รูปภาพ

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

  1. หากยังไม่ได้เพิ่ม Firebase ลงในแอป ให้ดำเนินการดังนี้ ขั้นตอนในคู่มือเริ่มต้นใช้งาน
  2. รวมไลบรารี ML Kit ไว้ใน Podfile ดังนี้
    pod 'Firebase/MLVision', '6.25.0'
    pod 'Firebase/MLVisionAutoML', '6.25.0'
    
    หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว อย่าลืมเปิด Xcode โดยใช้ .xcworkspace
  3. ในแอป ให้นำเข้า Firebase ดังนี้

    Swift

    import Firebase

    Objective-C

    @import Firebase;

1. โหลดโมเดล

ML Kit จะเรียกใช้โมเดลที่ AutoML สร้างขึ้นบนอุปกรณ์ อย่างไรก็ตาม คุณสามารถ กำหนดค่า ML Kit ให้โหลดโมเดลจากระยะไกลจาก Firebase ที่จัดเก็บข้อมูลในเครื่อง หรือทั้ง 2 อย่าง

เมื่อโฮสต์โมเดลใน Firebase คุณจะอัปเดตโมเดลได้โดยไม่ต้องเปิดตัว แอปเวอร์ชันใหม่ และคุณจะใช้ Remote Config และ A/B Testing เพื่อทำสิ่งต่อไปนี้ได้ แสดงรูปแบบต่างๆ แก่ผู้ใช้กลุ่มต่างๆ แบบไดนามิก

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

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

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

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

Swift

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

Objective-C

FIRAutoMLRemoteModel *remoteModel = [[FIRAutoMLRemoteModel 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

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

NSProgress *downloadProgress =
    [[FIRModelManager modelManager] downloadRemoteModel:remoteModel
                                             conditions:downloadConditions];

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

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

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

  1. แยกโมเดลและข้อมูลเมตาของโมเดลจากชุดไฟล์ ZIP ที่คุณดาวน์โหลด จากคอนโซล Firebase ลงในโฟลเดอร์:
    your_model_directory
      |____dict.txt
      |____manifest.json
      |____model.tflite
    
    ทั้ง 3 ไฟล์ต้องอยู่ในโฟลเดอร์เดียวกัน เราขอแนะนำให้คุณใช้ไฟล์เป็น ที่คุณได้ดาวน์โหลดไว้โดยไม่มีการแก้ไข (รวมถึงชื่อไฟล์)
  2. คัดลอกโฟลเดอร์ไปยังโปรเจ็กต์ Xcode แล้วเลือก โปรดสร้างการอ้างอิงโฟลเดอร์เมื่อคุณสร้าง ไฟล์โมเดลและข้อมูลเมตา จะรวมอยู่ใน App Bundle และพร้อมใช้งานสำหรับ ML Kit
  3. สร้างออบเจ็กต์ AutoMLLocalModel โดยระบุเส้นทางไปยังไฟล์ Manifest ของโมเดล ไฟล์:

    Swift

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

    Objective-C

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

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

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

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

Swift

let options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

Objective-C

FIRVisionOnDeviceAutoMLImageLabelerOptions *options =
    [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = 0;  // Evaluate your model in the Firebase console
                                  // to determine an appropriate value.
FIRVisionImageLabeler *labeler =
    [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];

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

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

Swift

var options: VisionOnDeviceAutoMLImageLabelerOptions?
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
  options = VisionOnDeviceAutoMLImageLabelerOptions(remoteModel: remoteModel)
} else {
  options = VisionOnDeviceAutoMLImageLabelerOptions(localModel: localModel)
}
options.confidenceThreshold = 0  // Evaluate your model in the Firebase console
                                 // to determine an appropriate value.
let labeler = Vision.vision().onDeviceAutoMLImageLabeler(options: options)

Objective-C

VisionOnDeviceAutoMLImageLabelerOptions *options;
if ([[FIRModelManager modelManager] isModelDownloaded:remoteModel]) {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
  options = [[FIRVisionOnDeviceAutoMLImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = 0.0f;  // Evaluate your model in the Firebase console
                                     // to determine an appropriate value.
FIRVisionImageLabeler *labeler = [[FIRVision vision] onDeviceAutoMLImageLabelerWithOptions:options];

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

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

Swift

NotificationCenter.default.addObserver(
    forName: .firebaseMLModelDownloadDidSucceed,
    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: .firebaseMLModelDownloadDidFail,
    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:FIRModelDownloadDidSucceedNotification
                object:nil
                 queue:nil
            usingBlock:^(NSNotification *_Nonnull note) {
              if (weakSelf == nil | note.userInfo == nil) {
                return;
              }
              __strong typeof(self) strongSelf = weakSelf;

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

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

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

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

จากนั้นสร้างออบเจ็กต์ VisionImage โดยใช้รูปภาพแต่ละรูปที่ต้องการติดป้ายกำกับ ตัวเลือกที่อธิบายในส่วนนี้ และส่งไปยัง VisionImageLabeler (อธิบายในส่วนถัดไป)

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

วิธีใช้ UIImage

  1. หากจำเป็น ให้หมุนรูปภาพเพื่อให้imageOrientation พร็อพเพอร์ตี้คือ .up
  2. สร้างออบเจ็กต์ VisionImage โดยใช้การหมุนที่ถูกต้อง UIImage ไม่ระบุข้อมูลเมตาการหมุนเวียน ซึ่งเป็นค่าเริ่มต้น ต้องใช้ค่า .topLeft

    Swift

    let image = VisionImage(image: uiImage)

    Objective-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithImage:uiImage];

วิธีใช้ CMSampleBufferRef

  1. สร้างออบเจ็กต์ VisionImageMetadata ที่ระบุ การวางแนวของข้อมูลภาพที่มีอยู่ใน บัฟเฟอร์ CMSampleBufferRef

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

    Swift

    func imageOrientation(
        deviceOrientation: UIDeviceOrientation,
        cameraPosition: AVCaptureDevice.Position
        ) -> VisionDetectorImageOrientation {
        switch deviceOrientation {
        case .portrait:
            return cameraPosition == .front ? .leftTop : .rightTop
        case .landscapeLeft:
            return cameraPosition == .front ? .bottomLeft : .topLeft
        case .portraitUpsideDown:
            return cameraPosition == .front ? .rightBottom : .leftBottom
        case .landscapeRight:
            return cameraPosition == .front ? .topRight : .bottomRight
        case .faceDown, .faceUp, .unknown:
            return .leftTop
        }
    }

    Objective-C

    - (FIRVisionDetectorImageOrientation)
        imageOrientationFromDeviceOrientation:(UIDeviceOrientation)deviceOrientation
                               cameraPosition:(AVCaptureDevicePosition)cameraPosition {
      switch (deviceOrientation) {
        case UIDeviceOrientationPortrait:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationLeftTop;
          } else {
            return FIRVisionDetectorImageOrientationRightTop;
          }
        case UIDeviceOrientationLandscapeLeft:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationBottomLeft;
          } else {
            return FIRVisionDetectorImageOrientationTopLeft;
          }
        case UIDeviceOrientationPortraitUpsideDown:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationRightBottom;
          } else {
            return FIRVisionDetectorImageOrientationLeftBottom;
          }
        case UIDeviceOrientationLandscapeRight:
          if (cameraPosition == AVCaptureDevicePositionFront) {
            return FIRVisionDetectorImageOrientationTopRight;
          } else {
            return FIRVisionDetectorImageOrientationBottomRight;
          }
        default:
          return FIRVisionDetectorImageOrientationTopLeft;
      }
    }

    จากนั้นสร้างออบเจ็กต์ข้อมูลเมตา ดังนี้

    Swift

    let cameraPosition = AVCaptureDevice.Position.back  // Set to the capture device you used.
    let metadata = VisionImageMetadata()
    metadata.orientation = imageOrientation(
        deviceOrientation: UIDevice.current.orientation,
        cameraPosition: cameraPosition
    )

    Objective-C

    FIRVisionImageMetadata *metadata = [[FIRVisionImageMetadata alloc] init];
    AVCaptureDevicePosition cameraPosition =
        AVCaptureDevicePositionBack;  // Set to the capture device you used.
    metadata.orientation =
        [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation
                                     cameraPosition:cameraPosition];
  2. สร้างออบเจ็กต์ VisionImage โดยใช้ ออบเจ็กต์ CMSampleBufferRef และข้อมูลเมตาการหมุน:

    Swift

    let image = VisionImage(buffer: sampleBuffer)
    image.metadata = metadata

    Objective-C

    FIRVisionImage *image = [[FIRVisionImage alloc] initWithBuffer:sampleBuffer];
    image.metadata = metadata;

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

หากต้องการติดป้ายกำกับวัตถุในรูปภาพ ให้ส่งออบเจ็กต์ VisionImage ไปยัง เมธอด process() ของ VisionImageLabeler:

Swift

labeler.process(image) { labels, error in
    guard error == nil, let labels = labels else { return }

    // Task succeeded.
    // ...
}

Objective-C

[labeler
    processImage:image
      completion:^(NSArray<FIRVisionImageLabel *> *_Nullable labels, NSError *_Nullable error) {
        if (error != nil || labels == nil) {
          return;
        }

        // Task succeeded.
        // ...
      }];

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

เช่น

Swift

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

Objective-C

for (FIRVisionImageLabel *label in labels) {
  NSString *labelText = label.text;
  NSNumber *confidence = label.confidence;
}

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

  • กดคันเร่งไปยังตัวตรวจจับ หากเฟรมวิดีโอใหม่กลายเป็น วางเฟรมได้ในขณะที่ตัวตรวจจับกำลังทำงานอยู่
  • หากคุณกำลังใช้เอาต์พุตของเครื่องมือตรวจสอบเพื่อวางซ้อนกราฟิก รูปภาพอินพุต รับผลลัพธ์จาก ML Kit ก่อน จากนั้นจึงแสดงผลรูปภาพ ซ้อนทับในขั้นตอนเดียว การทำเช่นนี้จะช่วยให้แสดงผลบนพื้นผิวจอแสดงผล เพียงครั้งเดียวสำหรับเฟรมอินพุตแต่ละเฟรม โปรดดู previewOverlayView และ FIRDetectionOverlayView ในตัวอย่างแอป Showcase