人脸识别
今天给大家分享的内容是纯 JavaScript 实现的人脸识别. 希望体验一下今天 web 端技术的飞速发展.
人脸识别
简单创建一个项目, 引入两个关键文件和文件夹
项目结构
models 是训练出来模型, 这些模型是通过大量图片训练出来的.
face-API.min.JS 引入依赖文件
创建一个 video 标签来捕捉我这张老脸.
<video id="video" width="720" height="560" autoplay muted></video>
简单地给样式
- <style>
- body {
- margin: 0;
- padding: 0;
- width: 100vw;
- height: 100vh;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- </style>
- <script defer src="./face-api.min.js"></script>
- <script defer src="./app.js"></script>
这里注意一下引用顺序, 我们需要引入 face-API.min.JS 这个依赖.
通过摄像头捕捉视频
- function startVideo(){
- navigator.getUserMedia(
- {video:{}},
- stream => video.srcObject = stream,
- err => console.log(err)
- )
- }
- startVideo();
这里我们使用 navigator 的 getUserMedia 获取设备的多媒体设备, 传入 video 表示要获取视频流, 然后将视频流传入到 video 标签来显示.
导入训练好的模型
- Promise.all([
- faceapi.nets.tinyFaceDetector.loadFromUri('/models'),
- faceapi.nets.faceLandmark68Net.loadFromUri('/models'),
- faceapi.nets.faceRecognitionNet.loadFromUri('/models'),
- faceapi.nets.faceExpressionNet.loadFromUri('/models'),
- ]).then(startVideo());
通过 Promise 的 all 将这些文件同时进行异步加载,
tinyFaceDetector 这是轻量级可以快速识别人脸的模型
faceLandmark68Net 用于对人脸不同部位识别的模型
faceRecognitionNet 识别出人脸的位置, 和覆盖的范围
faceExpressionNet 用于识别人的情绪, 是高兴呀还是高兴呀 呵呵
所有模型都加载完毕后再启动我们的视频
获取识别数据
- video.addEventListener('play',()=>{
- setInterval(async()=>{
- const detections = await faceapi.detectAllFaces(video,
- new faceapi.TinyFaceDetectorOptions())
- .withFaceLandmarks()
- // .withFaceExpressions()
- console.log(detections);
- },100)
- })
识别是个耗时的操作, 所有用异步方法获取识别数据, 调用 faceapi 的 detectAllFaces 方法, 传入要识别的资源, 也就是视频, 然后我们要识别什么可以传入一个 options 告诉识别器我们要识别什么. 打印识别出来的结果数据.
识别数据
绘制人脸识别框
这里我们创建一个 canvas 用于将识别出来数据绘制到视频上, canvas 可以用 JS 动态创建
- canvas {
- position: absolute;
- top: 0;
- left: 0;
- }
这里需要给 canvas 一个绝对定位, 以便和我们视频对其.
- const canvas = faceapi.createCanvasFromMedia(video);
- document.body.appendChild(canvas);
- const displaySize = { width: video.width, height: video.height};
faceapi.createCanvasFromMedia(video) 创建 canvas
- video.addEventListener('play',()=>{
- const canvas = faceapi.createCanvasFromMedia(video);
- document.body.appendChild(canvas);
- const displaySize = { width: video.width, height: video.height};
- faceapi.matchDimensions(canvas,displaySize);
- setInterval(async()=>{
- const detections = await faceapi.detectAllFaces(video,
- new faceapi.TinyFaceDetectorOptions())
- .withFaceLandmarks()
- const resizedDetections = faceapi.resizeResults(detections,displaySize)
- canvas.getContext('2d').clearRect(0,0,canvas.width,canvas.height);
- faceapi.draw.drawDetections(canvas,resizedDetections);
- // .withFaceExpressions()
- // console.log(detections);
- },100)
- })
- const displaySize = { width: video.width, height: video.height}
让 canvas 与我们 vidoe 大小匹配
const resizedDetections = faceapi.resizeResults(detections,displaySize)
将我们测试的框结果与显示大小相匹配.
canvas.getContext('2d').clearRect(0,0,canvas.width,canvas.height);
清除上一次绘制的结果, 下面就是讲结果绘制到视频上
faceapi.draw.drawDetections(canvas,resizedDetections);
来源: http://www.jianshu.com/p/31bad23d64b1