Vision Kit实时摄像头人脸检测如何实现人脸区域模糊效果
实时Vision人脸检测区域模糊实现方案
核心实现逻辑是用GPU加速的Core Image高斯模糊层搭配形状遮罩,不需要插入额外的UIView,性能可以稳定撑住30/60帧的实时摄像头流,不会出现明显掉帧或延迟。
1. 调整图层初始化逻辑
修改你现有的setupVisionDrawingLayers()方法,在人脸描边图层下方插入专门的模糊图层,注意图层层级顺序:模糊层在最底部,往上依次是人脸矩形描边层、人脸关键点描边层,避免描边线条被模糊覆盖。
在原有创建overlayLayer之后、创建faceRectangleShapeLayer之前,插入模糊层初始化代码:
// 初始化人脸模糊层 let faceBlurLayer = CALayer() faceBlurLayer.name = "FaceBlurLayer" faceBlurLayer.bounds = captureDeviceBounds faceBlurLayer.anchorPoint = normalizedCenterPoint faceBlurLayer.position = captureDeviceBoundsCenterPoint // 配置高斯模糊参数,radius值越大模糊强度越高,12-20区间适合人脸打码场景 let gaussianBlur = CIFilter(name: "CIGaussianBlur") gaussianBlur?.setValue(15, forKey: kCIInputRadiusKey) faceBlurLayer.filters = gaussianBlur == nil ? [] : [gaussianBlur!] // 绑定预览层内容作为模糊源,如果你是自己处理SampleBuffer自定义渲染预览,后续逐帧把当前帧的CGImage赋值给faceBlurLayer.contents即可 faceBlurLayer.contents = self.previewLayer.contents overlayLayer.addSublayer(faceBlurLayer) // 持有模糊层引用,方便后续更新 self.faceBlurLayer = faceBlurLayer
记得在类中补充对应的属性声明:
fileprivate var faceBlurLayer: CALayer?
2. 逐帧更新模糊区域遮罩
在你原有的Vision人脸检测结果回调里(也就是每次拿到VNFaceObservation、更新人脸矩形和关键点路径的位置),给模糊层设置形状遮罩,只有遮罩覆盖的区域才会显示模糊效果:
// 1. 生成你需要的模糊区域路径,和你原有绘制人脸轮廓用的坐标转换逻辑完全一致即可 let blurMaskPath = UIBezierPath() // 👉 选项A:模糊整个检测到的人脸矩形框 blurMaskPath.append(UIBezierPath(rect: convertedFaceBoundingRect)) // 👉 选项B:精准贴合人脸外轮廓模糊(效果更自然),用faceContour landmark点生成闭合路径即可 // if let faceContour = faceObservation.landmarks?.faceContour { // // 这里的坐标转换逻辑和你原来画人脸关键点的逻辑完全一致 // let contourPoints = convertNormalizedPoints(faceContour.pointsInImage(imageSize: captureDeviceResolution), to: captureDeviceBounds) // blurMaskPath.move(to: contourPoints.first!) // contourPoints.dropFirst().forEach { blurMaskPath.addLine(to: $0) } // blurMaskPath.close() // } // 2. 给模糊层设置遮罩 let maskLayer = CAShapeLayer() maskLayer.path = blurMaskPath.cgPath maskLayer.fillColor = UIColor.black.cgColor faceBlurLayer?.mask = maskLayer faceBlurLayer?.isHidden = false
避坑说明
- 不要用
UIVisualEffectView实现实时模糊:这个组件是为静态UI场景设计的,在实时摄像头流高帧率渲染场景下会有明显的延迟和掉帧,直接给CALayer挂CIFilter的方案走GPU渲染,性能开销低很多。 - 模糊层内容必须和预览帧同步:如果你是通过
AVCaptureVideoDataOutput逐帧拿SampleBuffer自定义渲染预览,每次拿到新帧的时候,记得把帧转成CGImage同步赋值给faceBlurLayer.contents,避免模糊内容和实际画面错位、拖影。 - 坐标转换必须对齐:生成模糊遮罩路径的坐标转换逻辑,要和你原来绘制人脸矩形、关键点的逻辑完全一致,否则模糊区域会和人脸位置偏移。
- 无人脸检测结果时记得隐藏模糊层:检测不到人脸的时候把
faceBlurLayer.isHidden设为true,避免画面上出现无意义的模糊块。
内容的提问来源于stack exchange,提问作者martin wotterman
相关产品推荐
相关产品推荐

