Highlight
Vision 框架的 Face Detection 升级到 Revision 3,支持检测戴口罩的人脸并新增 pitch 姿态指标,所有姿态指标从离散值改为连续值;Person Segmentation API 新增语义人物分割,可在多平台实现虚拟背景和人物抠图。
核心内容
人脸检测的口罩时代升级
戴口罩成为日常后,原来的人脸检测算法会遇到挑战。WWDC2021 把人脸检测升级到 Revision 3(01:15),不仅能识别被口罩遮挡的脸,还保留了眼镜、帽子等遮挡物的识别能力。
人脸姿态指标也得到完善。之前只有 roll 和 yaw,今年新增了 pitch(点头动作)。更重要的是,所有指标从离散值(分桶)改为连续值(01:41)。以前 roll 只能返回 -90、-45、0、45、90 这几档,现在可以返回任意弧度值,使得姿态跟踪更流畅。
三个姿态指标的含义来自飞行力学(02:54):
- Roll:头部左右歪斜(摇头)
- Yaw:头部左右转动(回头)
- Pitch:头部上下点头
这些指标通过 VNFaceObservation 的 roll、yaw、pitch 属性获取,单位是弧度。
人体姿态检测的改进
人体矩形检测升级到 Revision 2(05:17),新增全身检测支持。之前只能检测上半身,现在可以通过 upperBodyOnly 属性切换。默认仍是 true 保持向后兼容,设为 false 可以检测全身。
手部姿态检测新增 chirality 属性(06:16),可以判断检测到的手是左手还是右手。
Person Segmentation:语义人物分割
这是今年最大的新增功能(06:53)。VNGeneratePersonSegmentationRequest 可以生成一张分割掩码,把画面中的人物从背景中分离出来。与传统的前景背景分割不同,Vision 实现的是语义分割——它知道什么是「人」,会把画面中所有人合并到同一个掩码中。
API 提供三个质量级别(09:06):
- accurate:最高质量,适合计算摄影
- balanced:平衡,适合逐帧视频处理
- fast:最快,适合实时流处理
质量越高,资源消耗越大。掩码的动态范围、分辨率、内存占用、处理时间都会随质量提升而增加。
多框架的人物分割能力
Person Segmentation 不仅在 Vision 中可用,还集成到了多个框架(14:15):
- AVFoundation:拍照时可以获取
AVCapturePhoto.portraitEffectsMatte,部分新款设备支持 - ARKit:
ARFrame.segmentationBuffer提供 AR 场景中的人物分割,需要 A12 仿生芯片及后续设备 - Core Image:
CIFilter.personSegmentation()提供纯 Core Image 域的接口
详细内容
人物分割请求配置
(08:13)
// 创建请求
let request = VNGeneratePersonSegmentationRequest()
// 创建请求处理器
let requestHandler = VNImageRequestHandler(url: imageURL, options: options)
// 执行请求
try requestHandler.perform([request])
// 获取结果
let mask = request.results!.first!
let maskBuffer = mask.pixelBuffer
关键点:
- 请求是状态对象,在视频流中需要复用同一个 request,有助于帧间平滑
- 结果是
VNPixelBufferObservation,pixelBuffer属性包含掩码数据
(08:33)
let request = VNGeneratePersonSegmentationRequest()
// 设置 revision(明确指定以避免未来 SDK 更新行为变化)
request.revision = VNGeneratePersonSegmentationRequestRevision1
// 设置质量级别
request.qualityLevel = VNGeneratePersonSegmentationRequest.QualityLevel.accurate
// 设置输出像素格式
request.outputPixelFormat = kCVPixelFormatType_OneComponent8
关键点:
- 显式设置 revision 保证行为确定性,否则 SDK 更新后会自动用最新 revision
- 三种质量级别在不同场景下的推荐:accurate 用于计算摄影,balanced 用于视频,fast 用于实时流
- 输出格式可选:8 位整数、32 位浮点、16 位浮点(half float)。16 位浮点可直接输入 GPU 处理
应用分割掩码替换背景
(12:24)
let input = CIImage(contentsOf: imageUrl)!
let mask = CIImage(cvPixelBuffer: maskBuffer)
let background = CIImage(contentsOf: backgroundImageUrl)!
// 缩放掩码到输入图像尺寸
let maskScaleX = input.extent.width / mask.extent.width
let maskScaleY = input.extent.height / mask.extent.height
let maskScaled = mask.transformed(by: CGAffineTransform(
maskScaleX, 0, 0, maskScaleY, 0, 0
))
// 缩放背景到输入图像尺寸
let backgroundScaleX = input.extent.width / background.extent.width
let backgroundScaleY = input.extent.height / background.extent.height
let backgroundScaled = background.transformed(by: CGAffineTransform(
backgroundScaleX, 0, 0, backgroundScaleY, 0, 0
))
// 使用混合滤镜
let blendFilter = CIFilter.blendWithRedMask()
blendFilter.inputImage = input
blendFilter.backgroundImage = backgroundScaled
blendFilter.maskImage = maskScaled
let blendedImage = blendFilter.outputImage
关键点:
- 掩码和背景都需要缩放到与输入图像相同的尺寸
CIFilter.blendWithRedMask()根据 red 通道掩码混合前景和背景- CIImage 初始化时如果是单通道 PixelBuffer,默认是 red 通道
AVCapture 中的分割掩码
(14:37)
private let photoOutput = AVCapturePhotoOutput()
if self.photoOutput.isPortraitEffectsMatteDeliverySupported {
self.photoOutput.isPortraitEffectsMatteDeliveryEnabled = true
}
// AVCapturePhoto 的分割掩码属性
open class AVCapturePhoto {
var portraitEffectsMatte: AVPortraitEffectsMatte? { get }
// nil 表示场景中没有人
}
关键点:
isPortraitEffectsMatteDeliverySupported检查设备是否支持- 启用后在拍照时自动计算分割掩码
AVPortraitEffectsMatte可用于后期处理
ARKit 中的分割掩码
(14:58)
// 检查是否支持人物分割
if ARWorldTrackingConfiguration.supportsFrameSemantics(.personSegmentationWithDepth) {
// 可以获取人物分割掩码
// ...
}
open class ARFrame {
var segmentationBuffer: CVPixelBuffer? { get }
}
关键点:
- 需要 A12 仿生芯片或更新设备(iPhone Xs 及后续)
supportsFrameSemantics检查特定设备是否支持.personSegmentationWithDepth同时提供分割掩码和深度信息
Core Image 中的分割
(15:31)
let input = CIImage(contentsOf: imageUrl)!
let segmentationFilter = CIFilter.personSegmentation()
segmentationFilter.inputImage = input
let mask = segmentationFilter.outputImage
关键点:
CIFilter.personSegmentation()是 Vision API 的薄封装- 适合需要完全在 Core Image 域处理的场景
- 输出是 CIImage,可以直接用于其他 Core Image 滤镜
核心启发
1. 虚拟背景视频通话 App
- 做什么:类似 Zoom 的虚拟背景功能,让用户在视频通话时替换背景
- 为什么值得做:Person Segmentation 支持多平台,
balanced质量级别可在实时视频流中运行 - 怎么开始:用
AVCaptureVideoDataOutput获取视频帧,每帧执行VNGeneratePersonSegmentationRequest(qualityLevel = .balanced),用掩码混合背景图像
2. 人脸姿态控制的交互界面
- 做什么:用头部姿态控制 UI,比如转头翻页、点头确认
- 为什么值得做:连续值的面部姿态指标让控制更精确,不像离散值那样跳跃
- 怎么开始:用
VNDetectFaceRectanglesRequest的roll、yaw、pitch属性,设置阈值触发对应动作
3. 智能照片编辑 App
- 做什么:自动识别人物并提供人物专属的编辑效果(比如背景虚化、背景替换)
- 为什么值得做:Person Segmentation 的
accurate模式质量高,适合照片编辑场景 - 怎么开始:用
VNGeneratePersonSegmentationRequest的accurate质量,配合 Core Image 的CIFilter.portraitEffect()实现人物光效
4. AR 社交 App 的人物遮挡
- 做什么:在 AR 场景中,真实人物可以遮挡虚拟物体,增强真实感
- 为什么值得做:ARKit 的
personSegmentationWithDepth同时提供掩码和深度,可实现更精确的遮挡效果 - 怎么开始:检查
supportsFrameSemantics(.personSegmentationWithDepth),从ARFrame.segmentationBuffer获取掩码用于渲染
关联 Session
- Classify hand poses and actions with Create ML — 手势分类基于 Vision 的手部关键点检测,两者配合实现手势识别
- Extract document data using Vision — Vision 的文档识别能力,与人体分析互补扩展 Vision 的应用场景
- Build dynamic iOS apps with the Create ML framework — Create ML 模型训练可与 Vision 的检测结合
- Understanding Images in Vision Framework — WWDC19 的 Vision 基础,了解 Vision 框架的整体架构
评论
GitHub Issues · utterances