人脸识别之CoreImage

前段时间研究人脸识别,正好也在学习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受到容器的限制,可能拉伸或者压缩,所以坐标转换后还需要根据比例来计算出人脸实际显示的大小,然后再加框框。

总结

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 2018-09-04更新: 很久没有更新文章了,工作之余花时间看了之前写的这篇文章并运行了之前写的配套Demo,通...
    Mr_Victory阅读 27,759评论 50 171
  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,026评论 3 119
  • 2018-05-14 周一 太原市初三二模首日 今天是一个值得记录的日子,并不是因为是二模考试的第一天,而...
    龙城女子阅读 2,065评论 0 1
  • 距离小自班结束,还有两天了。每天惦记着交作业的日子,就要过去了。有时晚上想看个剧,可一想还有作业要做,等看完就哈欠...
    小自班048明诗阅读 215评论 0 0