参考

Build Real Time Face Detection With JavaScript (youtube get started)

face-api.js — JavaScript API for Face Recognition in the Browser with tensorflow.js

教程 | face-api.js:在浏览器中进行人脸识别的JavaScript接口 (有提到相似度)

face-api.js github

face-api.js documentation

注意事项:

由于 face-api.js 作者从 2020 Apr 之后就没有维护了, 以至于在 node.js 的时候无法使用最新的 @tensorflow/tfjs-node (issue 在这里)

后来有个好心人 folk 出来改. 所以推荐大家使用新的版本 @vladmandic/face-api

Get started

Build Real Time Face Detection With JavaScript (youtube get started)

这篇主要是叫一些 basic 入门.

流程: 

加载需要的 models

开启 webcam

把 webcam 源放入 video 做显示

通过 faceapi 扫描 video

做一个定位 canvas 画布

通过 faceapi draw 人脸位置, 轮廓, 表情.

代码:

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

const video = document.querySelector<HTMLVideoElement>('#js-video')!;

video.addEventListener('play', () => {
// 制作定位 canvas
const canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
document.body.append(canvas); // 配置显示尺寸
const displaySize = { width: video.width, height: video.height };
faceapi.matchDimensions(canvas, displaySize); // 每 100ms 去绘制
setInterval(async () => {
// 识别位置, 路阔, 表情
const detections = await faceapi
.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceExpressions(); // 调整尺寸
const resizedDetections = faceapi.resizeResults(detections, displaySize); canvas.getContext('2d')?.clearRect(0, 0, canvas.width, canvas.height); // 清空画布
faceapi.draw.drawDetections(canvas, resizedDetections); // 位置
faceapi.draw.drawFaceLandmarks(canvas, resizedDetections); // 路阔
faceapi.draw.drawFaceExpressions(canvas, resizedDetections); // 表情
}, 100);
}); setTimeout(async () => {
// 加载 models
await Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/face-api-models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/face-api-models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/face-api-models'),
faceapi.nets.faceExpressionNet.loadFromUri('/face-api-models'),
]);
// 开启 webcam, 把 webcam 的流引入 video 显示
navigator.getUserMedia(
{ video: {} },
stream => {
video.srcObject = stream;
},
error => console.log('error', error)
);
}, 1000);

 提醒: Webpack + face-api.js warning

如果使用 Webpack 可能会看见一个 warning 显示 Can't resolve 'fs'

这是因为 face-api.js 的代码是 node.js 和游览器共用的, 在 node.js 的环境下 fs 是必要的. 但是游览器是不需要的. 忽略掉这个 warning 就可以了.

github issue 看这里.

另外, webpack 5 之后就没有 build-in node 的 polyfill 了, 要用到就自己装,

npm – node-polyfill-webpack-plugin

module.exports = {
plugins: [
new NodePolyfillPlugin(),
]
};

还需要这个

  resolve: {
extensions: ['.ts', '.js'],
fallback: {
// vladmandic/face-api v1.5 以后就依赖 fs 了, 配上 webpack 5 就会有问题, 所以这里需要一个 false
fs: false,
},
},

人脸识别 + 相似度

通过获取 2 张图片的人脸信息就可以做一个相似度对比. 如果 < 0.6 就表示很可能是同一个人 (这个度没有规范, 只是一个参考值)

这里顺便补上了一个 detect age 的功能.

// import * as faceapi from 'face-api.js';
import * as faceapi from '@vladmandic/face-api'; (async () => {
await Promise.all([
faceapi.nets.tinyFaceDetector.loadFromUri('/face-api-models'),
faceapi.nets.faceLandmark68Net.loadFromUri('/face-api-models'),
faceapi.nets.faceRecognitionNet.loadFromUri('/face-api-models'),
faceapi.nets.faceExpressionNet.loadFromUri('/face-api-models'),
faceapi.nets.ageGenderNet.loadFromUri('/face-api-models'),
]);
const processAsync = async (image: HTMLImageElement) => {
const imageContainer = image.parentElement!;
const canvas = document.createElement('canvas');
canvas.style.position = 'absolute';
canvas.style.left = '0';
canvas.style.top = '0';
imageContainer.append(canvas);
const displaySize = { width: image.width, height: image.height };
faceapi.matchDimensions(canvas, displaySize); const faceDetection = (
await faceapi
.detectAllFaces(image, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptors()
.withFaceExpressions()
.withAgeAndGender()
)[0]; // 假设图片只会有一张脸
// 或者用 detectSingleFace 拿最像脸的脸, 提醒: withFaceDescriptor <- 没有 s 了
// const faceDetection = await faceapi
// .detectSingleFace(image, new faceapi.TinyFaceDetectorOptions())
// .withFaceLandmarks()
// .withFaceDescriptor()
// .withFaceExpressions()
// .withAgeAndGender(); if (faceDetection === undefined) {
throw new Error(`no faces detected`);
}
const resizedDetection = faceapi.resizeResults(faceDetection, displaySize);
faceapi.draw.drawDetections(canvas, resizedDetection);
faceapi.draw.drawFaceLandmarks(canvas, resizedDetection);
faceapi.draw.drawFaceExpressions(canvas, resizedDetection);
const box = resizedDetection.detection.box;
const drawBox = new faceapi.draw.DrawBox(box, {
label: Math.round(resizedDetection.age) + ' year old ' + resizedDetection.gender,
});
drawBox.draw(canvas);
return faceDetection;
};
const [fd1, fd2] = await Promise.all([
processAsync(document.querySelector<HTMLImageElement>('#js-image1')!),
processAsync(document.querySelector<HTMLImageElement>('#js-image2')!),
]); const distance = faceapi.euclideanDistance(fd1.descriptor, fd2.descriptor);
if (distance < 0.6) {
console.log('same person');
} else {
console.log('different person');
}
})();

关键就在最后几句.

Node.js 运行

安装

要在 Node.js 上运行 (Windows 机) 有些事情要留意, 我也不确定是不是要装到完

npm install -g --production windows-build-tools (Local machine PowerShell administrator 安装, 在 windows server 我是用 cmd without admin 安装的, 它大概装了 10 分钟, 虽然看上去没有什么跑,但其实 CPU 是有跑的, 要留意哦)

安装 Python (我是通过 visual studio installer 安装的 3.x 版本, windows server 的话通过 installer 安装 2.x 版本 (可能 3.x 也是 ok), 在配置的时候记得选要 setup path)

set environment variables path

常见问题

代码

参考: face-api.js docs

yarn add @tensorflow/tfjs-node @vladmandic/face-api canvas

这里用的是 CommonJS, 因为我目前还没有 migration 到 es module

require('@tensorflow/tfjs-node');
const canvas = require('canvas');
const faceapi = require('@vladmandic/face-api'); // 这个是官方推荐做法 monkeyPatch
const { Canvas, Image, ImageData } = canvas;
faceapi.env.monkeyPatch({ Canvas, Image, ImageData }); (async () => {
await Promise.all([
// 换成了 from disk
faceapi.nets.tinyFaceDetector.loadFromDisk('face-api-models'),
faceapi.nets.faceLandmark68Net.loadFromDisk('face-api-models'),
faceapi.nets.faceRecognitionNet.loadFromDisk('face-api-models'),
faceapi.nets.faceExpressionNet.loadFromDisk('face-api-models'),
]); // 通过 canvas.loadImage 读取图片
const image1 = await canvas.loadImage('klc-face/1.jpg');
const image2 = await canvas.loadImage('klc-face/2.jpg');
const fd1 = await faceapi
.detectSingleFace(image1, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptor(); const fd2 = await faceapi
.detectSingleFace(image2, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptor(); const distance = faceapi.euclideanDistance(fd1.descriptor, fd2.descriptor);
console.log('distance', distance);
})();

如果要用 es module 的话, 到 package.json 加 { "type": "module" }, 下面这个是 es module 版本

import '@tensorflow/tfjs-node';
import canvas from 'canvas';
import faceapi from '@vladmandic/face-api'; // 这个是官方推荐做法 monkeyPatch
const { Canvas, Image, ImageData } = canvas;
faceapi.env.monkeyPatch({ Canvas, Image, ImageData }); (async () => {
await Promise.all([
// 换成了 from disk
faceapi.nets.tinyFaceDetector.loadFromDisk('face-api-models'),
faceapi.nets.faceLandmark68Net.loadFromDisk('face-api-models'),
faceapi.nets.faceRecognitionNet.loadFromDisk('face-api-models'),
faceapi.nets.faceExpressionNet.loadFromDisk('face-api-models'),
]); // 通过 canvas.loadImage 读取图片
const image1 = await canvas.loadImage('klc-face/1.jpg');
const image2 = await canvas.loadImage('klc-face/2.jpg');
const fd1 = await faceapi
.detectSingleFace(image1, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptor(); const fd2 = await faceapi
.detectSingleFace(image2, new faceapi.TinyFaceDetectorOptions())
.withFaceLandmarks()
.withFaceDescriptor(); const distance = faceapi.euclideanDistance(fd1.descriptor, fd2.descriptor);
console.log('distance', distance);
})();

face-api.js 学习笔记的更多相关文章

  1. 一点感悟:《Node.js学习笔记》star数突破1000+

    写作背景 笔者前年开始撰写的<Node.js学习笔记> github star 数突破了1000,算是个里程碑吧. 从第一次提交(2016.11.03)到现在,1年半过去了.突然有些感慨, ...

  2. 基于jquery的插件turn.js学习笔记

    基于jquery的插件turn.js学习笔记 简介 turn.js是一个可以实现3d书籍展示效果的jq插件,使用html5和css3来执行效果.可以很好的适应于ios和安卓等触摸设备. How it ...

  3. js学习笔记:webpack基础入门(一)

    之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...

  4. Vue.js学习笔记(2)vue-router

    vue中vue-router的使用:

  5. Rest API 开发 学习笔记(转)

    Rest API 开发 学习笔记 概述 REST 从资源的角度来观察整个网络,分布在各处的资源由URI确定,而客户端的应用通过URI来获取资源的表示方式.获得这些表徵致使这些应用程序转变了其状态.随着 ...

  6. JS 学习笔记--9---变量-作用域-内存相关

    JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...

  7. JavaSE中线程与并行API框架学习笔记——线程为什么会不安全?

    前言:休整一个多月之后,终于开始投简历了.这段时间休息了一阵子,又病了几天,真正用来复习准备的时间其实并不多.说实话,心里不是非常有底气. 这可能是学生时代遗留的思维惯性--总想着做好万全准备才去做事 ...

  8. WebGL three.js学习笔记 使用粒子系统模拟时空隧道(虫洞)

    WebGL three.js学习笔记 使用粒子系统模拟时空隧道 本例的运行结果如图: 时空隧道demo演示 Demo地址:https://nsytsqdtn.github.io/demo/sprite ...

  9. WebGL three.js学习笔记 法向量网格材质MeshNormalMaterial的介绍和创建360度全景天空盒的方法

    WebGL学习----Three.js学习笔记(5) 点击查看demo演示 Demo地址:https://nsytsqdtn.github.io/demo/360/360 简单网格材质 MeshNor ...

  10. WebGL three.js学习笔记 创建three.js代码的基本框架

    WebGL学习----Three.js学习笔记(1) webgl介绍 WebGL是一种3D绘图协议,它把JavaScript和OpenGL ES 2.0结合在一起,通过增加OpenGL ES 2.0的 ...

随机推荐

  1. UE MultiLineTraceByChannel函数返回只有一个对象的问题

    问题描述 MultiLineTraceByChannel,看函数名字是返回射线检测到的所有对象,实际使用过程中,发现返回的数组中只又一个对象. Multi Line Trace by Channel ...

  2. odoo 通过Javascript显示或隐藏form自带按钮

    实践环境 Odoo 14.0-20221212 (Community Edition) 需求描述 如下,根据条件对form视图自带按钮的显示.隐藏进行控制 代码实现 隐藏.显示编辑和创建按钮为例 od ...

  3. appium模拟键盘事件

    原方法: 1 def press_keycode(self, keycode, metastate=None): 2 """Sends a keycode to the ...

  4. java开发环境安装IDEA+jdk1.8

    一. 需要得安装包 (1)IDEA破解版.zip (2)jdk1.8.0_25.7z 获取方式(免费): (1)       登录-注册:http://resources.kittytiger.cn/ ...

  5. windows edge浏览器免费复制网页文字

    复制时,出现上面提示时候 使用edge浏览器打开链接,在http前面加入read: ,然后打开,即可复制 如果用js,可以参考https://www.cnblogs.com/rmticocean/p/ ...

  6. [香橙派开发系列]使用wiringPi控制26个引脚

    目录 前言 一.香橙派使用的包 二.使用wiringPi包的命令 1.下载wiringOP 2.gpio readall信息分析 3.设置gpio的模式 4.设置gpio输出的电平 三.wiringP ...

  7. 【Git】04 文件删除

    版本分支的概念提示: 工作区就是我们的Git本地仓库,也就是一个很普通的目录 . 通过ADD指令添加文件到暂存区中, 在通过COMMIT指令提交到版本分支, 所谓的版本分支,就是就是这个蓝色的Mast ...

  8. 鹏城实验室——启智平台使用外部docker镜像 —— 实测并不可用,该功能可用性较低

    参考: https://bbs.openi.org.cn/forums/5492 需要注意,目前只有NVIDIA GPU运行环境下允许使用外部docker镜像. 注意: 对于该功能实测后发现可用性不高 ...

  9. 【转载】 tf.image.sample_distorted_bounding_box (为图像生成单个随机变形的边界框)

    原文地址: https://blog.csdn.net/tz_zs/article/details/77920116 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上 ...

  10. 韩国网费比其他国家贵10倍?—— 因网费太高,直播平台 Twitch 宣布2024年2月退出韩国市场

    看新闻,说直播平台 Twitch因为韩国的网费太贵宣布退出韩国,这个新闻给我看纳闷了,从来么有听说过哪个视频或直播公司因为网费贵而关停,这个估计是这种原因关停的第一家吧,于是比较好奇. 相关: htt ...