يمكنك استخدام أدوات تعلّم الآلة للتعرّف على الكيانات في صورة وتصنيفها. تتوافق واجهة برمجة التطبيقات هذه مع مجموعة كبيرة من نماذج تصنيف الصور المخصّصة. يُرجى الرجوع إلى النماذج المخصّصة باستخدام حزمة تعلّم الآلة للحصول على إرشادات حول متطلبات توافق النماذج، ومعرفة كيفية العثور على نماذج مدرّبة مسبقًا، وكيفية تدريب نماذجك الخاصة.
هناك طريقتان لدمج النموذج المخصّص. يمكنك تجميع النموذج من خلال وضعه في مجلد مواد العرض في التطبيق أو تنزيله ديناميكيًا من Firebase. يقارن الجدول التالي بين الخيارين.
النموذج المجمّع | النموذج المستضاف |
---|---|
النموذج هو جزء من حزمة APK لتطبيقك، ما يزيد من حجمه. | النموذج ليس جزءًا من APK. وتتم استضافته عن طريق تحميله إلى أداة تعلُّم الآلة من Firebase. |
يتوفر الطراز على الفور، حتى عندما يكون جهاز Android غير متصل بالإنترنت. | يتم تنزيل النموذج عند الطلب |
عدم الحاجة إلى مشروع Firebase | يجب توفّر مشروع في Firebase. |
يجب إعادة نشر تطبيقك لتحديث النموذج. | إرسال تحديثات النموذج بدون إعادة نشر تطبيقك |
بدون اختبار A/B مدمج | إجراء اختبار A/B بسهولة باستخدام ميزة الإعداد عن بُعد في Firebase |
تجربة السمات والبيانات
- للاطّلاع على مثال حول استخدام النموذج المستضاف، يمكنك الاطّلاع على تطبيق vision سريع التشغيل للاطّلاع على مثال عن استخدام النموذج المجمّع وتطبيق التشغيل السريع automl للاطّلاع على مثال حول استخدام النموذج المستضاف.
قبل البدء
تضمين مكتبات ML Kit في ملف Podfile:
لتجميع نموذج مع تطبيقك:
pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0'
لتنزيل نموذج بشكل ديناميكي من Firebase، أضِف التبعية
LinkFirebase
:pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0' pod 'GoogleMLKit/LinkFirebase', '3.2.0'
بعد تثبيت أو تحديث مجموعات اللوحات لمشروعك، افتح مشروع Xcode باستخدام
.xcworkspace
الخاص به. تتوفّر هذه الأداة في الإصدار 13.2.1 من Xcode أو الإصدارات الأحدث.إذا أردت تنزيل نموذج، تأكّد من إضافة Firebase إلى مشروع iOS، إذا لم يسبق لك إجراء ذلك، فهذا ليس مطلوبًا عند تجميع النموذج.
1- تحميل النموذج
ضبط مصدر نموذج محلي
لتجميع النموذج مع تطبيقك:
انسخ ملف النموذج (الذي ينتهي عادةً بالأرقام
.tflite
أو.lite
) إلى مشروع Xcode الخاص بك، مع الحرص على اختيارCopy bundle resources
عند إجراء ذلك. سيتم تضمين ملف النموذج في حزمة التطبيق وسيكون متاحًا لبرنامج ML Kit.إنشاء كائن
LocalModel
، مع تحديد المسار إلى ملف النموذج:Swift
let localModel = LocalModel(path: localModelFilePath)
Objective-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
ضبط مصدر نموذج مستضاف على Firebase
لاستخدام النموذج الذي تتم استضافته عن بُعد، أنشِئ عنصر RemoteModel
مع تحديد الاسم الذي حدّدته للنموذج عند نشره:
Swift
let firebaseModelSource = FirebaseModelSource( name: "your_remote_model") // The name you assigned in // the Firebase console. let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)
Objective-C
MLKFirebaseModelSource *firebaseModelSource = [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console. 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] downloadModel:remoteModel conditions:downloadConditions];
تبدأ العديد من التطبيقات مهمّة التنزيل في رمز الإعداد الخاص بها، ويمكنك تنفيذ ذلك في أي وقت قبل أن تحتاج إلى استخدام النموذج.
ضبط أداة تصنيف الصور
بعد ضبط مصادر النماذج، يمكنك إنشاء كائن ImageLabeler
من أحدها.
تتوفّر الخيارات التالية:
الخيارات | |
---|---|
confidenceThreshold
|
الحد الأدنى لدرجة الثقة للتصنيفات التي تم رصدها. وفي حال عدم ضبط هذه السياسة، سيتم استخدام أي حدّ أدنى للمصنِّف تحدِّده البيانات الوصفية للنموذج. إذا كان النموذج لا يحتوي على أي بيانات وصفية أو إذا لم تحدّد البيانات الوصفية حدًا للمصنِّف، سيتم استخدام حد أقصى تلقائي هو 0.0. |
maxResultCount
|
الحد الأقصى لعدد التصنيفات المطلوب عرضها. وفي حال ترك هذه السياسة بدون ضبط، سيتم استخدام القيمة التلقائية التي تبلغ 10. |
إذا كان لديك فقط نموذج مجمَّع محليًا، ما عليك سوى إنشاء تصنيف من
كائن LocalModel
:
Swift
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Objective-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); 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) 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.0); 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. تشغيل برنامج تصنيف الصور
لتصنيف الكائنات في صورة، مرِّر الكائن image
إلى طريقة process()
في ImageLabeler
.
بشكل غير متزامن:
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 (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*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
للحصول على نتائج متزامنة من إطار الفيديو المحدّد. الاحتفاظ بـAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
true
لتقليل المكالمات الواردة إلى جهاز الرصد. في حال توفّر إطار فيديو جديد أثناء تشغيل أداة الرصد، سيتم تجاهله. - إذا كنت تستخدم نتيجة أداة الرصد لإضافة رسومات على الصورة التي تم إدخالها، احصل أولاً على النتيجة من أدوات تعلّم الآلة، ثم اعرض الصورة والتراكب في خطوة واحدة. بإجراء ذلك، يتم عرضك على سطح الشاشة مرة واحدة فقط لكل إطار إدخال تمت معالجته. للاطّلاع على مثال، يمكن الاطّلاع على updatePreviewOverlayViewWithLastFrame في نموذج البدء السريع في ML Kit.