您可以使用机器学习套件检测和跟踪连续视频帧中的对象。
当您将图片传递给机器学习套件时,机器学习套件最多可检测图片中的 5 个对象 以及图像中每个对象的位置。当在 视频流,每个对象都有一个唯一 ID,可用于跟踪 帧的呈现方式您也可以选择启用粗略对象 分类,使用宽泛的类别说明为对象加标签。
试试看
- 您可以试用示例应用, 查看此 API 的用法示例。
- 请参阅 Material Design 展示区 app 获取此 API 的端到端实现。
准备工作
- 在 Podfile 中添加以下机器学习套件 Pod:
pod 'GoogleMLKit/ObjectDetection', '3.2.0'
- 安装或更新项目的 Pod 之后,使用 Xcode 项目的
.xcworkspace
。Xcode 12.4 或更高版本支持机器学习套件。
1. 配置对象检测器
要检测和跟踪对象,首先要创建一个
ObjectDetector
,并视需要指定任何检测器设置
更改。
使用
ObjectDetectorOptions
对象。您可以更改以下设置 设置:对象检测器设置 检测模式 .stream
(默认值)|.singleImage
在流模式(默认)下,对象检测器以非常低的 延迟时间,但可能会生成不完整的结果(例如未指定 边界框或类别)进行微调。 检测器。此外,在流模式下,检测器会指定跟踪 对象的 ID,可用于跨帧跟踪对象。 如果您想跟踪对象或缩短延迟时间,请使用此模式 非常重要,例如在实时处理视频流时, 。
在单图片模式下,对象检测器会返回结果 在确定了对象的边界框之后。如果您还启用了 它返回边界框之后的结果, 类别标签。因此,检测结果 延迟时间可能更长另外,在单图模式下 未分配 ID。如果延迟时间不重要,并且 因此您不希望只处理部分结果
检测和跟踪多个对象 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
。
使用 UIImage
或VisionImage
CMSampleBuffer
。
如果您使用 UIImage
,请按以下步骤操作:
- 使用
UIImage
创建一个VisionImage
对象。请务必指定正确的.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 机器学习驱动的特征的模式集合。
在实时应用中使用流处理模式时,请遵循以下准则 以实现最佳帧速率
- 不要在流式传输模式下使用多个对象检测,因为大多数设备不会 能够生成足够的帧速率
- 如果您不需要,请停用分类。
- 如需处理视频帧,请使用检测器的
results(in:)
同步 API。致电 此方法(可从 获取)AVCaptureVideoDataOutputSampleBufferDelegate
的captureOutput(_, didOutput:from:)
函数,用于同步获取指定视频的结果 帧。保留AVCaptureVideoDataOutput
的alwaysDiscardsLateVideoFrames
设置为true
,以限制对检测器的调用。如果新的 视频帧在检测器运行时可用,则会丢失。 - 如果您使用检测器的输出在图像上叠加显示 输入图片,首先从机器学习套件获取结果, 和叠加层。通过这种方式,您可以在显示屏上呈现 只对每个已处理的输入帧运行一次。请参阅 updatePreviewOverlayViewWithLastFrame 。