iOS AI相机App开发教程,02 实现瘦脸功能

瘦脸功能实现原理瘦脸

瘦脸功能实现原理

iOS AI相机App开发教程,02 实现瘦脸功能

瘦脸

人脸检测

首先需要对照片进行人脸检测,检测出人脸轮廓位置。人脸检测的方法非常多。在“魔法相机”中使用了 iOS Vision 库中的 VNDetectFaceLandmarksRequest 方法来进行人脸检测。使用这个方法可以充分利用iPhone的AI能力,并且检测效果也非常好。

MLS图像变形算法

MLS变形算法又叫做移动最小二乘变形算法,该算法引用量较高,效果相对较好,在变形过程中几乎毫无违和感,这也是MLS的优势所在。

MLS变形算法在美颜中的人脸变形特效或者图像变形特效中有着较多的应用,比如“天天P图”中的疯狂换脸特效,就是以MLS变形为基础开发设计的。”魔法相机“的瘦脸功能和变老功能也使用了MLS算法。

实现原理

使用人脸检测获得人脸眼睛到下巴的轮廓点,并在图片边缘进行锚点,然后通过MLS变形,将人像下半部分的脸和下巴的锚点做适当的收缩。

代码讲解

// 瘦脸特效方法func DoFaceThin(uiImage: UIImage, completionHandler: @escaping CompletionHandle) {        let image = CIImage(image: uiImage)        let weakSelf = self        let width = uiImage.size.width        let height = uiImage.size.height                // 人脸检测完成回调方法        let faceRequest = VNDetectFaceLandmarksRequest() { request, error in            guard let results = request.results as? [VNFaceObservation] else {             ...            }            let face = results.first             ...            guard let boundingRect = face?.boundingBox else {               ...            }           // 获得人脸位置盒子            var boundingBox = CGRect(x:CGFloat(boundingRect.origin.x * width),                                     y:CGFloat(height - ((boundingRect.origin.y + boundingRect.size.height) * height)),                                     width: CGFloat(boundingRect.size.width * width),                                     height: CGFloat(boundingRect.size.height * height))            // 锚点坐标            var points: [CGPoint] = []            // 变换后坐标            var toPoints: [CGPoint] = []            // 将人脸轮廓点添加到锚点数组中            for point in face!.landmarks!.faceContour!.normalizedPoints {               let p = CGPoint(x: CGFloat(point.x * boundingBox.width + boundingBox.origin.x),                               y: CGFloat((1.0 - point.y) * boundingBox.height + boundingBox.origin.y))                points.append(p)                toPoints.append(p)            }                        // 将图片边缘添加到锚点数组里            for i in stride(from: 0, to: Int(height) ,by: 80) {                let p1 = CGPoint(x: 0, y:CGFloat(i))                let p2 = CGPoint(x: width, y:CGFloat(i))                points.append(p1)                toPoints.append(p1)                points.append(p2)                toPoints.append(p2)            }            // 将图片四角添加到锚点列表中            let bottomLeft = CGPoint(x: 0, y: height)            let bottomRight = CGPoint(x: width, y: height)            points.append(bottomLeft)            toPoints.append(bottomLeft)            points.append(bottomRight)            toPoints.append(bottomRight)                        // 对人脸轮廓进行收缩,实现瘦脸效果            for index in 1...6 {                let idx1 = 8 - index                let idx2 = 8 + index                                let w = points[idx1].x - points[idx2].x                                let padding = w/CGFloat(8+index*2)/2                                toPoints[idx1].x -= padding                toPoints[idx2].x += padding            }                        // MLS 变换实例,传入锚点和目标点坐标,对图片进行变换            let thinFaceOperation = ThinFaceOperation()            thinFaceOperation.setupData(image: uiImage, landmarks: points, toPoints: toPoints)                        let imageInput = PictureInput(image: uiImage)                        let imageOutput = PictureOutput()            imageOutput.imageAvailableCallback = { image in                completionHandler(image)                weakSelf.lockFx.unlock()            }                        imageInput --> thinFaceOperation --> imageOutput            imageInput.processImage(synchronously:true)        }                // 执行人脸检测        let handler = VNImageRequestHandler(ciImage: image!,options: [:])        DispatchQueue.global(qos: .userInitiated).async {            try? handler.perform([faceRequest])        }    }

MSL变换需要两组数据,分别是锚点(原始点)的坐标位置数组和目标点(变换后的点)的坐标位置数组。
实现 VNDetectFaceLandmarksRequest 回调方法,在回调中处理人脸数据。
将图片的边缘和4角坐标也都传入锚点和目标点数组,这样可以防止图片边缘因为MSL变换产生畸变。
将人类数据传入锚点和目标点数组,并处理目标点坐标,使脸部收缩变瘦。
最后调用MSL方法实例,完成变换操作。

瘦脸特效完整代码 MagicCamera/Vision/ThinFace.swift

MSL算法的具体实现可以看源码文件: MagicCamera/Vision/MlsOperation/MovingLeastSquareHelper.mm

魔法相机项目

系列教程: 魔法相机 - 文集 - 简书

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/70047.html

(0)

相关推荐

  • 美国黑客入侵Booking.com 公司管理层却对此保持沉默

    2016年初,一名美国黑客闯入酒店网站Booking.com的服务器,盗取了中东地区国家数千家酒店的预订细节。经过两个月的研究,四名Booking.com的IT专家确定,该黑客是一名与美国情报部门关系密切的人。

    科技 2021年11月14日
  • 大学生为什么要参加军事训练,军事化训练对孩子的影响

    其实我想小孩子对与很多家长都是比较头疼的,生活懒散,爱玩手机平板,不听话等。其实这是每一个家长都无法避免的问题,正是因为孩子这些问题的出现所以才有了军事化训练孩子。其实很多人都会问这种训练到底有没有用,值不值得去,这个钱花得值不值?其实我从一个客观角度去分析,并不是去了就真的能改变孩子坏毛病了,我觉得这种训练完全是针对个人本身的,有些小孩子就是调皮,你不可能10来天的训练就完全教导过来,所以那我们为什么还要花这个钱送孩子过去呢?这不是浪费钱吗?在这里我想说,真的浪费了吗?不!肯定没有浪费。一个小孩子从小到18岁其实都是在一个固定环境长大,他没有接触更多脱离家庭,学校以外的社会,所以他们的陋习只会逐渐根蒂。从而你可以想想大人自己本身,你是什么时候成长的?懂事的?其实这不是在某一个固定的时间段,而是你经历多了你才会成长,你经历了各种酸甜苦辣才成就今天的你,所以在固定环境成长的孩子他没有机会去接触更多东西,而夏令营这种军事化训练其实就是孩子的一种脱离固定生活的经历,他能看到更多,感受到更多,正是因为这种经历会让他想得更多。其实家长也不用每年都送孩子去参加,只要让孩子去体验一次,哪怕一次就够了,至少这是他们经历过了,感受过了,至于其他就交给时间,交给孩子,交给父母,交给社会了!

    生活 2021年11月17日
  • 用漫画讲科学方法一看就全明白了(漫画你不知道的科学小实验)

    在如今的数字时代,科学早已成为每一个孩子的必修课。但是,当我们自己听到“最速降线问题”“费马大定理”“微积分”“UNIX”这些“高深”的词汇时,脑子可能一下子就转晕了。我们尚如此,那怎样才能让孩子初步理解这些科学定理和概念,并爱上科学呢?这本《十分钟漫画科学史》或许可以做到这一点。

    生活 2021年12月15日
  • 2012年上半年全国进出口贸易总额约为多少万亿美元,2013年中国货物进出口总额41600亿美元

    疫情期间,作为全球最大贸易国的中国发挥了强大供给能力,以出口的方式填补全球供需缺口。就在刚刚,中国又交出了一份亮眼的外贸成绩单。

    生活 2021年11月8日
  • 文石发布25.3英寸墨水屏显示器,3K分辨率,售价8999元

    墨水屏在我们印象中,更多的用于掌上电子书使用,它可以避免液晶屏所带来的蓝光、频闪、高亮度、强刺激等问题。不过,近日文石发布了一款大屏的电子墨水屏桌面显示器,售价8999元。

    科技 2021年12月3日