بعد تدريب نموذجك الخاص باستخدام AutoML Vision Edge، يمكنك استخدامه في تطبيقك لتصنيف الصور.
هناك طريقتان لدمج النماذج التي تم تدريبها من AutoML Vision Edge. يمكنك تجميع النموذج عن طريق نسخ ملفات النموذج إلى مشروع Xcode أو تنزيله ديناميكيًا من Firebase.
خيارات تجميع النموذج | |
---|---|
مُجمَّعة في تطبيقك |
|
مستضاف باستخدام Firebase |
|
قبل البدء
تضمين مكتبات ML Kit في Podfile:
لتجميع نموذج مع تطبيقك:
pod 'GoogleMLKit/ImageLabelingCustom'
لتنزيل نموذج ديناميكيًا من Firebase، أضِف الاعتمادية
LinkFirebase
:pod 'GoogleMLKit/ImageLabelingCustom' pod 'GoogleMLKit/LinkFirebase'
بعد تثبيت لوحات مشروعك أو تحديثها، افتح مشروعك في Xcode باستخدام
.xcworkspace
. يتوافق ML Kit مع الإصدار 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 في نموذج تطبيق العرض