С помощью ML Kit можно обнаруживать и отслеживать объекты в последовательных кадрах видео.
Когда вы передаете изображение в ML Kit, он обнаруживает на изображении до пяти объектов, а также положение каждого объекта на изображении. При обнаружении объектов в видеопотоках каждому объекту присваивается уникальный идентификатор, который можно использовать для отслеживания объекта от кадра к кадру. Вы также можете включить приблизительную классификацию объектов, которая помечает объекты описаниями широких категорий.
Попробовать
- Попробуйте пример приложения, чтобы увидеть, как используется этот API.
- Пример реализации этого API можно найти в приложении Material Design showcase.
Подготовка
- Добавьте в Podfile следующие контейнеры ML Kit:
pod 'GoogleMLKit/ObjectDetection', '8.0.0'
- После установки или обновления Pods откройте проект Xcode, используя файл
.xcworkspace. ML Kit поддерживается в Xcode версии 12.4 и более поздних.
1. Как настроить детектор объектов
Чтобы обнаруживать объекты и отслеживать их перемещение, сначала создайте экземпляр класса ObjectDetector и при необходимости укажите настройки детектора, которые вы хотите изменить.
Настройте детектор объектов для своего варианта использования с помощью объекта
ObjectDetectorOptions. Вы можете изменить следующие настройки:Настройки детектора объектов Режим обнаружения .stream(по умолчанию) |.singleImageВ режиме потока (по умолчанию) детектор объектов работает с очень низкой задержкой, но при первых нескольких вызовах может выдавать неполные результаты (например, неопределенные ограничительные рамки или категории). Кроме того, в режиме потоковой передачи детектор присваивает объектам идентификаторы отслеживания, которые можно использовать для отслеживания объектов на разных кадрах. Используйте этот режим, если вам нужно отслеживать объекты или если важна низкая задержка, например при обработке видеопотоков в реальном времени.
В режиме одного изображения детектор объектов возвращает результат после определения ограничительной рамки объекта. Если вы также включите классификацию, результат будет возвращен после того, как будут доступны граничная рамка и ярлык категории. В результате задержка обнаружения может быть выше. Кроме того, в режиме одного изображения идентификаторы отслеживания не назначаются. Используйте этот режим, если задержка не критична и вы не хотите иметь дело с частичными результатами.
Обнаружение и отслеживание нескольких объектов false(по умолчанию) |trueНужно ли обнаруживать и отслеживать до пяти объектов или только самый заметный объект (по умолчанию).
Классифицировать объекты false(по умолчанию) |trueНужно ли классифицировать обнаруженные объекты по категориям. Если эта функция включена, детектор объектов классифицирует объекты по следующим категориям: одежда, еда, товары для дома, места и растения.
API обнаружения и отслеживания объектов оптимизирован для двух основных вариантов использования:
- Обнаружение и отслеживание в реальном времени наиболее заметного объекта в видоискателе камеры.
- Обнаружение нескольких объектов на статичном изображении.
Чтобы настроить API для этих вариантов использования:
Swift
// Live detection and tracking let options = ObjectDetectorOptions() options.shouldEnableClassification = true // Multiple object detection in static images let options = ObjectDetectorOptions() options.detectorMode = .singleImage options.shouldEnableMultipleObjects = true options.shouldEnableClassification = true
Objective-C
// Live detection and tracking MLKObjectDetectorOptions *options = [[MLKObjectDetectorOptions alloc] init]; options.shouldEnableClassification = YES; // Multiple object detection in static images MLKObjectDetectorOptions *options = [[MLKOptions alloc] init]; options.detectorMode = MLKObjectDetectorModeSingleImage; options.shouldEnableMultipleObjects = YES; options.shouldEnableClassification = YES;
- Получите экземпляр
ObjectDetector:
Swift
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Objective-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. Как подготовить входное изображение
Чтобы обнаружить и отслеживать объекты, выполните следующие действия для каждого изображения или кадра видео.
Если вы включили режим потока, то должны создать объекты VisionImage из объектов CMSampleBuffer.
Создайте объект VisionImage, используя UIImage или CMSampleBuffer.
Если вы используете 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;
Если вы используете CMSampleBuffer, выполните следующие действия:
-
Укажите ориентацию изображения, содержащегося в
CMSampleBuffer.Чтобы получить ориентацию изображения:
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 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и ориентацию: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. Обработка изображения
ПередайтеVisionImage одному из методов обработки изображений детектора объектов. Вы можете использовать асинхронный метод process(image:) или синхронный метод results().
Чтобы обнаружить объекты асинхронно:
Swift
objectDetector.process(image) { objects, error in guard error == nil else { // Error. return } guard !objects.isEmpty else { // No objects detected. return } // Success. Get object info here. // ... }
Objective-C
[objectDetector processImage:image completion:^(NSArray* _Nullable objects, NSError * _Nullable error) { if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here. }];
Чтобы распознавать объекты синхронно:
Swift
var objects: [Object] do { objects = try objectDetector.results(in: image) } catch let error { print("Failed to detect object with error: \(error.localizedDescription).") return } guard !objects.isEmpty else { print("Object detector returned no results.") return } // Success. Get object info here.
Objective-C
NSError *error; NSArray*objects = [objectDetector resultsInImage:image error:&error]; if (error == nil) { return; } if (objects.count == 0) { // No objects detected. return; } // Success. Get object info here.
4. Как получать информацию об обнаруженных объектах
Если вызов обработчика изображений выполнен успешно, он передает список объектовObject обработчику завершения или возвращает этот список (в зависимости от того, какой метод был вызван – асинхронный или синхронный).
Каждый объект Object содержит следующие свойства:
frame |
Элемент CGRect, указывающий положение объекта на изображении. |
trackingID |
Целое число, которое идентифицирует объект на разных изображениях, или значение nil в режиме одного изображения. |
labels |
Массив ярлыков, описывающих объект, возвращенный детектором.
Если для параметра детектора shouldEnableClassification задано значение false, свойство будет пустым.
|
Swift
// objects contains one item if multiple object detection wasn't enabled. for object in objects { let frame = object.frame let trackingID = object.trackingID // If classification was enabled: let description = object.labels.enumerated().map { (index, label) in "Label \(index): \(label.text), \(label.confidence)" }.joined(separator:"\n") }
Objective-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]; ... } }
Улучшение удобства использования и производительности
Чтобы обеспечить удобство пользователей, следуйте этим рекомендациям:
- Успешное обнаружение объектов зависит от их визуальной сложности. Чтобы объекты с небольшим количеством визуальных признаков были обнаружены, они должны занимать большую часть изображения. Пользователям нужно предоставить инструкции по съемке объектов, которые вы хотите распознавать.
- Если вы используете классификацию и хотите обнаруживать объекты, которые не относятся к поддерживаемым категориям, реализуйте специальную обработку неизвестных объектов.
Также ознакомьтесь с коллекцией шаблонов для функций на основе машинного обучения в Material Design.
При использовании режима потоковой передачи в приложении реального времени следуйте приведенным ниже рекомендациям, чтобы добиться наилучшей частоты кадров.
- Не используйте обнаружение нескольких объектов в режиме потоковой передачи, так как большинство устройств не смогут обеспечить адекватную частоту кадров.
- Если классификация вам не нужна, отключите ее.
- Для обработки кадров видео используйте синхронный API детектора
results(in:). Вызовите этот метод из функцииcaptureOutput(_, didOutput:from:)объектаAVCaptureVideoDataOutputSampleBufferDelegate, чтобы синхронно получить результаты для заданного кадра видео. Установите для параметраAVCaptureVideoDataOutputзначениеalwaysDiscardsLateVideoFrames, чтобы ограничить количество вызовов детектора.trueЕсли во время работы детектора станет доступен новый кадр видео, он будет отброшен. - Если вы используете результаты работы детектора для наложения графики на входное изображение, сначала получите результат от ML Kit, а затем отрисуйте изображение и наложите графику за один шаг. В этом случае отрисовка на поверхности экрана выполняется только один раз для каждого обработанного входного кадра. Пример можно найти в разделе updatePreviewOverlayViewWithLastFrame в руководстве по быстрому началу работы с ML Kit.