美文网首页
AVFoundation 实现人脸识别

AVFoundation 实现人脸识别

作者: 陈雨尘 | 来源:发表于2021-02-07 17:48 被阅读0次

    接着之前的视频采集之后今天聊下人脸识别,现在很多拍摄工具中的美颜,激萌效果等 都需要用到人脸识别。人脸识别的方案有CoreImage、 face++、OpenCV、libefacedetection、AV Foundation、vision 等,本文主要聊下AVFoundation 在视频拍摄中对人脸的捕捉。

    大体流程如下

    • AVCaptureSessin 设置AVCaptureMetadataOutput 捕获元数据输出
    • 设置元数据类型为 AVMetadataObjectTypeFace
    • setMetadataObjectsDelegate 设置回调代理
    • didOutputMetadataObjects 回调中 让人脸信息传给AVCaptureVideoPreviewLayer
    • AVCaptureVideoPreviewLayer 上显示对应的人脸信息

    1.AVCaptureSessin 设置AVCaptureMetadataOutput

    这里要注意人脸检测要使用到硬件加速所以要放到主线程中

        // AVCaptureMetadataOutput 用于处理捕获会话AVCaptureSession产生的定时元数据的捕获输出。
        self.metadataOutput = [[AVCaptureMetadataOutput alloc]init];
        if ([self.captureSession canAddOutput:self.metadataOutput]) {
            [self.captureSession addOutput:self.metadataOutput];
            
            // 获取人脸 属性  也可以是二维码 条形码等
            NSArray *metadatObjectTypes = @[AVMetadataObjectTypeFace];
             //设置metadataObjectTypes 指定对象输出的元数据类型。
             self.metadataOutput.metadataObjectTypes = metadatObjectTypes;
               //创建主队列: 因为人脸检测用到了硬件加速,而且许多重要的任务都在主线程中执行,所以需要为这次参数指定主队列。
               dispatch_queue_t mainQueue = dispatch_get_main_queue();
               //通过设置AVCaptureVideoDataOutput的代理,就能获取捕获到一帧一帧数据
            [self.metadataOutput setMetadataObjectsDelegate:self queue:mainQueue];
      
        }
    
    

    2.AVCaptureMetadataOutputObjectsDelegate 捕捉代理回调
    将捕捉的人脸信息传给显示的层的layer(这里是只做人脸的一个框选,其他功能跟脸部信息有关的实现也都可在这个回调中)

    - (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputMetadataObjects:(NSArray *)metadataObjects
           fromConnection:(AVCaptureConnection *)connection {
    
        NSLog(@"有输出的");
        //使用循环,打印人脸数据
        for (AVMetadataFaceObject *face in metadataObjects) {
            
            NSLog(@"Face detected with ID:%li",(long)face.faceID);
            NSLog(@"Face detected with rollAngle:%f",face.rollAngle);
            NSLog(@"Face detected with yawAngle:%f",face.yawAngle);
            NSLog(@"Face bounds:%@",NSStringFromCGRect(face.bounds));
            
        }
        
        //将元数据 传递给 previewView.m   将元数据转换为layer
        [self.PreView didDetectFaces:metadataObjects];
    
    }
    

    3.AVCaptureVideoPreviewLayer 人脸信息的渲染

    这里涉及到3个点 1.人脸位置跟layer上位置的转化transformedMetadataObjectForMetadataObject:这里跟上一篇中的摄像头聚焦时候的位置转化很像 2.人脸的rollAngle 和 yawAngle 转化成对应的angle(角度) 3.这里的faceID对于同一个人并不是唯一的,但如果是一直在采集中没有出过采集框就是唯一的

    - (void)didDetectFaces:(NSArray *)faces{
       //创建一个本地数组 保存转换后的人脸数据
        NSArray *transformedFaces = [self transformedFacesFromFaces:faces];
           //获取faceLayers的key,用于确定哪些人移除了视图并将对应的图层移出界面。
        /*
            支持同时识别10个人脸
         */
        NSMutableArray *lostFaces = [self.faceLayers.allKeys mutableCopy];
          //遍历每个转换的人脸对象
        for (AVMetadataFaceObject *face in transformedFaces) {
             //获取关联的faceID。这个属性唯一标识一个检测到的人脸
            NSNumber *faceID = @(face.faceID);
             //将对象从lostFaces 移除
            [lostFaces removeObject:faceID];
              //拿到当前faceID对应的layer
            CALayer *layer = self.faceLayers[faceID];
              //如果给定的faceID 没有找到对应的图层
            if (!layer) {
                 //调用makeFaceLayer 创建一个新的人脸图层
                layer = [self makeFaceLayerWith:face.bounds.size];
                 //将新的人脸图层添加到 overlayLayer上
                [self.overlayLayer addSublayer:layer];
                  //将layer加入到字典中
                self.faceLayers[faceID] = layer;
             }
            
            //设置图层的transform属性 CATransform3DIdentity 图层默认变化 这样可以重新设置之前应用的变化
            layer.transform = CATransform3DIdentity;
              //图层的大小 = 人脸的大小
            layer.frame = face.bounds;
             //判断人脸对象是否具有有效的斜倾交。 头部向肩膀方向的侧斜角度
            if (face.hasRollAngle) {
                  //如果为YES,则获取相应的CATransform3D 值
                CATransform3D t = [self transformForRollAngle:face.rollAngle];
                   //将它与标识变化关联在一起,并设置transform属性
                layer.transform = CATransform3DConcat(layer.transform, t);
            }
               //判断人脸对象是否具有有效的偏转角 人脸绕y轴旋转的角度
            if (face.hasYawAngle) {
                  //如果为YES,则获取相应的CATransform3D 值
                CATransform3D  t = [self transformForYawAngle:face.yawAngle];
                layer.transform = CATransform3DConcat(layer.transform, t);
                
            }
        }
        //遍历数组将剩下的人脸ID集合从上一个图层和faceLayers字典中移除
        for (NSNumber *faceID in lostFaces) {
            CALayer *layer = self.faceLayers[faceID];
            [layer removeFromSuperlayer];
            [self.faceLayers  removeObjectForKey:faceID];
        }
        
    }
    
    

    按照这个思路就可以看到人脸的标记了,这里要涉及到最基础的视频采集可以看上一篇 AVFoundation 视频拍摄
    人脸信息拿出来之后可以做很多事情,比如人脸数据匹配,活体检测,激萌效果等等。对应代码也上传的git上 AVFoundation 人脸识别

    相关文章

      网友评论

          本文标题:AVFoundation 实现人脸识别

          本文链接:https://www.haomeiwen.com/subject/rqiztltx.html