بعد تدريب النموذج الخاص بك باستخدام 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
الخاص به. ML Kit مدعوم في Xcode الإصدار 12.2 أو أعلى.إذا كنت ترغب في تنزيل نموذج ، فتأكد من إضافة Firebase إلى مشروع Android الخاص بك ، إذا لم تكن قد قمت بذلك بالفعل. هذا ليس مطلوبًا عند تجميع النموذج.
1. قم بتحميل النموذج
تكوين مصدر نموذج محلي
لتجميع النموذج مع تطبيقك:
استخرج النموذج وبياناته الوصفية من الأرشيف المضغوط الذي قمت بتنزيله من وحدة تحكم Firebase إلى مجلد:
your_model_directory |____dict.txt |____manifest.json |____model.tflite
يجب أن تكون جميع الملفات الثلاثة في نفس المجلد. نوصيك باستخدام الملفات أثناء تنزيلها ، دون تعديل (بما في ذلك أسماء الملفات).
انسخ المجلد إلى مشروع Xcode الخاص بك ، مع الحرص على تحديد إنشاء مراجع مجلد عند القيام بذلك. سيتم تضمين ملف النموذج والبيانات الوصفية في حزمة التطبيق ومتاحة لـ ML Kit.
قم بإنشاء كائن
LocalModel
، مع تحديد المسار إلى ملف بيان النموذج:سويفت
guard let manifestPath = Bundle.main.path( forResource: "manifest", ofType: "json", inDirectory: "your_model_directory" ) else { return true } let localModel = LocalModel(manifestPath: manifestPath)
ج موضوعية
NSString *manifestPath = [NSBundle.mainBundle pathForResource:@"manifest" ofType:@"json" inDirectory:@"your_model_directory"]; MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithManifestPath:manifestPath];
هيئ مصدر نموذج مستضاف على Firebase
لاستخدام النموذج المستضاف عن بُعد ، أنشئ كائن CustomRemoteModel
، وحدد الاسم الذي عينته للنموذج عند نشره:
سويفت
// 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)
ج موضوعية
// 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:
سويفت
let downloadConditions = ModelDownloadConditions(
allowsCellularAccess: true,
allowsBackgroundDownloading: true
)
let downloadProgress = ModelManager.modelManager().download(
remoteModel,
conditions: downloadConditions
)
ج موضوعية
MLKModelDownloadConditions *downloadConditions =
[[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES
allowsBackgroundDownloading:YES];
NSProgress *downloadProgress =
[[MLKModelManager modelManager] downloadRemoteModel:remoteModel
conditions:downloadConditions];
تبدأ العديد من التطبيقات مهمة التنزيل في كود التهيئة الخاص بها ، ولكن يمكنك القيام بذلك في أي وقت قبل أن تحتاج إلى استخدام النموذج.
قم بإنشاء ملصق صورة من نموذجك
بعد تكوين مصادر النموذج ، قم بإنشاء كائن ImageLabeler
من أحدها.
إذا كان لديك نموذج مجمع محليًا فقط ، فما عليك سوى إنشاء أداة تسمية من كائن LocalModel
وتكوين حد درجة الثقة التي تريد طلبها (راجع تقييم النموذج الخاص بك ):
سويفت
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)
ج موضوعية
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
: قم بإنشاء أداة تسمية من النموذج البعيد إذا كانت تم تنزيله ، ومن النموذج المحلي بخلاف ذلك.
سويفت
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)
ج موضوعية
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
في كتلة المراقب ، حيث يمكن أن تستغرق التنزيلات بعض الوقت ، ويمكن تحرير الكائن الأصلي بحلول الوقت الذي ينتهي فيه التنزيل. على سبيل المثال:
سويفت
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]
// ...
}
ج موضوعية
__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
الصحيح.سويفت
let image = VisionImage(image: uiImage) visionImage.orientation = image.imageOrientation
ج موضوعية
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
إذا كنت تستخدم CMSampleBufferRef
، فاتبع الخطوات التالية:
حدد اتجاه بيانات الصورة الموجودة في المخزن المؤقت
CMSampleBufferRef
.للحصول على اتجاه الصورة:
سويفت
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 } }
ج موضوعية
- (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
والاتجاه:سويفت
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
ج موضوعية
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. قم بتشغيل أداة تسمية الصورة
بشكل غير متزامن:
سويفت
imageLabeler.process(image) { labels, error in
guard error == nil, let labels = labels, !labels.isEmpty else {
// Handle the error.
return
}
// Show results.
}
ج موضوعية
[imageLabeler
processImage:image
completion:^(NSArray<MLKImageLabel *> *_Nullable labels,
NSError *_Nullable error) {
if (label.count == 0) {
// Handle the error.
return;
}
// Show results.
}];
بشكل متزامن:
سويفت
var labels: [ImageLabel]
do {
labels = try imageLabeler.results(in: image)
} catch let error {
// Handle the error.
return
}
// Show results.
ج موضوعية
NSError *error;
NSArray<MLKImageLabel *> *labels =
[imageLabeler resultsInImage:image error:&error];
// Show results or handle the error.
4. احصل على معلومات حول الكائنات المسماة
إذا نجحت عملية وسم الصورة ، فإنها تُرجع مصفوفة ImageLabel
. تمثل كل ImageLabel
شيئًا تم تسميته في الصورة. يمكنك الحصول على وصف نصي لكل تسمية (إذا كان متوفرًا في البيانات الوصفية لملف نموذج TensorFlow Lite) ودرجة الثقة والفهرس. على سبيل المثال:
سويفت
for label in labels {
let labelText = label.text
let confidence = label.confidence
let index = label.index
}
ج موضوعية
for (MLKImageLabel *label in labels) {
NSString *labelText = label.text;
float confidence = label.confidence;
NSInteger index = label.index;
}
نصائح لتحسين الأداء في الوقت الفعلي
إذا كنت ترغب في تسمية الصور في تطبيق في الوقت الفعلي ، فاتبع هذه الإرشادات لتحقيق أفضل الإطارات:
- خنق المكالمات للكاشف. إذا أصبح إطار الفيديو الجديد متاحًا أثناء تشغيل الكاشف ، فقم بإسقاط الإطار.
- إذا كنت تستخدم إخراج الكاشف لتراكب الرسومات على صورة الإدخال ، فاحصل أولاً على النتيجة ، ثم اعرض الصورة والتراكب في خطوة واحدة. من خلال القيام بذلك ، فإنك تقدم لسطح العرض مرة واحدة فقط لكل إطار إدخال. اطلع على فئتي previewOverlayView و FIRDetectionOverlayView في تطبيق نموذج العرض للحصول على مثال.