2020-04-05 17:56:15

作者 | 前端开发劝退师

责编 | 夕颜

出品 | CSDN(ID:CSDNnews)

最终结果

在线体验:http://www.caomage.com/index

急性子想直接食用的点这个:源码地址 https://github.com/usecodelee/mldrawberry

原理

要在用户上传的人脸上画草莓,会面临几个问题:

  1. 在哪儿画?
  2. 画多大?
  3. 草莓的角度和脸的角度是否一致?

基于这些问题,就不得不使用机器学习来解决了!

1. 前端的机器学习

提起前端的机器学习,首先想到的就是Google的TensorFlow:

TensorFlow 是一个端到端开源机器学习平台。它拥有一个包含各种工具、库和社区资源的全面灵活生态系统,可以让研究人员推动机器学习领域的先进技术的发展,并让开发者轻松地构建和部署由机器学习提供支持的应用。

有兴趣的可以去TensorFlow官网看看,有很多好玩的东西。

当然,我们仅仅是使用人脸识别,那有人已经在TensorFlow的基础上封装了专门针对人脸识别的库 face-api.js

2. 基本原理

我只是大体说一下,我只是一个感兴趣的可以去看看具体的内容。

第一步:找出所有的面孔

解决方案HOG(Histogram of Oriented Gradients)方向梯度直方图,一种能够检测物体轮廓的算法。

第二步:脸部的不同姿势

使用由瓦希德·卡奇米(Vahid Kazemi)和约瑟菲娜·沙利文(Josephine Sullivan)在 2014 年发明的一种面部特征点估计(face landmark estimation)算法。

这一算法的基本思路是找到68个人脸上普遍存在的点(称为特征点, landmark):

其中:

下巴轮廓17个点 [0-16]

左眉毛5个点 [17-21]

右眉毛5个点 [22-26]

鼻梁4个点 [27-30]

鼻尖5个点 [31-35]

左眼6个点 [36-41]

右眼6个点 [42-47]

外嘴唇12个点 [48-59]

内嘴唇8个点 [60-67]

有了这68个点,我们就可以轻松的知道眉毛、眼睛、鼻子和嘴巴的位置信息了,根据这些位置信息,我们经过一些简单的计算就可以得出开始提到的这几个问题的答案:

  1. 在哪儿画?
  2. 画多大?
  3. 草莓的角度和脸的角度是否一致?

基于vue-cli搞一个

有了face-api.js我们就可以动手开始搞了。大体上分为4步:

  1. 使用vue-cli脚手架搭建项目
  2. 使用face-api.js检测人脸图片,获取检测结果
  3. 计算(草莓大小、位置、旋转角度等)
  4. 画草莓

1. 使用vue-cli脚手架搭建项目

使用vue-cli快速创建一个项目

2. 使用face-api.js检测人脸图片,获取检测结果

(1)安装face-api.js

npm i face-api.js

(2)加载模型数据

使用face-api.js是不需要我们自己慢慢训练的,可以直接使用models。

你可以根据应用程序的要求加载你需要的特定模型。但是如果要运行一个完整的端到端的示例,我们还需要加载人脸检测、人脸特征点检测和人脸识别模型。相关的模型文件可以在代码仓库中找到。我们将它们放在public/models文件夹下并导入:

const MODEL_URL = "/models";await faceapi.loadSsdMobilenetv1Model(MODEL_URL);await faceapi.loadFaceLandmarkModel(MODEL_URL);await faceapi.loadFaceRecognitionModel(MODEL_URL);

将face-api.js导入我们的组件:

import * as faceapi from "face-api.js";

(3)使用face-api.js检测人脸图片,获取检测结果

let input = this.$refs.inputImg; // 待检测的图片let canvas = this.$refs.overlay; // 等下画检测结果的画布const minConfidence = 0.8;let fullFaceDescriptions = await faceapi .detectAllFaces(input) .withFaceLandmarks .withFaceDescriptors; // 检测图片faceapi.matchDimensions(canvas, input); // 让画布和图片一样大const displaySize = { width: input.width, height: input.height };const resizedDetections = faceapi.resizeResults( fullFaceDescriptions, displaySize); // 调整检测结果和输入图片像素

3. 计算(草莓位置、大小、倾斜弧度等)

(1)获取脸上元素的特征点数组

// 脸颊是从左往右 17个点const jawOutline = resizedDetections[0].landmarks.getJawOutline; // 鼻子是从上往下画的 9个点const nose = resizedDetections[0].landmarks.getNose; //嘴巴分 20个点const mouth = resizedDetections[0].landmarks.getMouth; //左眼 6个点 从左往右const leftEye = resizedDetections[0].landmarks.getLeftEye;//右眼 6个点 从左往右 const rightEye = resizedDetections[0].landmarks.getRightEye; //左眉毛 5个点 从左往右const leftEyeBbrow = resizedDetections[0].landmarks.getLeftEyeBrow; //右眉毛 5个点 从左往右const rightEyeBrow = resizedDetections[0].landmarks.getRightEyeBrow; faceapi.draw.drawDetections(canvas, resizedDetections); // 画框faceapi.draw.drawFaceLandmarks(canvas, resizedDetections); // 画点

画出来的结果如图:

(2)获取草莓位置

草莓的位置获取,先看下面这张图:

先比较左右黄色和绿色两条线的长度,哪边长就画在哪边(考虑可能照片是侧着脸的),具体的位置左右不一样,右边绿色的线直接从线的中点开始画,而左边黄色的线则是在线的中点再往左边偏移草莓宽度的一半开始画。

大概如图:

所以是先获取点32和点16的距离,再获取中点:

// 获取两点之间距离const getDistance = (a, b) => { return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2))}// 获取两点之间的中点const getMidPoint = (pa, pb) => ({ x: (pa.x + pb.x) / 2, y: (pa.y + pb.y) / 2})

(3)获取草莓大小

草莓的大小可以估计一下,大概是整个脸宽的1/6:

const size = { width: faceWidth / 6, height: faceWidth / 6 }

(4)获取草莓倾斜弧度

我们可以根据眉毛的中点和下颚的最低点两个点计算出脸的弧度,即草莓的弧度:

// 获取脸的倾斜弧度const getFaceRadian = (jawPos, midPointOfEyebrows) => Math.PI - Math.atan2(jawPos.x - midPointOfEyebrows.x, jawPos.y - midPointOfEyebrows.y)

4. 画草莓

有了前面的内容,画草莓就简单了。先将原图画上去,再在原图的基础上画上草莓:

// 画草莓function drawBerry(ctx, config, berryUrl) { const { angle, faceWidth, facePos } = config getImg(berryUrl, (img) => { ctx.save // 移动画布原点到画草莓的位置 ctx.translate(facePos.point.x, facePos.point.y) // 旋转草莓的角度和脸的角度一致 ctx.rotate(angle) // 调整草莓的位置 const { x, y, width, height } = transBerry(faceWidth, 0, 0, facePos.dir) ctx.drawImage(img, x, y, width, height) ctx.restore })}// 获取图片function getImg(src, cb) { const img = new Image img.setAttribute('crossOrigin', 'anonymous') img.src = src img.onload = => cb(img)}

限于篇幅,文中只提及了部分重点代码,需要看完整代码的可以点这里:https://github.com/usecodelee/mldrawberry

原文链接:

https://blog.csdn.net/caomage/article/details/103751111

前端机器学习:识别人脸,并在脸颊上画草莓相关推荐

  1. 前端机器学习--识别人脸在脸颊上画草莓

    文章目录 前端机器学习--识别人脸在脸颊上画草莓 一.最终结果 二.原理 1. 前端的机器学习 2. 基本原理 三.基于`vue-cli`搞一个 1. 使用`vue-cli`脚手架搭建项目 2. 使用 ...

  2. 机器学习原来这么有趣!第四章:用深度学习识别人脸

    第一章:全世界最简单的机器学习入门指南 https://blog.csdn.net/wskzgz/article/details/89917343 第二章:用机器学习制作超级马里奥的关卡 https: ...

  3. 机器学习之人脸识别face_recognition使用

    机器学习之人脸识别face_recognition使用 简介 一 二 主要方法介绍 1. load_image_file 加载图像 2. face_locations 定位图中所有人脸 3. face ...

  4. 机器学习之人脸识别(Face Recognition)

    机器学习之机器是如何识别人脸(Face Recognition)的? 目前,一些机器学习技术已经被广泛应用于人脸识别.人脸支付以及身份认证领域,例如支付宝的FACEID,阿里的Alipay,ETC等等 ...

  5. 机器学习原来如此有趣:用深度学习识别人脸

    本系列文章目前已经更新两期,分别是: 机器学习原来如此有趣!全世界最简单的机器学习入门指南. 机器学习原来如此有趣:如何故意欺骗神经网络 你是否有注意到Facebook最近开发了一个非同寻常的功能:将 ...

  6. 中科院DeepMind联手,用深度学习揭示大脑如何识别人脸|Nature子刊

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 梦晨 发自 凹非寺 量子位 报道 | 公众号 QbitAI Deep ...

  7. 人脸识别是怎么识别人脸的?

    刷脸打卡.刷脸支付.刷脸开门,你开始刷脸生活了吗? 相比指纹,虹膜,语音,静脉,视网膜识别,人脸识别更快捷方便,你知道人脸识别技术是怎样实现的吗? 基于2D图像数据的人脸识别是目前的主流,在安防.监控 ...

  8. python识别人脸多种属性_用Python识别人脸,人种等各种信息

    最近几天了解了一下人脸识别,应用场景可以是图片标注,商品图和广告图中有没有模特,有几个模特,模特的性别,年龄,颜值,表情等数据的挖掘. 基础的识别用dlib来实现,dlib是一个机器学习的包,主要用C ...

  9. 用深度学习识别人脸openface和dlib

    你有没有发现 Facebook 研发出了一种能够在你的照片中识别出你朋友的神奇neng li? 之前,你需要手动点击你朋友的照片,输入他们的名字,然后加上标签.现在,只要你一上传照片,Facebook ...

最新文章

  1. 48.结构体位域获取内存模型
  2. 数据库 / 事务的 ACID
  3. ai物联网工业_人工智能和物联网将如何改变行业
  4. 户口所在地代码查询_毕业生如何查询档案存放地及存档问题?
  5. 循环神经网络(RNN)Recurrent Neural Networks
  6. 集成电路设计专业有计算机课程吗,集成电路属于什么专业大类 什么学科
  7. ES6--阮一峰版笔记
  8. JAVA WEB学习
  9. python计算现场得分_如何使用Python(scikitlearn)计算factorananalysis得分?
  10. JavaScript几种继承方式
  11. 对团队中“这是某某某的问题”引起的思考
  12. 代码性能优化--NENO编程
  13. 通过uart串口和printf函数打印
  14. BAT脚本: ping检测网络稳定性 与 取命令结果的指定行方法 与 将变量内容追加写入txt文件方法
  15. 读《当众讲话诀窍》-殷亚敏 (2)
  16. C++实现——任意多边形的面积
  17. Jzoj5454【NOIP2017提高A组冲刺11.5】仔细的检查
  18. 小插曲 之 二分查找
  19. 强势图解AC自动机 --- 转载
  20. html跳转页面 url不变,实现页面的跳转后,浏览器的地址栏不变

热门文章

  1. 计算机网络的八股文自述(持续更新)
  2. 自己一路经历的实习面试总结(希望能给看到这篇博客的小伙伴提供一些帮助)
  3. 用notepad++怎样批量添加引号
  4. pytorch bert预训练模型的加载地址
  5. jadclipse设置,这个解决了问题
  6. 用c语言编写心里测试,求各位大神赐教!我做了一个“心理测试的答题卷”编程,总共有1...
  7. 智能,万亿维空间中的求解
  8. 使用pytorch构建2D和3D人脸比对库(使用face-alignment)
  9. TensorFlow入门(一)基本用法
  10. Fiat–Shamir heuristic 启发式的应用 理解 代码实现