Когда вы передаете изображение в ML Kit, он обнаруживает до пяти объектов на изображении, а также положение каждого объекта на изображении. При обнаружении объектов в видеопотоках каждый объект имеет уникальный идентификатор, по которому можно отслеживать объект от кадра к кадру.
Вы можете использовать пользовательскую модель классификации изображений для классификации обнаруженных объектов. Ознакомьтесь с разделом «Пользовательские модели с комплектом ML», чтобы узнать о требованиях к совместимости моделей, где найти предварительно обученные модели и как обучать собственные модели.
Существует два способа интеграции пользовательской модели. Вы можете связать модель, поместив ее в папку ресурсов вашего приложения, или динамически загрузить ее из Firebase. В следующей таблице сравниваются два варианта.
Модель в комплекте | Размещенная модель |
---|---|
Модель является частью файла .ipa вашего приложения, что увеличивает его размер. | Модель не является частью .ipa файла вашего приложения. Он размещается путем загрузки в Firebase Machine Learning . |
Модель доступна сразу, даже когда Android-устройство находится в автономном режиме. | Модель скачивается по запросу. |
Нет необходимости в проекте Firebase | Требуется проект Firebase |
Вам необходимо повторно опубликовать свое приложение, чтобы обновить модель. | Отправляйте обновления модели без повторной публикации приложения. |
Нет встроенного A/B-тестирования. | Простое A/B-тестирование с помощью Firebase Remote Config |
Попробуйте это
- См. приложение быстрого запуска Vision для примера использования связанной модели и приложение быстрого запуска automl для примера использования размещенной модели.
- См. демонстрационное приложение Material Design , где представлена комплексная реализация этого API.
Прежде чем вы начнете
Включите библиотеки ML Kit в свой подфайл:
Для объединения модели с вашим приложением:
pod 'GoogleMLKit/ObjectDetectionCustom', '3.2.0'
Для динамической загрузки модели из Firebase добавьте зависимость
LinkFirebase
:pod 'GoogleMLKit/ObjectDetectionCustom', '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
Чтобы использовать удаленно размещенную модель, создайте объект CustomRemoteModel
, указав имя, которое вы присвоили модели при ее публикации:
Быстрый
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];
Многие приложения запускают задачу загрузки в своем коде инициализации, но вы можете сделать это в любой момент, прежде чем вам понадобится использовать модель.
2. Настройте детектор объектов
После настройки источников модели настройте детектор объектов для вашего варианта использования с помощью объекта CustomObjectDetectorOptions
. Вы можете изменить следующие настройки:
Настройки детектора объектов | |
---|---|
Режим обнаружения | STREAM_MODE (по умолчанию) | SINGLE_IMAGE_MODE В В |
Обнаружение и отслеживание нескольких объектов | false (по умолчанию) | true Следует ли обнаруживать и отслеживать до пяти объектов или только самый заметный объект (по умолчанию). |
Классифицировать объекты | false (по умолчанию) | true Следует ли классифицировать обнаруженные объекты с помощью предоставленной пользовательской модели классификатора. Чтобы использовать собственную модель классификации, вам необходимо установить для этого параметра значение |
Порог достоверности классификации | Минимальный показатель достоверности обнаруженных меток. Если не установлено, будет использоваться любое пороговое значение классификатора, указанное в метаданных модели. Если модель не содержит метаданных или в метаданных не указан порог классификатора, будет использоваться порог по умолчанию, равный 0,0. |
Максимальное количество ярлыков на объект | Максимальное количество меток на объект, возвращаемое детектором. Если не установлено, будет использоваться значение по умолчанию 10. |
Если у вас есть только локально связанная модель, просто создайте детектор объектов из вашего объекта LocalModel
:
Быстрый
let options = CustomObjectDetectorOptions(localModel: localModel) options.detectorMode = .singleImage options.shouldEnableClassification = true options.shouldEnableMultipleObjects = true options.classificationConfidenceThreshold = NSNumber(value: 0.5) options.maxPerObjectLabelCount = 3
Цель-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
: создайте детектор из удаленной модели, если оно скачано, а иначе из локальной модели.
Быстрый
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
Цель-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
в блоке наблюдателя, поскольку загрузка может занять некоторое время, а исходный объект может быть освобожден к моменту завершения загрузки. Например:
Быстрый
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]; }];
API обнаружения и отслеживания объектов оптимизирован для этих двух основных случаев использования:
- Обнаружение и отслеживание самого заметного объекта в видоискателе камеры в реальном времени.
- Обнаружение нескольких объектов на статическом изображении.
Чтобы настроить API для этих случаев использования:
Быстрый
// 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
Цель-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
.Быстрый
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];
4. Создайте и запустите детектор объектов.
Создайте новый детектор объектов:
Быстрый
let objectDetector = ObjectDetector.objectDetector(options: options)
Цель-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
Затем используйте детектор:
Асинхронно:
Быстрый
objectDetector.process(image) { objects, error in guard error == nil, let objects = objects, !objects.isEmpty else { // Handle the error. return } // Show results. }
Цель-C
[objectDetector processImage:image completion:^(NSArray
*_Nullable objects, NSError *_Nullable error) { if (objects.count == 0) { // Handle the error. return; } // Show results. }]; Синхронно:
Быстрый
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { // Handle the error. return } // Show results.
Цель-C
NSError *error; NSArray
*objects = [objectDetector resultsInImage:image error:&error]; // Show results or handle the error.
5. Получить информацию о помеченных объектах
Если вызов процессора изображений успешен, он либо передает список
Object
s обработчику завершения, либо возвращает список, в зависимости от того, вызвали ли вы асинхронный или синхронный метод.Каждый
Object
содержит следующие свойства:frame
CGRect
, указывающий положение объекта на изображении.trackingID
Целое число, идентифицирующее объект на всех изображениях, или «ноль» в SINGLE_IMAGE_MODE. labels
label.text
Текстовое описание метки. Возвращается только в том случае, если метаданные модели TensorFlow Lite содержат описания меток. label.index
Индекс метки среди всех меток, поддерживаемых классификатором. label.confidence
Доверительная ценность классификации объектов. Быстрый
// 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") }
Цель-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][showcase-link]{: .external } и коллекцией шаблонов Material Design для функций машинного обучения .
Улучшение производительности
Если вы хотите использовать обнаружение объектов в приложении реального времени, следуйте этим рекомендациям для достижения наилучшей частоты кадров:Когда вы используете режим потоковой передачи в приложении реального времени, не используйте обнаружение нескольких объектов, поскольку большинство устройств не смогут обеспечить адекватную частоту кадров.
- Для обработки видеокадров используйте синхронный API
results(in:)
детектора. Вызовите этот метод изcaptureOutput(_, didOutput:from:)
AVCaptureVideoDataOutputSampleBufferDelegate
, чтобы синхронно получить результаты из данного видеокадра. ОставьтеAVCaptureVideoDataOutput
значениеalwaysDiscardsLateVideoFrames
какtrue
, чтобы ограничить вызовы детектора. Если во время работы детектора появится новый видеокадр, он будет удален. - Если вы используете выходные данные детектора для наложения графики на входное изображение, сначала получите результат из ML Kit, затем визуализируйте изображение и наложите его за один шаг. При этом вы выполняете рендеринг на поверхность дисплея только один раз для каждого обработанного входного кадра. Пример см. в updatePreviewOverlayViewWithLastFrame в образце быстрого запуска ML Kit.
Если не указано иное, контент на этой странице предоставляется по лицензии Creative Commons "С указанием авторства 4.0", а примеры кода – по лицензии Apache 2.0. Подробнее об этом написано в правилах сайта. Java – это зарегистрированный товарный знак корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2024-08-13 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":"Другое" }] { "last_modified": "Последнее обновление: 2024-08-13 UTC.", "state": "" }