หลังจากฝึกโมเดลของคุณเองโดยใช้ AutoML Vision Edge แล้ว คุณจะใช้โมเดลดังกล่าวในแอปเพื่อติดป้ายกำกับรูปภาพได้
การผสานรวมโมเดลที่ฝึกจาก AutoML Vision Edge ทำได้ 2 วิธี คุณจะรวมโมเดลได้โดยคัดลอกไฟล์ของโมเดลลงในโปรเจ็กต์ Xcode หรือจะดาวน์โหลดไฟล์แบบไดนามิกจาก Firebase ก็ได้
ตัวเลือกการรวมกลุ่มโมเดล | |
---|---|
รวมกลุ่มในแอปของคุณ |
|
โฮสต์กับ Firebase |
|
ก่อนเริ่มต้น
รวมไลบรารี ML Kit ไว้ใน Podfile ดังนี้
สำหรับการรวมโมเดลกับแอป ให้ทำดังนี้
pod 'GoogleMLKit/ImageLabelingCustom'
ในการดาวน์โหลดโมเดลแบบไดนามิกจาก Firebase ให้เพิ่มการอ้างอิง
LinkFirebase
ดังนี้pod 'GoogleMLKit/ImageLabelingCustom' pod 'GoogleMLKit/LinkFirebase'
หลังจากติดตั้งหรืออัปเดตพ็อดของโปรเจ็กต์แล้ว ให้เปิดโปรเจ็กต์ Xcode โดยใช้
.xcworkspace
ทั้งนี้ ML Kit รองรับ Xcode เวอร์ชัน 12.2 ขึ้นไปหากต้องการดาวน์โหลดโมเดล ให้ตรวจสอบว่า เพิ่ม Firebase ลงในโปรเจ็กต์ Android หากยังไม่ได้ดาวน์โหลด ซึ่งไม่จำเป็นต้องดำเนินการเมื่อรวมโมเดล
1. โหลดโมเดล
กำหนดค่าต้นทางของโมเดลในเครื่อง
วิธีการรวมโมเดลกับแอปมีดังนี้
แยกโมเดลและข้อมูลเมตาจากชุดไฟล์ Zip ที่คุณดาวน์โหลดจากคอนโซล Firebase ลงในโฟลเดอร์ โดยทำดังนี้
your_model_directory |____dict.txt |____manifest.json |____model.tflite
ทั้ง 3 ไฟล์ต้องอยู่ในโฟลเดอร์เดียวกัน เราขอแนะนำให้คุณใช้ไฟล์ตามที่คุณดาวน์โหลดมาโดยไม่ต้องแก้ไข (รวมถึงชื่อไฟล์)
คัดลอกโฟลเดอร์ไปยังโปรเจ็กต์ Xcode และอย่าลืมเลือกสร้างการอ้างอิงโฟลเดอร์ เมื่อคัดลอกแล้ว ไฟล์โมเดลและข้อมูลเมตา จะรวมอยู่ใน App Bundle และพร้อมใช้งานสำหรับ ML Kit
สร้างออบเจ็กต์
LocalModel
โดยระบุเส้นทางไปยังไฟล์ Manifest ของโมเดลSwift
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return true } let localModel = LocalModel(manifestPath: manifestPath)
Objective-C
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithManifestPath:manifestPath];
กำหนดค่าแหล่งที่มาของโมเดลที่โฮสต์กับ Firebase
หากต้องการใช้โมเดลที่โฮสต์จากระยะไกล ให้สร้างออบเจ็กต์ CustomRemoteModel
โดยระบุชื่อที่คุณกำหนดให้กับโมเดลเมื่อเผยแพร่
Swift
// Initialize the model source with the name you assigned in
// the Firebase console.
let remoteModelSource = FirebaseModelSource(name: "your_remote_model")
let remoteModel = CustomRemoteModel(remoteModelSource: remoteModelSource)
Objective-C
// Initialize the model source with the name you assigned in
// the Firebase console.
MLKFirebaseModelSource *firebaseModelSource =
[[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"];
MLKCustomRemoteModel *remoteModel =
[[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
จากนั้นเริ่มงานดาวน์โหลดโมเดล โดยระบุเงื่อนไขที่ต้องการอนุญาตให้ดาวน์โหลด หากโมเดลไม่ได้อยู่ในอุปกรณ์ หรือหากมีโมเดลเวอร์ชันใหม่กว่า งานจะดาวน์โหลดโมเดลแบบไม่พร้อมกันจาก 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] downloadRemoteModel:remoteModel
conditions:downloadConditions];
แอปจำนวนมากเริ่มงานดาวน์โหลดในโค้ดเริ่มต้น แต่คุณทำได้ทุกเมื่อก่อนที่จะต้องใช้โมเดลดังกล่าว
สร้างเครื่องมือติดป้ายกำกับรูปภาพจากโมเดล
หลังจากที่กำหนดค่าแหล่งที่มาของโมเดลแล้ว ให้สร้างออบเจ็กต์ ImageLabeler
จากหนึ่งในแหล่งที่มาของโมเดล
หากคุณมีเฉพาะโมเดลที่รวมไว้ในเครื่องเดียวกัน ก็เพียงแค่สร้างผู้ติดป้ายกำกับจากออบเจ็กต์ LocalModel
แล้วกำหนดค่าเกณฑ์คะแนนความเชื่อมั่นที่ต้องการ (ดูประเมินโมเดลของคุณ)
Swift
let options = CustomImageLabelerOptions(localModel: localModel)
options.confidenceThreshold = NSNumber(value: 0.0) // Evaluate your model in the Cloud console
// to determine an appropriate value.
let imageLabeler = ImageLabeler.imageLabeler(options)
Objective-C
CustomImageLabelerOptions *options =
[[CustomImageLabelerOptions alloc] initWithLocalModel:localModel];
options.confidenceThreshold = @(0.0f); // Evaluate your model in the Cloud console
// to determine an appropriate value.
MLKImageLabeler *imageLabeler =
[MLKImageLabeler imageLabelerWithOptions:options];
หากมีโมเดลที่โฮสต์จากระยะไกล คุณจะต้องตรวจสอบว่ามีการดาวน์โหลดโมเดลแล้วก่อนที่จะเรียกใช้ คุณตรวจสอบสถานะของงานดาวน์โหลดโมเดลได้โดยใช้เมธอด isModelDownloaded(remoteModel:)
ของตัวจัดการโมเดล
แม้คุณจะต้องยืนยันเรื่องนี้ก่อนเรียกใช้ผู้ติดป้ายกำกับเท่านั้น แต่หากคุณมีทั้งโมเดลที่โฮสต์จากระยะไกลและโมเดลที่รวมภายในเครื่อง ก็อาจทำให้ดำเนินการตรวจสอบนี้เมื่อเริ่มต้น ImageLabeler
ได้ นั่นคือ สร้างผู้ติดป้ายกำกับจากโมเดลระยะไกลหากดาวน์โหลดมาแล้ว และจากโมเดลในเครื่องหากใช้จากโมเดลในเครื่อง
Swift
var options: CustomImageLabelerOptions
if (ModelManager.modelManager().isModelDownloaded(remoteModel)) {
options = CustomImageLabelerOptions(remoteModel: remoteModel)
} else {
options = CustomImageLabelerOptions(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
MLKCustomImageLabelerOptions *options;
if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) {
options = [[MLKCustomImageLabelerOptions alloc] initWithRemoteModel:remoteModel];
} else {
options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel];
}
options.confidenceThreshold = @(0.0f); // Evaluate your model in the Firebase console
// to determine an appropriate value.
MLKImageLabeler *imageLabeler =
[MLKImageLabeler imageLabelerWithOptions:options];
หากคุณมีเฉพาะโมเดลที่โฮสต์จากระยะไกล คุณควรปิดใช้ฟังก์ชันที่เกี่ยวข้องกับโมเดล เช่น เป็นสีเทาหรือซ่อนบางส่วนของ UI จนกว่าจะยืนยันว่าดาวน์โหลดโมเดลแล้ว
คุณดูสถานะการดาวน์โหลดโมเดลได้โดยแนบผู้สังเกตการณ์เข้ากับศูนย์การแจ้งเตือนเริ่มต้น อย่าลืมใช้การอ้างอิงที่ไม่รัดกุมไปยัง self
ในบล็อกผู้สังเกตการณ์ เนื่องจากการดาวน์โหลดอาจใช้เวลาสักครู่ และออบเจ็กต์เริ่มต้นจะพร้อมใช้งานได้ในขณะที่การดาวน์โหลดเสร็จสิ้น ตัวอย่างเช่น
Swift
NotificationCenter.default.addObserver(
forName: .mlkitMLModelDownloadDidSucceed,
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: .mlkitMLModelDownloadDidFail,
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
หรือ CMSampleBufferRef
หากคุณใช้ 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;
หากคุณใช้ CMSampleBufferRef
ให้ทำตามขั้นตอนต่อไปนี้
-
ระบุการวางแนวของข้อมูลรูปภาพที่อยู่ในบัฟเฟอร์
CMSampleBufferRef
วิธีดูการวางแนวรูปภาพ
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 position == AVCaptureDevicePositionFront ? UIImageOrientationLeftMirrored : UIImageOrientationRight; case UIDeviceOrientationLandscapeLeft: return position == AVCaptureDevicePositionFront ? UIImageOrientationDownMirrored : UIImageOrientationUp; case UIDeviceOrientationPortraitUpsideDown: return position == AVCaptureDevicePositionFront ? UIImageOrientationRightMirrored : UIImageOrientationLeft; case UIDeviceOrientationLandscapeRight: return position == AVCaptureDevicePositionFront ? UIImageOrientationUpMirrored : UIImageOrientationDown; case UIDeviceOrientationUnknown: case UIDeviceOrientationFaceUp: case UIDeviceOrientationFaceDown: return UIImageOrientationUp; } }
- สร้างออบเจ็กต์
VisionImage
โดยใช้ออบเจ็กต์CMSampleBufferRef
และการวางแนว ดังนี้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<MLKImageLabel *> *_Nullable labels,
NSError *_Nullable error) {
if (label.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<MLKImageLabel *> *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;
}
เคล็ดลับในการปรับปรุงประสิทธิภาพแบบเรียลไทม์
หากต้องการติดป้ายกำกับรูปภาพในแอปพลิเคชันแบบเรียลไทม์ ให้ทำตามหลักเกณฑ์ต่อไปนี้เพื่อให้ได้อัตราเฟรมที่ดีที่สุด
- กดคันเร่งไปยังตัวตรวจจับ หากมีเฟรมวิดีโอใหม่ขณะที่ตัวตรวจจับทำงานอยู่ ให้วางเฟรมดังกล่าว
- หากคุณกำลังใช้เอาต์พุตของเครื่องมือตรวจจับเพื่อวางซ้อนกราฟิกบนรูปภาพอินพุต ให้รับผลลัพธ์ก่อน จากนั้นแสดงผลรูปภาพและวางซ้อนในขั้นตอนเดียว การทำเช่นนี้จะทําให้คุณแสดงผลบนพื้นผิวจอแสดงผลเพียงครั้งเดียวสําหรับเฟรมอินพุตแต่ละเฟรม โปรดดูคลาส previewOverlayView และ FIRDetectionOverlayView ในแอปตัวอย่าง Showcase