swift 人脸识别相关

因为 基于GPUImage 的对象处理

方式一 基于系统 AVCaptureMetadataOutput  效率比较低

  lazy var myVideo: GPUImageVideoCamera = {
        //初始化相机,第一个参数表示相册的尺寸,第二个参数表示前后摄像头
        let  myVideo:GPUImageVideoCamera = GPUImageVideoCamera.init(sessionPreset: AVCaptureSession.Preset.high.rawValue, cameraPosition: AVCaptureDevice.Position.back)
        //设置竖屏
        
        myVideo.outputImageOrientation = UIInterfaceOrientation.portrait
        // 设置前置摄像头和后置摄像头是否进行镜像
        myVideo.horizontallyMirrorRearFacingCamera = false
        myVideo.horizontallyMirrorFrontFacingCamera = true
        //竖屏方向
        myVideo.outputImageOrientation = .portrait
        //添加音频//该句可防止允许声音通过的情况下,避免录制第一帧黑屏闪屏(====)
        myVideo.addAudioInputsAndOutputs()
        myVideo.delegate = self
        //设置帧数
        //        myVideo.frameRate = 60
      
       //人脸识别部分代码
        let metaDataOutput = AVCaptureMetadataOutput()
        if myVideo.captureSession.canAddOutput(metaDataOutput){
            myVideo.captureSession.addOutput(metaDataOutput)
            let supportTypes = metaDataOutput.availableMetadataObjectTypes
            if supportTypes.contains(AVMetadataObject.ObjectType.face){
                /*

                 [metaDataOutput setMetadataObjectTypes:@[AVMetadataObjectTypeFace]];
                 [metaDataOutput setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
                 */
                metaDataOutput.metadataObjectTypes = [AVMetadataObject.ObjectType.face]
                metaDataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            }
        }
        
        return myVideo
    }()

 

代理方法  GPUImageVideoCameraDelegate 计算出来的坐标基于 图片原始大小 所以需要 自己转换 我这里没有转换

 func metadataOutput(_ output: AVCaptureMetadataOutput, didOutput metadataObjects: [AVMetadataObject], from connection: AVCaptureConnection) {
        if metadataObjects.count != 0 {
            DDLOG(message:"数量:\(metadataObjects.count)")
            //AVMetadataObject 对象
            let faceObjc:AVMetadataFaceObject = metadataObjects.first! as! AVMetadataFaceObject
            
            let faceID = faceObjc.faceID
            
            let bounds = faceObjc.bounds
            
            let rollAngle = faceObjc.rollAngle   //侧倾角  手机翻转的角度
            
            let yawAngle = faceObjc.yawAngle   //偏转角  脸部偏转角度 正对着为 0度
          
            
            
            DDLOG(message: faceObjc)
            
            let x = DeviceMaxWidth * bounds.origin.x
            let y = DeviceMaxHeight * bounds.origin.y
            let w = DeviceMaxWidth * bounds.size.width
            let h = DeviceMaxHeight * bounds.size.height
           
        }else{
             DDLOG(message: "没找到人脸")
        }
    }

方法二  基于 CIImage

简介 (网上copy 的 )

CoreImage framework组成

Apple 已经帮我们把image的处理分类好,来看看它的结构:

core Image.png


主要分为三个部分:

  • 定义部分:CoreImage 和CoreImageDefines。见名思义,代表了CoreImage 这个框架和它的定义。
  • 操作部分:
    • 滤镜(CIFliter):CIFilter 产生一个CIImage。典型的,接受一到多的图片作为输入,经过一些过滤操作,产生指定输出的图片。
    • 检测(CIDetector):CIDetector 检测处理图片的特性,如使用来检测图片中人脸的眼睛、嘴巴、等等。
    • 特征(CIFeature):CIFeature 代表由 detector处理后产生的特征。
  • 图像部分:
    • 画布(CIContext):画布类可被用与处理Quartz 2D 或者 OpenGL。可以用它来关联CoreImage类。如滤镜、颜色等渲染处理。
    • 颜色(CIColor): 图片的关联与画布、图片像素颜色的处理。
    • 向量(CIVector): 图片的坐标向量等几何方法处理。
    • 图片(CIImage): 代表一个图像,可代表关联后输出的图像。

在了解上述基本知识后,我们开始通过创建一个工程来带大家一步步验证Core Image的人脸识别特性。

人脸监测的步骤是:先获取图像,然后转成CIImage格式,利用CIFeature特征,使用探测器CIDetector拿到所有的人脸,然后在图中圈出,即可达到人脸识别的目的,关键代码如下:

 override func viewDidLoad() {
        super.viewDidLoad()
        
       
        
        
        
        let  imgView = UIImageView.init(frame: CGRect.init(x: 0, y: 0, width: DeviceMaxWidth, height: DeviceMaxHeight))
        imgView.image = image
        imgView.contentMode  = UIViewContentMode.scaleAspectFit
        self.view.addSubview(imgView)
        let ciImage = CIImage.init(image: image)
        let faceDetector:CIDetector = CIDetector.init(ofType: CIDetectorTypeFace, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyLow,CIDetectorTracking:true])!
        let featureArray:[CIFeature] = faceDetector.features(in: ciImage!)
        DDLOG(message: "识别个数:\(featureArray.count)")
        /*
         
         人脸识别是在原始图像上进行的,由于原始图像的分辨率比image view要高,因此需要设置image view的content mode为aspect fit(保持纵横比的情况下缩放图片)。为了合适的绘制矩形框,需要计算image view中人脸的实际位置与尺寸
         还要注意的是,CoreImage与UIView使用两种不同的坐标系统(看下图),因此要实现一个CoreImage坐标到UIView坐标的转换。
         */
        // 转换坐标系
        let ciImageSize = ciImage?.extent.size
        var transform = CGAffineTransform(scaleX: 1, y: -1)
        transform = transform.translatedBy(x: 0, y: -CGFloat((ciImageSize?.height)!))
        
        for index in 0..<featureArray.count {
            let face:CIFaceFeature = featureArray[index] as! CIFaceFeature
            
            
            // 应用变换转换坐标
            var faceViewBounds = face.bounds.applying(transform)
//            //获取转换后的坐标
//            let faceBounds = self.transform(bgView: imgView, ciImage: ciImage, transfromRect: faceViewBounds)
            
            // 在图像视图中计算矩形的实际位置和大小
            let viewSize = imgView.bounds.size
            //计算宽高比例
            let scale = min(viewSize.width / (ciImageSize?.width)!, viewSize.height / (ciImageSize?.height)!)
            
            //放在imageview 之后 图片相对于背景 的 x y 坐标
            let offsetX = (viewSize.width - (ciImageSize?.width)! * scale) / 2
            let offsetY = (viewSize.height - (ciImageSize?.height)! * scale) / 2
            
            //获取缩放后的 脸部位置坐标
            faceViewBounds = faceViewBounds.applying(CGAffineTransform(scaleX: scale, y: scale))
            faceViewBounds.origin.x += offsetX
            faceViewBounds.origin.y += offsetY

            
            let faceVIew = UIView.init(frame: faceViewBounds)
            faceVIew.layer.borderWidth = 1
            faceVIew.layer.borderColor = UIColor.red.cgColor
            faceVIew.backgroundColor = UIColor.clear
            imgView.addSubview(faceVIew)
            
            DDLOG(message:"111\(imgView.bounds)" )
            DDLOG(message:"222\(String(describing: ciImage?.extent.size))" )
            DDLOG(message:"脸部相对于原始图片位置\(face.bounds)" )
            DDLOG(message:"脸部相对于 转换后图片位置\(faceViewBounds)" )
            
            if face.hasLeftEyePosition {
               //左眼位置
                print("左眼位置 \(face.leftEyePosition)")
                // 应用矩阵变换转换坐标
                let leftEyesPoint = face.leftEyePosition.applying(transform)
                //缩放后坐标
                var leftEyesScalPoint = leftEyesPoint.applying(CGAffineTransform(scaleX: scale, y: scale))
                
                leftEyesScalPoint.x += offsetX
                leftEyesScalPoint.y += offsetY
                
                
                let leftEyesVIew = UIView.init(frame: CGRect.init(origin: leftEyesScalPoint, size: CGSize(width: 20, height: 20)))
             
                leftEyesVIew.layer.cornerRadius = leftEyesVIew.width/2
                leftEyesVIew.layer.borderWidth = 1
                leftEyesVIew.layer.borderColor = UIColor.red.cgColor
                leftEyesVIew.backgroundColor = UIColor.clear
                imgView.addSubview(leftEyesVIew)
                
            }
            
            if face.hasRightEyePosition {
                //右眼位置
                print("右眼位置 \(face.rightEyePosition)")
                // 应用矩阵变换转换坐标
                let rightEyesPoint = face.rightEyePosition.applying(transform)
                //缩放后坐标
                var rightEyesScalPoint = rightEyesPoint.applying(CGAffineTransform(scaleX: scale, y: scale))
                
                rightEyesScalPoint.x += offsetX
                rightEyesScalPoint.y += offsetY
                let rightEyesVIew = UIView.init(frame: CGRect.init(origin: rightEyesScalPoint, size: CGSize(width: 20, height: 20)))
                
                rightEyesVIew.layer.cornerRadius = rightEyesVIew.width/2
                rightEyesVIew.layer.borderWidth = 1
                rightEyesVIew.layer.borderColor = UIColor.red.cgColor
                rightEyesVIew.backgroundColor = UIColor.clear
                imgView.addSubview(rightEyesVIew)
            }
            if face.leftEyeClosed {
                //左眼闭着
                print("左眼闭着")
            }
            
            if face.rightEyeClosed {
                //右眼闭着
                print("右眼闭着")
            }
            
            if face.hasMouthPosition {
                //嘴巴位置
                print("嘴巴位置e \(face.mouthPosition)")
                
                // 应用矩阵变换转换坐标
                let mouthPoint = face.mouthPosition.applying(transform)
                //缩放后坐标
                var mouthScalPoint = mouthPoint.applying(CGAffineTransform(scaleX: scale, y: scale))
                
               mouthScalPoint.x += offsetX
               mouthScalPoint.y += offsetY
                

                let mouthVIew = UIView.init(frame: CGRect.init(origin:mouthScalPoint, size: CGSize(width: 30, height: 30)))
               mouthVIew.layer.borderWidth = 1
               mouthVIew.layer.borderColor = UIColor.red.cgColor
               mouthVIew.backgroundColor = UIColor.clear
                
                imgView.addSubview(mouthVIew)
            }
            if face.hasSmile {
                //是否微笑
                print("在微笑")
            }

            if face.hasFaceAngle {
                //人脸角度
                print("人脸角度 \(face.faceAngle)")
            }
            if face.hasTrackingID {
                //获取追踪对象
                print("获取追踪对象ID \(face.trackingID)")
            }
            if face.hasTrackingFrameCount {
                //获取追踪对象个数
                print("获取追踪对象个数 \(face.hasTrackingFrameCount)")
            }
        }
        
        let backbtn = UIButton.init(frame: CGRect.init(x: 15, y:20, width: 30, height: 30))
        backbtn.setTitleColor(UIColor.red, for: .normal)
        backbtn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
        backbtn.setTitle("返回", for: .normal)
        backbtn.addTarget(self, action: #selector(btnEvent1), for: .touchUpInside)
        backbtn.tag = 0
        self.view.addSubview(backbtn)
    }
    

 

转载于:https://my.oschina.net/iceTear/blog/1607876

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在iOS上进行人脸识别并抠取人脸的方法可以使用Core Image框架中的CIDetector类。通过以下代码可以实现人脸识别和抠取人脸的功能: ```swift func detectFace(withImage image: UIImage) { // 将图像转为CIImage,使用Core Image需要使用CIImage guard let personCIImg = CIImage(image: image) else { return } // 设置识别精度 let opts: \[String: Any\] = \[CIDetectorAccuracy: CIDetectorAccuracyHigh\] // 初始化识别器 let detector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: opts) let result: \[CIFaceFeature\] = (detector?.features(in: personCIImg, options: opts) as? \[CIFaceFeature\])! if result.count > 0 { for face in result { let faceBox = UIView(frame: face.bounds) // 画一个红框画出面部位置 faceBox.layer.borderWidth = 3 faceBox.layer.borderColor = UIColor.red.cgColor faceBox.backgroundColor = UIColor.clear // 添加红框到图片上 imgView.addSubview(faceBox) print("面部坐标------> %d ", faceBox.frame) } } } ``` 这段代码会将传入的UIImage对象转换为CIImage对象,然后使用CIDetector进行人脸识别。识别到的人脸会通过在UIImageView上添加红色边框的方式进行标记。你可以根据需要对这段代码进行修改和扩展,以满足你的具体需求。 #### 引用[.reference_title] - *1* *2* [ios人脸识别_适用于Android和iOS的10种最佳人脸识别应用程序](https://blog.csdn.net/cumian8165/article/details/108160585)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [iOS人脸识别Demo](https://blog.csdn.net/kangpengpeng1/article/details/79197201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值