face-api.js的基本使用方法

安装依赖

开发face-api.js最好使用ts来开发,可以省去很多查文档的时间,并且face-api是支持ts的

1
npm i face-api.js -S

下载模型文件

face-api.jsgithub上下载代码包并将其中的w文件夹中的内容拷贝到自己的项目models文件夹中

引入依赖

1
import { detectSingleFace, FaceDetection, FaceLandmarks68, nets, TinyFaceDetectorOptions, WithFaceLandmarks } from 'face-api.js'

获取摄像头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
export class VideoController {
private width: number
private height: number
private container: HTMLElement
public videoElement: HTMLVideoElement
constructor(width: number, height: number, container: HTMLElement = document.body) {
this.videoElement = document.createElement('video')
this.width = width
this.height = height
this.container = container
}
createVideo() {
this.videoElement.width = this.width
this.videoElement.height = this.height
this.videoElement.autoplay = true
this.videoElement.muted = true
this.videoElement.controls = false
this.videoElement.style.display = 'none'
this.videoElement.style.position = 'absolute'
this.videoElement.style.top = '0px'
this.videoElement.style.left = '0px'
this.videoElement.setAttribute('playsinline', 'playsinline')
this.container.append(this.videoElement)
}
setSrc(url:string){
this.videoElement.src = url
}
async getCamera() {
const mediaDevices = navigator.mediaDevices

console.log('开始获取摄像头数据')
const stream = await mediaDevices.getUserMedia(
{
'audio': false,
'video': {
width: {
// min: 1280,
ideal: this.height
// max: 2560,
},
height: {
// min: 720,
ideal: this.width
// max: 1440
},

// // sourceId: 'default',
facingMode: { exact: 'user' }
}
}
).catch(err => {
console.log('摄像头数据获取失败',err)
})

if (stream) {
console.log('获取到摄像头数据',stream.getTracks())
this.videoElement.srcObject = stream
this.videoElement.play()
this.videoElement.style.transform = 'rotateY(180deg)'
// this.videoElement.style.opacity = '0'
this.videoElement.onloadedmetadata = () => {
// const cameraSize = {
// 'width': this.videoElement.offsetWidth,
// 'height': this.videoElement.offsetHeight
// }
// if (window.innerWidth < window.innerHeight) {
// // 竖屏
// if (cameraSize.height < window.innerHeight) {
// console.log(document.body.offsetHeight)
// this.videoElement.setAttribute('height', document.body.offsetHeight.toString() + 'px');
// }
// }
// else {
// // 横屏
// if (cameraSize.width < window.innerWidth) {
// this.videoElement.setAttribute('width', document.body.offsetWidth.toString() + 'px');
// }
// }
}
}
}

}

加载模型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Promise.all([
// 每一种模型对应一种检测类型,如表情,人脸轮廓,年龄等,可根据需要选择性加载
nets.tinyFaceDetector.loadFromUri('./static/model'),
nets.faceLandmark68Net.loadFromUri('./static/model'),
nets.faceRecognitionNet.loadFromUri('./static/model'),
nets.faceExpressionNet.loadFromUri('./static/model'),
]).then(async () => {
this.video = new VideoController(window.innerWidth, window.innerHeight, this.$window)
this.video.createVideo()
this.video.getCamera()
this.video.videoElement.addEventListener('play', () => {
setTimeout(() => {
// 这里开始获取摄像头的画面
}, 1000)
})
}).catch(err => {
console.log('人脸识别数据加载失败', err)
})

人脸识别

当获取到摄像头画面后,就可以进行人脸识别了
使用face-api下的detectSingleFace函数可以得到人脸的基本数据(大小和位置),如果需要进一步判断年龄,表情等,需要使用对应的方法解析获得的detections

1
2
3
4
5
6
7
8
const detections = await detectSingleFace(
this.video.videoElement,
new TinyFaceDetectorOptions()
) // 添加各种识别信息
.withFaceLandmarks() // 人脸区域
.withFaceExpressions() // 人脸表情
.withFaceDescriptors() //
.withAgeAndGender() // 年龄

最终会获得一个人脸数据的数组,数组内是多人的人脸数据,使用face-api自带的drew方法可以绘制到canvas中。