作者:沫沫 政采云前端团队
转发链接:https://mp.weixin.qq.com/s/fRDpXixnLIy9c0Uh2tMezQ
前言
近些年来,随着生物识别技术的逐渐成熟,基于深度学习的人脸识别技术取得了突破性进展,准确率显著提高。现阶段,人脸识别身份验证作为非常重要的身份验证方式,已被广泛的应用于诸多行业和领域,例如:支付宝付款、刷脸签到等方面。
其优点在于,以人脸为识别对象,识别过程更加友好、便捷,只需被识别者进入摄像范围内即可,不会引起被识别者的反感和警惕。目前,市面上的应用场景主要集中在移动端,而基于 Web 浏览器端的人脸识别身份验证方案较少。
本文将介绍基于 Web 浏览器端的人脸识别身份验证的整体方案,以及重点讲解如何在 Web 浏览器中实现人脸自动采集。
场景描述及分析
- 适用场景:人脸识别身份实名认证。用户使用人脸识别身份验证功能时,只需要将人脸对准摄像头,程序自动对人脸进行检测。如果检测到当前摄像头可视区域内仅存在唯一一个人脸,则采集当前人脸图片进行人脸对比、活体检测、身份证识别等多项组合能力,快速完成用户身份核验。
- 从上述场景描述中,分析出几个关键问题及解决方案:
- 考虑到 Web 端性能,活体检测交由服务端处理比较合适。具体可参考百度 AI 活体检测 (https://ai.baidu.com/tech/face/faceliveness)
- 个人身份证上的高清照片是无法直接获取到的。可以使用 百度 AI 的实名身份认证服务 (https://ai.baidu.com/tech/face/personverify),将待比对的人脸图片 + 身份证号码 + 姓名上传到百度 AI 服务,会返回图片的匹配度(0~100)。其底层调用的也是公安的实名认证接口
- 使用开源的人脸采集 JS 库。需要支持单个和多个人脸检测
- 经横向对比目前常用的开源人脸采集 JS 库,Face-api.js 在性能和准确度上更胜一筹
- face-api.js :基于 TensorFlow.js 内核,实现了三种卷积神经网络架构,用于完成人脸检测、识别和特征点检测任务,可以在浏览器中进行人脸识别。其内部实现了一个非常轻巧,快速,准确的 68 点面部标志探测器。支持多种 tf 模型,微小模型仅为 80kb。另外,它还支持 GPU 加速,相关操作可以使用 WebGL 运行
- tracking.js : 一个独立的 JavaScript 库,主要实现了颜色和人(人脸、五官等)的跟踪检测。可以通过检测到某特定颜色,或者检测一个人体/脸的出现与移动,来触发 JavaScript 事件,然后对人脸进行采集。Tracking.js 是使用 CPU 进行计算的,在图像的矩阵运算效率上,相对 GPU 要慢一些
- 通过 navigator.mediaDevices.getUserMedia API(基于 WebRTC)可以获取到摄像头拍摄的实时视频流数据
- 问题一:如何获取到摄像头拍摄的实时视频流数据?
- 问题二:如何检测到实时视频流中存在唯一人脸,并进行采集?
- 问题三:实名身份验证怎么实现?如何获取到身份证上的高清照片进行比对?
- 问题四:活体检测怎么实现?
整体方案
- 主要分为以下几个关键步骤:
- 调用摄像头(需获得用户授权允许),获取摄像头的视频流数据
- 使用 face-api.js 识别视频流中的人脸特征点,定位出人脸的位置
- 符合人脸特征时,暂停视频流,根据视频流当前帧,绘制图像
- 将图像转成 Base64 编码,上传到服务端
- 服务端调用百度 AI 的接口,与身份证上的图片信息进行比对,并进行活体检测
实现细节
在上述方案中,想必大家对摄像头检测、实时视频流数据获取、Canvas 图片绘制这些都比较熟悉,我这边就不详细讲解了。部分同学没接触过也没关系,具体实现比较简单,可以直接看 源码 (https://github.com/Angela-Chen/face-api-demo),源码里面关于这些都有详细的注解。
下面我详细讲下,如何使用 face-api.js 在实时视频流中进行人脸的检测
1、引入 face-api
script 标签方式,获取 最新脚本 (https://github.com/justadudewhohacks/face-api.js/tree/master/dist)
或者 使用 npm 方式
npm install face-api.js
2、加载模型数据
“
加载模型数据是异步操作。需要等模型数据加载完成后,才能开始人脸检测。
// 加载所有模型数据,models 是存放模型数据文件的目录await faceapi.loadModels('/models'); // 加载单个指定的模型数据await faceapi.loadTinyFaceDetectorModel('/models');await faceapi.loadSsdMobilenetv1Model('/models');await faceapi.loadMtcnnModel('/models');
3、检测人脸
“
当人脸被检测到符合模型的配置参数后,就会被认为检测到人脸了,然后返回一个detection对象,包括了人脸匹配度、人脸坐标等信息。可用于后续自定义绘制人脸边界框,以及阈值的逻辑判断。
- faceapi.detectAllFaces :检测图像中的所有人脸
- faceapi.detectSingleFace :检测单个人脸,返回图像中具有最高置信度得分的人脸
// 数据源支持:HTMLImageElement | HTMLVideoElement | HTMLCanvasElement 类型// 不同的模型有不同的配置参数,下面会详细介绍const detections1 = await faceapi.detectAllFaces(待检测的数据源, 模型的配置参数);const detections2 = await faceapi.detectSingleFace(待检测的数据源, 模型的配置参数);
4、常用人脸检测模型介绍
(1) Tiny Face Detector 是一款性能非常高的实时人脸检测模型,与 SSD Mobilenet V1 人脸检测模型相比,它更快,更小,资源消耗更少,量化模型的大小仅为 190 KB(tiny_face_detector_model),但它在检测小脸时的表现稍差。加载时长 8 ms左右
// 模型的配置参数new faceapi.TinyFaceDetectorOptions({ // 输入的数据源大小,这个值越小,处理速度越快。常用值:128, 160, 224, 320, 416, 512, 608 inputSize: number, // default: 416 // 用于过滤边界的分数阈值,大于等于这个值才被认为检测到了人脸,然后返回一个detection对象 scoreThreshold: number // default: 0.5});
(2) SSD Mobilenet V1 对于面部检测,该模型实现了基于 MobileNetV1 的 SSD(单次多核检测器)。神经网络将计算图像中每个面部的位置,并将返回边界框以及每个面部的概率。该面部检测器旨在获得检测面部边界框而不是低推理时间的高精度。量化模型的大小约为 5.4 MB(ssd_mobilenetv1_model)。加载时长 2-3s 左右
// 模型的配置参数new faceapi.SsdMobilenetv1Options({ // 最小置信值,大于等于这个值才被认为检测到了人脸,然后返回一个detection对象 minConfidence: number, // default: 0.5 // 最多返回人脸的个数 maxResults: number // default: 100});
(3) MTCNN MTCNN(多任务级联卷积神经网络)代表了 SSD Mobilenet v1 和 Tiny Yolo v2 的替代面部检测模型,它提供了更多的配置空间。通过调整输入参数,MTCNN 应该能够检测各种面部边界框大小。MTCNN 是一个 3 级级联 CNN,它同时返回 5 个面部标志点以及每个面的边界框和分数。此外,型号尺寸仅为 2 MB。加载时长 1-2s 左右
// 模型的配置参数new faceapi.MtcnnOptions({ // 人脸尺寸的最小值,小于这个尺寸的人脸不会被检测到 minFaceSize: number, // default: 20 // 用于过滤边界的分数阈值,分别可以设置3个阶段盒子的阈值。 scoreThresholds: number[], // default: [0.6, 0.7, 0.7] // 比例因子用于计算图像的比例步长 scaleFactor: number, // default: 0.709 // 经过CNN的输入图像缩放版本的最大数量。数字越小,检测时间越短,但相对准确度会差一些。 maxNumScales: number, // default: 10 // 手动设置缩放步长 scaleSteps scaleSteps?: number[],});
- 特别说明:
- 模型的配置参数设置非常重要,需要慢慢的微调,能优化识别性能和比对的正确性
- 实测下来,Tiny Face Detector 模型的性能非常好,检测的准确度也不错,只有人脸很小的时候,会有较大偏差,scoreThreshold 阈值为 0.6 时最佳
注意事项
- 由于 Web 端的人脸识别将依赖于本地摄像头的唤起,因此,对于本地摄像头的调用需要进行详细的错误捕获和处理,以便明确的提示用户该如何操作。下面已枚举出所有可能出现的报错:
const errorMap = { 'NotAllowedError': '摄像头已被禁用,请在系统设置或者浏览器设置中开启后重试', 'AbortError': '硬件问题,导致无法访问摄像头', 'NotFoundError': '未检测到可用摄像头', 'NotReadableError': '操作系统上某个硬件、浏览器或者网页层面发生错误,导致无法访问摄像头', 'OverConstrainedError': '未检测到可用摄像头', 'SecurityError': '摄像头已被禁用,请在系统设置或者浏览器设置中开启后重试', 'TypeError': '类型错误,未检测到可用摄像头'};await navigator.mediaDevices.getUserMedia({video: true}) .catch((error) => { if (errorMap[error.name]) { alert(errorMap[error.name]); }});
- http 协议下,Chrome 浏览器无法调用本地摄像头
- Chrome 浏览器出于安全性的考虑,现只支持 HTTPS 协议 和 localhost 下,调用摄像头。HTTP 协议下是无法调用摄像头的。如果一定要在 HTTP下调用到摄像头,只能修改 Chrome 浏览器的配置项,但不建议这么做
源码获取
- 查看源码 (https://github.com/Angela-Chen/face-api-demo)
推荐JavaScript经典实例学习资料文章
《「前端进阶」高性能渲染十万条数据(时间分片)》
《「前端进阶」高性能渲染十万条数据(虚拟列表)》
《图解 Promise 实现原理(一):基础实现》
《图解 Promise 实现原理(二):Promise 链式调用》
《图解 Promise 实现原理(三):Promise 原型方法实现》
《图解 Promise 实现原理(四):Promise 静态方法实现》
《实践教你从零构建前端 Lint 工作流「干货」》
《高性能多级多选级联组件开发「JS篇」》
《深入浅出讲解Node.js CLI 工具最佳实战》
《延迟加载图像以提高Web网站性能的五种方法「实践」》
《比较 JavaScript 对象的四种方式「实践」》
《使用Service Worker让你的 Web 应用如虎添翼(上)「干货」》
《使用Service Worker让你的 Web 应用如虎添翼(中)「干货」》
《使用Service Worker让你的 Web 应用如虎添翼(下)「干货」》
《前端如何一次性处理10万条数据「进阶篇」》
《推荐三款正则可视化工具「JS篇」》
《如何让用户选择是否离开当前页面?「JS篇」》
《JavaScript开发人员更喜欢Deno的五大原因》
《仅用18行JavaScript实现一个倒数计时器》
《图文细说JavaScript 的运行机制》
《一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索》
《推荐Web程序员常用的15个源代码编辑器》
《10个实用的JS技巧「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」》
《细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」》
《深入JavaScript教你内存泄漏如何防范》
《手把手教你7个有趣的JavaScript 项目-上「附源码」》
《手把手教你7个有趣的JavaScript 项目-下「附源码」》
《JavaScript 使用 mediaDevices API 访问摄像头自拍》
《手把手教你前端代码如何做错误上报「JS篇」》
《一文让你彻底搞懂移动前端和Web 前端区别在哪里》
《63个JavaScript 正则大礼包「值得收藏」》
《提高你的 JavaScript 技能10 个问答题》
《JavaScript图表库的5个首选》
《一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法》
《可视化的 JS:动态图演示 - 事件循环 Event Loop的过程》
《教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」》
《可视化的 js:动态图演示 Promises & Async/Await 的过程》
《原生JS封装拖动验证滑块你会吗?「实践」》
《如何实现高性能的在线 PDF 预览》
《细说使用字体库加密数据-仿58同城》
《Node.js要完了吗?》
《Pug 3.0.0正式发布,不再支持 Node.js 6/8》
《纯JS手写轮播图(代码逻辑清晰,通俗易懂)》
《JavaScript 20 年 中文版之创立标准》
《值得收藏的前端常用60余种工具方法「JS篇」》
《箭头函数和常规函数之间的 5 个区别》
《通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events》
《「前端篇」不再为正则烦恼》
《「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能》
《深入细品浏览器原理「流程图」》
《JavaScript 已进入第三个时代,未来将何去何从?》
《前端上传前预览文件 image、text、json、video、audio「实践」》
《深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系》
《推荐13个有用的JavaScript数组技巧「值得收藏」》
《前端必备基础知识:window.location 详解》
《不要再依赖CommonJS了》
《犀牛书作者:最该忘记的JavaScript特性》
《36个工作中常用的JavaScript函数片段「值得收藏」》
《Node + H5 实现大文件分片上传、断点续传》
《一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」》
《【实践总结】关于小程序挣脱枷锁实现批量上传》
《手把手教你前端的各种文件上传攻略和大文件断点续传》
《字节跳动面试官:请你实现一个大文件上传和断点续传》
《谈谈前端关于文件上传下载那些事【实践】》
《手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件》
《最全的 JavaScript 模块化方案和工具》
《「前端进阶」JS中的内存管理》
《JavaScript正则深入以及10个非常有意思的正则实战》
《前端面试者经常忽视的一道JavaScript 面试题》
《一行JS代码实现一个简单的模板字符串替换「实践」》
《JS代码是如何被压缩的「前端高级进阶」》
《前端开发规范:命名规范、html规范、css规范、js规范》
《【规范篇】前端团队代码规范最佳实践》
《100个原生JavaScript代码片段知识点详细汇总【实践】》
《关于前端174道 JavaScript知识点汇总(一)》
《关于前端174道 JavaScript知识点汇总(二)》
《关于前端174道 JavaScript知识点汇总(三)》
《几个非常有意思的javascript知识点总结【实践】》
《都2020年了,你还不会JavaScript 装饰器?》
《JavaScript实现图片合成下载》
《70个JavaScript知识点详细总结(上)【实践】》
《70个JavaScript知识点详细总结(下)【实践】》
《开源了一个 JavaScript 版敏感词过滤库》
《送你 43 道 JavaScript 面试题》
《3个很棒的小众JavaScript库,你值得拥有》
《手把手教你深入巩固JavaScript知识体系【思维导图】》
《推荐7个很棒的JavaScript产品步骤引导库》
《Echa哥教你彻底弄懂 JavaScript 执行机制》
《一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧》
《深入解析高频项目中运用到的知识点汇总【JS篇】》
《JavaScript 工具函数大全【新】》
《从JavaScript中看设计模式(总结)》
《身份证号码的正则表达式及验证详解(JavaScript,Regex)》
《浏览器中实现JavaScript计时器的4种创新方式》
《Three.js 动效方案》
《手把手教你常用的59个JS类方法》
《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》
《深入浅出讲解 js 深拷贝 vs 浅拷贝》
《手把手教你JS开发H5游戏【消灭星星】》
《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》
《手把手教你全方位解读JS中this真正含义【实践】》
《书到用时方恨少,一大波JS开发工具函数来了》
《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》
《手把手教你JS 异步编程六种方案【实践】》
《让你减少加班的15条高效JS技巧知识点汇总【实践】》
《手把手教你JS开发H5游戏【黄金矿工】》
《手把手教你JS实现监控浏览器上下左右滚动》
《JS 经典实例知识点整理汇总【实践】》
《2.6万字JS干货分享,带你领略前端魅力【基础篇】》
《2.6万字JS干货分享,带你领略前端魅力【实践篇】》
《简单几步让你的 JS 写得更漂亮》
《恭喜你获得治疗JS this的详细药方》
《谈谈前端关于文件上传下载那些事【实践】》
《面试中教你绕过关于 JavaScript 作用域的 5 个坑》
《Jquery插件(常用的插件库)》
《【JS】如何防止重复发送ajax请求》
《JavaScript+Canvas实现自定义画板》
《Continuation 在 JS 中的应用「前端篇」》
作者:沫沫 政采云前端团队
转发链接:https://mp.weixin.qq.com/s/fRDpXixnLIy9c0Uh2tMezQ