美文网首页
人脸识别之CoreImage

人脸识别之CoreImage

作者: melody5 | 来源:发表于2018-07-06 16:18 被阅读20次

    前段时间研究人脸识别,正好也在学习swift,所以真好都总结一下。

    步骤;

    1. 创建特征检测器CIDetector,检测类型人脸,高精度。
    2. 调用检测器的featuresInImage方法,传入图片,会得到一个人脸的数组。
    3. 遍历人脸数组,转为CIFaceFeature类型,并根据其各个特征点进行操作,比如人脸,眼睛等位置。

    下面是我的demo,就一个imageView和一个按钮,点击按钮开始检测,检测到人脸后,在脸上加一个红色的框。

    检测前:

    image.png

    检测后

    image.png

    看一下,点击检测按钮做了什么:

        @IBAction func detect(_ sender: Any) {
            // 取出照片并将其转换为CIImage,使用Core Image时需要用CIImage
            guard let picture = CIImage(image: pictureView.image!) else {
                return
            }
            // 选择高精度
            let accuracy = [CIDetectorAccuracy:CIDetectorAccuracyHigh]
            // 这里定义了一个属于CIDetector类的faceDetector变量,并输入之前创建的accuracy变量
            let faceDetector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: accuracy)
            // 调用faceDetector的featuresInImage方法,识别器会找到所给图像中的人脸,最后返回一个人脸数组
            let faces = faceDetector?.features(in: picture)
            
            // 计算转换坐标系的transform(这里取出来的size是图片的原始尺寸)
            let ciImageSize = picture.extent.size
            var transform = CGAffineTransform(scaleX: 1, y: -1)
            transform = transform.translatedBy(x: 0, y: -ciImageSize.height)
            
            // 遍历faces数组,把人脸数据转换为CIFaceFeature类型
            for face in faces as! [CIFaceFeature] {
                print("发现人脸坐标= \(face.bounds)")
                // 通过上边transform转换face的坐标
                var faceViewBounds = face.bounds.applying(transform)
                
                // 由于图片的宽高比例可能会随着容器pictureView的zize而被压缩或者拉伸,这里计算框框在pictureView中的实际大小和位置
                let viewSize = pictureView.bounds.size
                let scale = min(viewSize.width / ciImageSize.width, viewSize.height / ciImageSize.height)
                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 faceCase = UIView(frame: faceViewBounds)
                faceCase.layer.borderWidth = 3
                faceCase.layer.borderColor = UIColor.red.cgColor
                faceCase.backgroundColor   = UIColor.clear
                pictureView.addSubview(faceCase)
                
                print("转换后人脸坐标= \(faceCase.frame)")
                
                if face.hasLeftEyePosition {
                    print("左眼位置=\(face.leftEyePosition)")
                }
                if face.hasRightEyePosition {
                    print("右眼位置=\(face.rightEyePosition)")
                }
                if face.hasMouthPosition {
                    print("检测到嘴巴=\(face.mouthPosition)")
                }
                if face.hasFaceAngle {
                    print("人脸旋转角度=\(face.faceAngle)")
                }
            }
    
        }
    
    image.png

    坐标转换

    其中涉及到一个UIKit和CoreImage的坐标转换,UIKit的坐标是左上角为顶点(0,0)向右下方展开,而CoreImage是以左下角为顶点(0,0)向右上方展开的,如图所示:


    image.png

    由于取出来的CIImage图片是原始尺寸,但是图片真实显示出来的size受到容器的限制,可能拉伸或者压缩,所以坐标转换后还需要根据比例来计算出人脸实际显示的大小,然后再加框框。

    总结

    还有些特征点可以检测,但是我试了一下,不是特别好使,总是检测不到,比如微笑和闭眼的状态,如果你发现了问题所在,请告诉我,谢谢。
    参考文章

    相关文章

      网友评论

          本文标题:人脸识别之CoreImage

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