这段代码是一个 CameraViewController
的扩展,遵循了 PoseLandmarkerServiceLiveStreamDelegate
协议,用于处理姿势检测的结果,并在界面上进行绘制。下面是对代码的详细解释:
1. 协议实现
extension CameraViewController: PoseLandmarkerServiceLiveStreamDelegate {
这个扩展表示 CameraViewController
类遵循了 PoseLandmarkerServiceLiveStreamDelegate
协议,意味着它需要实现协议中定义的方法。
2. 方法实现
func poseLandmarkerService(
_ poseLandmarkerService: PoseLandmarkerService,
didFinishDetection result: ResultBundle?,
error: Error?) {
这是协议中的方法。当姿势检测完成时会被调用。该方法接受三个参数:
poseLandmarkerService
: 发起检测的服务实例。result
: 检测结果的可选包裹类型(可能为nil)。error
: 如果发生错误,则包含相应的错误信息(可能为nil)。
3. 主线程异步执行
DispatchQueue.main.async { [weak self] in
由于 UI 更新必须在主线程上执行,这里使用 GCD(Grand Central Dispatch)将后续操作调度到主线程。[weak self]
是为了避免强引用循环,从而防止内存泄漏。
4. 安全解包和委托回调
guard let weakSelf = self else { return }
weakSelf.inferenceResultDeliveryDelegate?.didPerformInference(result: result)
首先,通过安全解包确保 self
不为 nil。如果不为 nil,就调用代理 (inferenceResultDeliveryDelegate
) 的方法,将检测结果传递给它。
5. 获取姿势检测结果
guard let poseLandmarkerResult = result?.poseLandmarkerResults.first as? PoseLandmarkerResult else { return }
从结果中提取第一个姿势检测结果。如果没有结果,则直接返回,不再继续执行后面的代码。
6. 获取图像尺寸
let imageSize = weakSelf.cameraFeedService.videoResolution
获取当前摄像头视频流的分辨率,用于后续绘制。
7. 创建覆盖层对象(Overlay)
let poseOverlays = OverlayView.poseOverlays(
fromMultiplePoseLandmarks: poseLandmarkerResult.landmarks,
inferredOnImageOfSize: imageSize,
ovelayViewSize: weakSelf.overlayView.bounds.size,
imageContentMode: weakSelf.overlayView.imageContentMode,
andOrientation: UIImage.Orientation.from(deviceOrientation: UIDevice.current.orientation))
调用静态方法创建覆盖层,该方法根据多个姿势地标生成相应的绘制对象,参数包括:
- 姿势地标数组。
- 图像大小。
- 覆盖视图的大小。
- 图像内容模式。
- 当前设备方向转换成对应的 UIImage Orientation。
8. 绘制覆盖层到视图上
weakSelf.overlayView.draw(poseOverlays: poseOverlays,
inBoundsOfContentImageOfSize: imageSize,
imageContentMode: weakSelf.cameraFeedService.videoGravity.contentMode)
最后,通过调用 overlayView 的绘制方法,将计算出的覆盖层绘制到显示区域。这也是更新 UI 的关键部分,根据之前获取的数据动态展示姿势识别效果。
总结:此段代码主要功能是在摄像头实时输入下,对人体姿势进行识别并将识别结果以图形化方式展示在用户界面上。
内容由零声教学AI助手提供,问题来源于学员提问