بعد تدريب النموذج الخاص بك باستخدام AutoML Vision Edge، يمكنك استخدامه في تطبيقك لتصنيف الصور.
هناك طريقتان لدمج النماذج التي تم تدريبها من AutoML Vision Edge. يمكنك تجميع النموذج عن طريق نسخ ملفات النموذج إلى مشروع Xcode، أو يمكنك تنزيله ديناميكيًا من Firebase.
خيارات تجميع النماذج | |
---|---|
مُضمَّنة في تطبيقك |
|
مستضافة باستخدام Firebase |
|
قبل البدء
أدرِج مكتبات ML Kit في ملف Podfile:
لتجميع نموذج مع تطبيقك:
pod 'GoogleMLKit/ImageLabelingCustom'
لتنزيل نموذج ديناميكيًا من Firebase، أضِف
LinkFirebase
التبعية:pod 'GoogleMLKit/ImageLabelingCustom' pod 'GoogleMLKit/LinkFirebase'
بعد تثبيت حِزم Pods في مشروعك أو تحديثها، افتح مشروع Xcode باستخدام
.xcworkspace
. تتوافق "حزمة تعلُّم الآلة" مع الإصدار 12.2 من Xcode أو الإصدارات الأحدث.إذا أردت تنزيل نموذج، تأكَّد من إضافة Firebase إلى مشروع Android، إذا لم يسبق لك إجراء ذلك. ولا يُشترط إجراء ذلك عند تجميع النموذج.
1. تحميل النموذج
ضبط مصدر نموذج على الجهاز
لتجميع النموذج مع تطبيقك:
استخرِج النموذج والبيانات الوصفية له من أرشيف zip الذي نزّلته من وحدة تحكّم Firebase إلى مجلد:
your_model_directory |____dict.txt |____manifest.json |____model.tflite
يجب أن تكون جميع الملفات الثلاثة في المجلد نفسه. ننصحك باستخدام الملفات كما نزّلتها، بدون إجراء أي تعديلات (بما في ذلك أسماء الملفات).
انسخ المجلد إلى مشروع Xcode، مع الحرص على اختيار إنشاء إشارات إلى المجلد عند إجراء ذلك. سيتم تضمين ملف النموذج والبيانات الوصفية في حِزمة التطبيق وسيتم إتاحتهما لخدمة ML Kit.
أنشئ عنصر
LocalModel
، مع تحديد المسار إلىملف بيان النموذج: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];
إذا كان لديك نموذج مستضاف عن بُعد فقط، عليك إيقاف وظائفه المتعلقة بالنموذج، مثل إخفاء جزء من واجهة المستخدم أو جعله يظهر باللون الرمادي، إلى أن يتم تأكيد تنزيل النموذج.
يمكنك الحصول على حالة تنزيل النموذج من خلال إرفاق مراقبين بتطبيق "مركز الإشعارات" التلقائي. احرص على استخدام إشارة ضعيفة إلى 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 في تطبيق "نموذج العرض" للحصول على مثال.