عند تمرير صورة إلى أدوات تعلّم الآلة، يرصد ما يصل إلى خمسة عناصر في الصورة، بالإضافة إلى موضع كل عنصر في الصورة. عند رصد الكائنات في الفيديوهات المضمّنة، يكون لكل عنصر معرّف فريد يمكنك استخدامه لتتبُّع العنصر من إطار إلى آخر.
يمكنك استخدام نموذج تصنيف مخصّص للصور لتصنيف العناصر التي يتم رصدها. يُرجى الرجوع إلى النماذج المخصّصة باستخدام حزمة تعلّم الآلة للحصول على إرشادات حول متطلبات توافق النماذج، وأماكن العثور على نماذج مدرّبة مسبقًا، وكيفية تدريب نماذجك الخاصة.
هناك طريقتان لدمج النموذج المخصّص. يمكنك تجميع النموذج من خلال وضعه في مجلد مواد العرض في التطبيق أو تنزيله ديناميكيًا من Firebase. يقارن الجدول التالي بين الخيارين.
النموذج المجمّع | النموذج المستضاف |
---|---|
يُعد النموذج جزءًا من ملف .ipa لتطبيقك، ما
يؤدي إلى زيادة حجمه. |
النموذج ليس جزءًا من ملف .ipa لتطبيقك. وتتم استضافته عن طريق تحميله إلى ميزة تعلُّم الآلة من Firebase. |
يتوفر الطراز على الفور، حتى عندما يكون جهاز Android غير متصل بالإنترنت. | يتم تنزيل النموذج عند الطلب |
عدم الحاجة إلى مشروع Firebase | يجب توفّر مشروع في Firebase. |
يجب إعادة نشر تطبيقك لتحديث النموذج. | إرسال تحديثات النموذج بدون إعادة نشر تطبيقك |
بدون اختبار A/B مدمج | إجراء اختبار A/B بسهولة باستخدام ميزة الإعداد عن بُعد في Firebase |
تجربة السمات والبيانات
- للاطّلاع على مثال حول استخدام النموذج المستضاف، يمكنك الاطّلاع على تطبيق vision سريع التشغيل للاطّلاع على مثال عن استخدام النموذج المجمّع وتطبيق التشغيل السريع automl للاطّلاع على مثال حول استخدام النموذج المستضاف.
- يمكنك الاطّلاع على تطبيق واجهة عرض التصميم المتعدد الأبعاد للتعرّف على عملية التنفيذ الشاملة لواجهة برمجة التطبيقات هذه.
قبل البدء
تضمين مكتبات ML Kit في ملف Podfile:
لتجميع نموذج مع تطبيقك:
pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
لتنزيل نموذج بشكل ديناميكي من Firebase، أضِف التبعية
LinkFirebase
:pod 'GoogleMLKit/ObjectDetectionCustom', '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
لاستخدام النموذج الذي تتم استضافته عن بُعد، أنشِئ كائن CustomRemoteModel
مع تحديد الاسم الذي تم تخصيص النموذج له عند نشره:
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];
تبدأ العديد من التطبيقات مهمّة التنزيل في رمز الإعداد الخاص بها، ويمكنك تنفيذ ذلك في أي وقت قبل أن تحتاج إلى استخدام النموذج.
2. ضبط أداة رصد الكائنات
بعد ضبط مصادر النموذج، عليك ضبط أداة رصد الكائنات لحالة الاستخدام لديك مع كائن CustomObjectDetectorOptions
. يمكنك تغيير
الإعدادات التالية:
إعدادات أداة رصد العناصر | |
---|---|
وضع الرصد |
STREAM_MODE (الخيار التلقائي) | SINGLE_IMAGE_MODE
في السياسة في |
رصد عناصر متعددة وتتبّعها |
false (الخيار التلقائي) | true
لتحديد ما إذا كنت تريد اكتشاف وتتبع ما يصل إلى خمسة عناصر أو العنصر الأكثر بروزًا فقط (تلقائي). |
تصنيف الكائنات |
false (الخيار التلقائي) | true
تحديد ما إذا كان سيتم تصنيف العناصر المكتشفة أم لا باستخدام
نموذج المصنِّف المخصّص المقدَّم. لاستخدام نموذج التصنيف المخصّص، يجب ضبطه على |
الحد الأدنى للثقة للتصنيف |
الحد الأدنى لدرجة الثقة للتصنيفات التي تم رصدها. وفي حال عدم ضبط هذه السياسة، سيتم استخدام أي حدّ أدنى للمصنِّف تحدِّده البيانات الوصفية للنموذج. إذا كان النموذج لا يحتوي على أي بيانات وصفية أو إذا لم تحدّد البيانات الوصفية حدًا للمصنِّف، سيتم استخدام حد أقصى تلقائي هو 0.0. |
الحد الأقصى لعدد التصنيفات لكل عنصر |
الحدّ الأقصى لعدد التصنيفات التي ستعرضها أداة الرصد لكل عنصر. وفي حال ترك هذه السياسة بدون ضبط، سيتم استخدام القيمة التلقائية التي تبلغ 10. |
إذا كان لديك فقط نموذج مجمَّع محليًا، ما عليك سوى إنشاء أداة رصد الكائنات من
كائن LocalModel
:
Swift
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
إذا كان لديك نموذج مُستضاف عن بُعد، عليك التأكّد ممّا إذا تمّ تنزيله قبل تشغيله. ويمكنك التحقّق من حالة مهمة تنزيل النموذج
باستخدام طريقة isModelDownloaded(remoteModel:)
لدى مدير النماذج.
على الرغم من أنّه عليك تأكيد ذلك فقط قبل تشغيل أداة رصد الكائنات، إذا كان لديك نموذج مستضاف عن بُعد ونموذج مجمَّع محليًا، قد يكون من الأفضل إجراء هذا الفحص عند إنشاء مثيل ObjectDetector
: يمكنك إنشاء جهاز رصد من النموذج البعيد إذا تم تنزيله، ومن النموذج المحلي بطريقة أخرى.
Swift
var options: CustomObjectDetectorOptions! if (ModelManager.modelManager().isModelDownloaded(remoteModel)) { options = CustomObjectDetectorOptions(remoteModel: remoteModel) } else { options = CustomObjectDetectorOptions(localModel: localModel) } options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Objective-C
MLKCustomObjectDetectorOptions *options; if ([[MLKModelManager modelManager] isModelDownloaded:remoteModel]) { options = [[MLKCustomObjectDetectorOptions alloc] initWithRemoteModel:remoteModel]; } else { options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; } options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableClassification = YES; options.shouldEnableMultipleObjects = YES; options.classificationConfidenceThreshold = @(0.5); options.maxPerObjectLabelCount = 3;
إذا لم يكن لديك سوى نموذج مُستضاف عن بُعد، يجب إيقاف الوظائف ذات الصلة بالنموذج، على سبيل المثال، غير متاح أو إخفاء جزء من واجهة المستخدم، حتى تتأكّد من تنزيل النموذج.
يمكنك معرفة حالة تنزيل النموذج من خلال إرفاق المراقبين بمركز الإشعارات التلقائي. يجب استخدام إشارة ضعيفة إلى 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]; }];
ويتم تحسين واجهة برمجة التطبيقات الخاصة برصد الكائنات وتتبّعها لحالة الاستخدام الأساسية التالية:
- الرصد المباشر لأبرز العناصر في عدسة الكاميرا وتتبّعها
- يشير ذلك المصطلح إلى رصد عناصر متعددة من صورة ثابتة.
لضبط واجهة برمجة التطبيقات لحالات الاستخدام هذه:
Swift
// Live detection and tracking let options = CustomObjectDetectorOptions(localModel: localModel) options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3 // Multiple object detection in static images let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true options.maxPerObjectLabelCount = 3
Objective-C
// Live detection and tracking MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3; // Multiple object detection in static images MLKCustomObjectDetectorOptions *options = [[MLKCustomObjectDetectorOptions alloc] initWithLocalModel:localModel]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES; options.maxPerObjectLabelCount = 3;
3. تحضير صورة الإدخال
أنشِئ عنصر 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];
4. إنشاء أداة رصد الكائنات وتشغيلها
إنشاء أداة رصد جديدة للكائنات:
Swift
let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
بعد ذلك استخدِم أداة الرصد:
بشكل غير متزامن:
Swift
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Objective-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; في الوقت نفسه:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Objective-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. الحصول على معلومات عن العناصر المصنّفة
إذا نجح طلب معالج الصور، يتم تمرير قائمة
Object
إلى معالج الإكمال أو عرض القائمة، بناءً على
ما إذا كنت قد استدعيت الطريقة غير المتزامنة أو المتزامنة.
يحتوي كل Object
على السمات التالية:
frame |
تمثّل هذه السمة CGRect للإشارة إلى موضع العنصر في الصورة. |
||||||
trackingID |
عدد صحيح يعرّف الكائن في الصور، أو "nil" في SINGLE_IMAGE_Mode. | ||||||
labels |
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence), \(label.index)" }.joined(separator: "\n") }
Objective-C
// The list of detected objects contains one item if multiple object detection // wasn't enabled. for (MLKObject *object in objects) { CGRect frame = object.frame; NSNumber *trackingID = object.trackingID; for (MLKObjectLabel *label in object.labels) { NSString *labelString = [NSString stringWithFormat:@"%@, %f, %lu", label.text, label.confidence, (unsigned long)label.index]; } }
ضمان تجربة رائعة للمستخدم
لأفضل تجربة مستخدم، يُرجى اتّباع الإرشادات التالية في تطبيقك:
- يعتمد رصد الكائنات بدقة على مدى التعقيد البصري للكائن. لكي يتم رصدها، قد تحتاج العناصر التي تحتوي على عدد قليل من الميزات المرئية إلى أن تشغل مساحة أكبر من الصورة. يجب عليك تزويد المستخدمين بإرشادات حول التقاط المدخلات التي تعمل بشكل جيد مع نوع الكائنات التي تريد اكتشافها.
- عند استخدام التصنيف، إذا أردت رصد الكائنات التي لا تندرج ضمن الفئات المتوافقة، نفِّذ معالجة خاصة للكائنات غير المعروفة.
يمكنك أيضًا الاطّلاع على مجموعة [ML Kit Material Design view app][showcase-link]{: .external } ومجموعة أنماط الميزات المستندة إلى تعلُم الآلة في "التصميم المتعدد الأبعاد".
Improving performance
إذا أردت استخدام ميزة اكتشاف الأجسام في تطبيق في الوقت الفعلي، يُرجى اتّباع الإرشادات التالية لتحقيق أفضل عدد من اللقطات:عند استخدام وضع البث في تطبيق في الوقت الفعلي، يجب عدم استخدام ميزة رصد عناصر متعددة، لأنّ معظم الأجهزة لن تتمكّن من تسجيل عدد لقطات مناسب في الثانية.
- لمعالجة إطارات الفيديو، استخدِم واجهة برمجة التطبيقات المتزامنة
results(in:)
لأداة الرصد. ويمكنك استدعاء هذه الطريقة من وظيفةcaptureOutput(_, didOutput:from:)
فيAVCaptureVideoDataOutputSampleBufferDelegate
للحصول على نتائج متزامنة من إطار الفيديو المحدّد. الاحتفاظ بـAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
true
لتقليل المكالمات الواردة إلى جهاز الرصد. في حال توفّر إطار فيديو جديد أثناء تشغيل أداة الرصد، سيتم تجاهله. - إذا كنت تستخدم نتيجة أداة الرصد لإضافة رسومات على الصورة التي تم إدخالها، احصل أولاً على النتيجة من أدوات تعلّم الآلة، ثم اعرض الصورة والتراكب في خطوة واحدة. بإجراء ذلك، يتم عرضك على سطح الشاشة مرة واحدة فقط لكل إطار إدخال تمت معالجته. للاطّلاع على مثال، يمكن الاطّلاع على updatePreviewOverlayViewWithLastFrame في نموذج البدء السريع في ML Kit.