Вы можете использовать ML Kit для обнаружения и отслеживания объектов в последовательных видеокадрах.
Когда вы передаете изображение в ML Kit, он обнаруживает до пяти объектов на изображении, а также положение каждого объекта на изображении. При обнаружении объектов в видеопотоках каждый объект имеет уникальный идентификатор, по которому можно отслеживать объект от кадра к кадру. Вы также можете дополнительно включить грубую классификацию объектов, которая помечает объекты широкими описаниями категорий.
Попробуйте это
- Поэкспериментируйте с примером приложения , чтобы увидеть пример использования этого API.
- См. демонстрационное приложение Material Design , где представлена комплексная реализация этого API.
Прежде чем вы начнете
- Включите в свой подфайл следующие модули ML Kit:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- После установки или обновления модулей вашего проекта откройте проект Xcode, используя его
.xcworkspace
. ML Kit поддерживается в Xcode версии 12.4 или новее.
1. Настройте детектор объектов
Чтобы обнаруживать и отслеживать объекты, сначала создайте экземпляр ObjectDetector
и при необходимости укажите любые настройки детектора, которые вы хотите изменить по умолчанию.
Настройте детектор объектов для вашего варианта использования с помощью объекта
ObjectDetectorOptions
. Вы можете изменить следующие настройки:Настройки детектора объектов Режим обнаружения .stream
(по умолчанию) |.singleImage
В потоковом режиме (по умолчанию) детектор объектов работает с очень низкой задержкой, но может давать неполные результаты (например, неуказанные ограничивающие рамки или категории) при первых нескольких вызовах детектора. Кроме того, в потоковом режиме детектор присваивает объектам идентификаторы отслеживания, которые можно использовать для отслеживания объектов между кадрами. Используйте этот режим, если вы хотите отслеживать объекты или когда важна низкая задержка, например, при обработке видеопотоков в реальном времени.
В режиме одного изображения детектор объектов возвращает результат после определения ограничивающей рамки объекта. Если вы также включите классификацию, результат будет возвращен после того, как будут доступны ограничивающая рамка и метка категории. Как следствие, задержка обнаружения потенциально выше. Кроме того, в режиме одного изображения идентификаторы отслеживания не назначаются. Используйте этот режим, если задержка не критична и вы не хотите иметь дело с частичными результатами.
Обнаружение и отслеживание нескольких объектов false
(по умолчанию) |true
Следует ли обнаруживать и отслеживать до пяти объектов или только самый заметный объект (по умолчанию).
Классифицировать объекты false
(по умолчанию) |true
Классифицировать обнаруженные объекты по грубым категориям или нет. При включении детектор объектов классифицирует объекты по следующим категориям: модные товары, продукты питания, товары для дома, места и растения.
API обнаружения и отслеживания объектов оптимизирован для этих двух основных случаев использования:
- Обнаружение и отслеживание самого заметного объекта в видоискателе камеры в реальном времени.
- Обнаружение нескольких объектов на статическом изображении.
Чтобы настроить API для этих случаев использования:
Быстрый
// 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
Цель-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
:
Быстрый
let objectDetector = ObjectDetector.objectDetector() // Or, to change the default settings: let objectDetector = ObjectDetector.objectDetector(options: options)
Цель-C
MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetector]; // Or, to change the default settings: MLKObjectDetector *objectDetector = [MLKObjectDetector objectDetectorWithOptions:options];
2. Подготовьте входное изображение
Чтобы обнаружить и отслеживать объекты, выполните следующие действия для каждого изображения или кадра видео. Если вы включили потоковый режим, вам необходимо создать объекты VisionImage
из CMSampleBuffer
s.
Создайте объект 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. Обработка изображения
ПередайтеVisionImage
одному из методов обработки изображений детектора объектов. Вы можете использовать либо метод асинхронногоprocess(image:)
либо метод синхронныхresults()
.Чтобы обнаружить объекты асинхронно:
Быстрый
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. // ... }
Цель-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. }]; Чтобы обнаружить объекты синхронно:
Быстрый
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.
Цель-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
s обработчику завершения, либо возвращает список, в зависимости от того, вызвали ли вы асинхронный или синхронный метод.Каждый
Object
содержит следующие свойства:frame
CGRect
, указывающий положение объекта на изображении.trackingID
Целое число, идентифицирующее объект на всех изображениях, или «ноль» в режиме одного изображения. labels
Массив меток, описывающих объект, возвращаемый детектором. Свойство пусто, если для параметра детектора shouldEnableClassification
установлено значениеfalse
.Быстрый
// 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") }
Цель-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]; ... } }
Улучшение удобства использования и производительности
Для обеспечения наилучшего пользовательского опыта следуйте этим рекомендациям в своем приложении:
- Успешное обнаружение объекта зависит от визуальной сложности объекта. Чтобы быть обнаруженными, объектам с небольшим количеством визуальных особенностей может потребоваться занимать большую часть изображения. Вы должны предоставить пользователям рекомендации по захвату входных данных, которые хорошо работают с объектами того типа, которые вы хотите обнаружить.
- Если при использовании классификации вы хотите обнаружить объекты, которые не попадают в поддерживаемые категории, реализуйте специальную обработку неизвестных объектов.
Также ознакомьтесь с коллекцией шаблонов проектирования материалов для функций машинного обучения .
При использовании режима потоковой передачи в приложении реального времени следуйте этим рекомендациям для достижения наилучшей частоты кадров:
- Не используйте обнаружение нескольких объектов в режиме потоковой передачи, так как большинство устройств не смогут обеспечить достаточную частоту кадров.
- Отключите классификацию, если она вам не нужна.
- Для обработки видеокадров используйте синхронный 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": "" }