تصنيف الصور باستخدام نموذج مدرَّب على تكنولوجيا تعلُّم الآلة على نظام التشغيل iOS
بعد تدريب نموذجك الخاص باستخدام AutoML Vision Edge، يمكنك استخدامه في تطبيقك لتصنيف الصور.
هناك طريقتان لدمج النماذج المدرَّبة من AutoML Vision Edge. يمكنك تجميع النموذج عن طريق نسخ ملفات النموذج إلى مشروع Xcode لديك، أو يمكنك تنزيله ديناميكيًا من Firebase.
خيارات تجميع النموذج | |
---|---|
مجمعة في تطبيقك |
|
مستضافة باستخدام Firebase |
|
التجربة الآن
- جرّب نموذج التطبيق للاطّلاع على مثال لاستخدام واجهة برمجة التطبيقات هذه.
قبل البدء
1- تضمين مكتبات ML Kit في ملف Podfile:لدمج نموذج مع تطبيقك:
pod 'GoogleMLKit/ImageLabelingAutoML'لتنزيل نموذج من Firebase بشكل ديناميكي، أضِف القاعدة التابعة
LinkFirebase
:
pod 'GoogleMLKit/ImageLabelingAutoML' pod 'GoogleMLKit/LinkFirebase'2. بعد تثبيت مجموعات Pod الخاصة بمشروعك أو تحديثها، افتح مشروع Xcode باستخدام
.xcworkspace
الرمز الخاص به. إنّ حزمة MLK متوافقة مع الإصدار 13.2.1 من Xcode
أو الإصدارات الأحدث.
3- إذا أردت تنزيل نموذج، تأكّد من
إضافة Firebase إلى مشروع iOS الخاص بك
إذا لم يسبق لك ذلك، لأنّ هذا الإجراء ليس مطلوبًا عند تجميع
النموذج.
1- تحميل النموذج
ضبط مصدر نموذج محلي
لتجميع النموذج مع تطبيقك:1. استخرِج النموذج وبياناته الوصفية من أرشيف ZIP الذي نزّلته من "وحدة تحكّم Firebase" إلى مجلد:
your_model_directory |____dict.txt |____manifest.json |____model.tfliteيجب أن تكون الملفات الثلاثة في المجلد نفسه. ننصحك باستخدام الملفات أثناء تنزيلها، بدون أي تعديل (بما في ذلك أسماء الملفات).
2- انسخ المجلد إلى مشروع Xcode، مع الحرص على اختيار إنشاء مراجع للمجلدات عند إجراء ذلك. سيتم تضمين ملف النموذج والبيانات الوصفية في حزمة التطبيق، كما سيتم إتاحته في حزمة ML Kit.
3- أنشئ كائن
AutoMLImageLabelerLocalModel
مع تحديد المسار إلى ملف بيان النموذج:
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
من أحدها.
إذا كان لديك نموذج مجمّع محليًا فقط، ما عليك سوى إنشاء تصنيف من عنصر 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];
إذا كان لديك نموذج تتم استضافته عن بُعد، يجب عليك إيقاف الوظائف ذات الصلة بالنموذج، على سبيل المثال، اللون الرمادي أو إخفاء جزء من واجهة المستخدم، إلى أن تتأكد من تنزيل النموذج.
يمكنك معرفة حالة تنزيل النموذج عن طريق إرفاق مراقبين بـ "مركز الإشعارات" التلقائي. احرِص على استخدام إشارة ضعيفة إلى 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; }
نصائح لتحسين الأداء في الوقت الفعلي
إذا أردت تصنيف الصور في تطبيق في الوقت الفعلي، اتّبِع هذه الإرشادات لتحقيق أفضل عدد من اللقطات:
- لمعالجة إطارات الفيديو، استخدِم واجهة برمجة التطبيقات المتزامنة
results(in:)
لأداة الرصد. ويمكنك استدعاء هذه الطريقة من دالةcaptureOutput(_, didOutput:from:)
فيAVCaptureVideoDataOutputSampleBufferDelegate
للحصول على نتائج بشكل متزامن من إطار الفيديو المحدّد. عليك مواصلة استخدامalwaysDiscardsLateVideoFrames
فيAVCaptureVideoDataOutput
كـtrue
لتضييق نطاق الطلبات المتعلّقة بأداة الرصد. وفي حال توفُّر إطار فيديو جديد أثناء تشغيل أداة الرصد، سيتم تجاهله. - إذا كنت تستخدم إخراج أداة الرصد لعرض الرسومات على الصورة المُدخَلة، احصل أولاً على النتيجة من أدوات تعلّم الآلة، ثم اعرض الصورة والتراكب في خطوة واحدة. ومن خلال إجراء ذلك، يتم العرض على سطح الشاشة مرة واحدة فقط لكل إطار إدخال تمت معالجته. للاطّلاع على مثال، راجِع updatePreviewOverlayViewWithLastFrame في نموذج البدء السريع حول حزمة ML Kit.