Вы можете использовать ML Kit, чтобы распознавать объекты на изображении и маркировать их. Этот API поддерживает широкий спектр пользовательских моделей классификации изображений. См. Пользовательские модели с комплектом ML , чтобы узнать о требованиях к совместимости моделей, где найти предварительно обученные модели и как обучать собственные модели.
Существует два способа интеграции пользовательской модели. Вы можете связать модель, поместив ее в папку активов вашего приложения, или вы можете динамически загрузить ее из Firebase. В следующей таблице сравниваются два варианта.
Комплектная модель | Размещенная модель |
---|---|
Модель является частью APK вашего приложения, что увеличивает его размер. | Модель не является частью вашего APK. Он размещается путем загрузки в Firebase Machine Learning . |
Модель доступна сразу, даже когда Android-устройство не в сети | Модель скачивается по запросу |
Нет необходимости в проекте Firebase | Требуется проект Firebase |
Вы должны повторно опубликовать свое приложение, чтобы обновить модель. | Отправляйте обновления модели без повторной публикации приложения |
Нет встроенного A/B-тестирования | Простое A/B-тестирование с помощью Firebase Remote Config |
Попробуйте
- См. приложение быстрого запуска Vision для примера использования связанной модели и приложение быстрого запуска automl для примера использования размещенной модели.
Прежде чем вы начнете
Включите библиотеки ML Kit в свой подфайл:
Для связывания модели с вашим приложением:
pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0'
Для динамической загрузки модели из Firebase добавьте зависимость
LinkFirebase
:pod 'GoogleMLKit/ImageLabelingCustom', '3.2.0' pod 'GoogleMLKit/LinkFirebase', '3.2.0'
После установки или обновления модулей вашего проекта откройте проект Xcode, используя его
.xcworkspace
. ML Kit поддерживается в Xcode версии 13.2.1 или выше.Если вы хотите загрузить модель , убедитесь, что вы добавили Firebase в свой проект iOS , если вы еще этого не сделали. Это не требуется, когда вы связываете модель.
1. Загрузите модель
Настройте локальный источник модели
Чтобы связать модель с вашим приложением:
Скопируйте файл модели (обычно оканчивающийся на
.tflite
или.lite
) в свой проект Xcode, не забыв при этом выбратьCopy bundle resources
. Файл модели будет включен в комплект приложения и доступен для ML Kit.Создайте объект
LocalModel
, указав путь к файлу модели:Быстрый
let localModel = LocalModel(path: localModelFilePath)
Цель-C
MLKLocalModel *localModel = [[MLKLocalModel alloc] initWithPath:localModelFilePath];
Настройте источник модели, размещенный в Firebase.
Чтобы использовать удаленно размещенную модель, создайте объект RemoteModel
, указав имя, которое вы присвоили модели при ее публикации:
Быстрый
let firebaseModelSource = FirebaseModelSource( name: "your_remote_model") // The name you assigned in // the Firebase console. let remoteModel = CustomRemoteModel(remoteModelSource: firebaseModelSource)
Цель-C
MLKFirebaseModelSource *firebaseModelSource = [[MLKFirebaseModelSource alloc] initWithName:@"your_remote_model"]; // The name you assigned in // the Firebase console. MLKCustomRemoteModel *remoteModel = [[MLKCustomRemoteModel alloc] initWithRemoteModelSource:firebaseModelSource];
Затем запустите задачу загрузки модели, указав условия, при которых вы хотите разрешить загрузку. Если модели нет на устройстве или доступна более новая версия модели, задача асинхронно загрузит модель из Firebase:
Быстрый
let downloadConditions = ModelDownloadConditions( allowsCellularAccess: true, allowsBackgroundDownloading: true ) let downloadProgress = ModelManager.modelManager().download( remoteModel, conditions: downloadConditions )
Цель-C
MLKModelDownloadConditions *downloadConditions = [[MLKModelDownloadConditions alloc] initWithAllowsCellularAccess:YES allowsBackgroundDownloading:YES]; NSProgress *downloadProgress = [[MLKModelManager modelManager] downloadModel:remoteModel conditions:downloadConditions];
Многие приложения запускают задачу загрузки в своем коде инициализации, но вы можете сделать это в любой момент, прежде чем вам понадобится использовать модель.
Настройте этикетировщик изображений
После настройки источников модели создайте объект ImageLabeler
из одного из них.
Доступны следующие варианты:
Опции | |
---|---|
confidenceThreshold | Минимальная оценка достоверности обнаруженных меток. Если не задано, будет использоваться любой порог классификатора, указанный в метаданных модели. Если модель не содержит метаданных или метаданные не определяют пороговое значение классификатора, будет использоваться пороговое значение по умолчанию, равное 0,0. |
maxResultCount | Максимальное количество возвращаемых ярлыков. Если не установлено, будет использоваться значение по умолчанию 10. |
Если у вас есть только локально связанная модель, просто создайте метку из вашего объекта LocalModel
:
Быстрый
let options = CustomImageLabelerOptions(localModel: localModel) options.confidenceThreshold = NSNumber(value: 0.0) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Цель-C
MLKCustomImageLabelerOptions *options = [[MLKCustomImageLabelerOptions alloc] initWithLocalModel:localModel]; options.confidenceThreshold = @(0.0); 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) let imageLabeler = ImageLabeler.imageLabeler(options: options)
Цель-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
в блоке наблюдателя, поскольку загрузка может занять некоторое время, а исходный объект может быть освобожден к моменту завершения загрузки. Например:
Быстрый
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] // ... }
Цель-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
.Быстрый
let image = VisionImage(image: UIImage) visionImage.orientation = image.imageOrientation
Цель-C
MLKVisionImage *visionImage = [[MLKVisionImage alloc] initWithImage:image]; visionImage.orientation = image.imageOrientation;
Если вы используете
CMSampleBuffer
, выполните следующие действия:Укажите ориентацию данных изображения, содержащихся в
CMSampleBuffer
.Чтобы получить ориентацию изображения:
Быстрый
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 } }
Цель-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
и ориентацию:Быстрый
let image = VisionImage(buffer: sampleBuffer) image.orientation = imageOrientation( deviceOrientation: UIDevice.current.orientation, cameraPosition: cameraPosition)
Цель-C
MLKVisionImage *image = [[MLKVisionImage alloc] initWithBuffer:sampleBuffer]; image.orientation = [self imageOrientationFromDeviceOrientation:UIDevice.currentDevice.orientation cameraPosition:cameraPosition];
3. Запустите этикетировщик изображений
Чтобы пометить объекты на изображении, передайте объект
image
методуprocess()
объектаImageLabeler
.Асинхронно:
Быстрый
imageLabeler.process(image) { labels, error in guard error == nil, let labels = labels, !labels.isEmpty else { // Handle the error. return } // Show results. }
Цель-C
[imageLabeler processImage:image completion:^(NSArray
*_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.
Цель-C
NSError *error; NSArray
*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 }
Цель-C
for (MLKImageLabel *label in labels) { NSString *labelText = label.text; float confidence = label.confidence; NSInteger index = label.index; }
Советы по улучшению производительности в реальном времени
Если вы хотите маркировать изображения в приложении реального времени, следуйте этим рекомендациям для достижения наилучшей частоты кадров:
- Для обработки видеокадров используйте синхронный API
results(in:)
детектора. Вызовите этот метод изAVCaptureVideoDataOutputSampleBufferDelegate
captureOutput(_, didOutput:from:)
чтобы синхронно получить результаты из данного видеокадра. СохраняйтеAVCaptureVideoDataOutput
alwaysDiscardsLateVideoFrames
какtrue
, чтобы ограничить вызовы детектора. Если новый видеокадр становится доступным во время работы детектора, он будет отброшен. - Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем выполните визуализацию изображения и наложение за один шаг. Поступая таким образом, вы визуализируете на поверхность дисплея только один раз для каждого обработанного входного кадра. В качестве примера см. updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.
Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.
Last updated 2023-02-03 UTC.
[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Отсутствует нужная мне информация" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Слишком сложен/слишком много шагов" },{ "type": "thumb-down", "id": "outOfDate", "label":"Устарел" },{ "type": "thumb-down", "id": "translationIssue", "label":"Проблема с переводом текста" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Проблемы образцов/кода" },{ "type": "thumb-down", "id": "otherDown", "label":"Другое" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Прост для понимания" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Помог мне решить мою проблему" },{ "type": "thumb-up", "id": "otherUp", "label":"Другое" }] - Для обработки видеокадров используйте синхронный API