这几天研究了一下webrtc的基础能力,在此基础之上能实现的视频通话,互动等更多实用功能。项目中使用的是阿里的rtc,我研究的是声网的是否符合功能,后续会总结和记录一下应用到的几个功能实现方法。
今天要记录的功能是项目流识别人脸的功能,其实类似功能很常见了,人脸登录,身份证识别等,大都使用的是阿里api,百度api或者其他软件,我在研究这个功能期间,也查看了第三方的sdk的接入,大致流程是注册->创建功能项目->得到key,secret->接入sdk->合理调用->返回识别的结果。需要注意的是价格是否符合你的预算,而sdk的接入,最好还是后端来实现,避免前端的安全性问题。
除此之外还有什么方法呢,前端能实现吗?答案当然可以,使用face-api.js。
face-api.js:JavaScript人脸识别API的浏览器和nodejs实现在tensorflow.js核心之上的。tensorflow.js我们或许不陌生。TensorFlow是一个由Google开源的适用于人工智能(Artificial Intelligence, AI)和机器学习(Machine Learning, ML)的数据流图计算神器。这些框架的开发和使用让我们可以使用训练好的模型来实现我们的功能,也可以自己进行训练,这里不多讲。
face-api.js github代码链接。readme,api文档,demo都很完善,而且使用十分方便,我们不需要知道底层是如何实现的,我们只要会使用就可以了。实例代码如下:
const results = await faceapi
.detectAllFaces(queryImage2)
.withFaceLandmarks()
.withFaceDescriptors()
results.forEach(fd => {
const bestMatch = faceMatcher.findBestMatch(fd.descriptor)
console.log(bestMatch.toString())
})
就是这么简单,具体的算法和训练模型都不需要知道,根据功能选择方法调用,注意参数格式,返回结果,链式调用也十分方便。
我们了解了以上,就可以在音视频中进行使用了。以下是我开发demo的过程,不涉及到具体业务代码。
首先html部分,img是一张人脸的图片,video是后续开启摄像头,识别相机流所需要的,canvas则是结果可视化的输出,能讲人脸部分标出。
<div>
<img ref="image" src="./assets/bbt1.jpg" style="width: 640px;height:480px;">
<video ref="video" autoplay></video>
<canvas ref="canvas" width='640px' height='480px'></canvas>
<button @click="detectPic">检测图片</button>
<button @click="startVideo">开启摄像头</button>
</div>
先实现图片的人脸检测,因为视频可以认为是每一帧图片进行人脸检测,频率自己可以控制,所以实现图片的人脸检测,接入视频流就可以了。
1,引入faceapi,可以使用cdn,也可以在项目中安装 npm i face-api.js 来加载。
<script src="https://cdn.jsdelivr.***/npm/@vladmandic/face-api/dist/face-api.js"></script>
<!-- <script src="https://unpkg.dev/@vladmandic/face-api/dist/face-api.js"></script> -->
import * as faceapi from 'face-api.js'
2,在使用faceapi的模型之前,要加载模型,以 tinyFaceDetector 为例
Promise.all([
faceapi.***s.tinyFaceDetector.loadFromUri('./assets'),
// faceapi.***s.faceLandmark68***.loadFromUri('/models'),
// faceapi.***s.faceRecognition***.loadFromUri('/models')
])
或者
Promise.all([
faceapi.***s.tinyFaceDetector.loadFromUri('https://raw.githubusercontent.***/
justadudewhohacks/face-api.js/master/weights')
]).then(this.startVideo);
这里有一点要注意!!!我在项目中使用时,模型一直引入不成功,模型下载到本地,用相对路径是无法生效的,使用网络资源 https://raw.githubusercontent.***/justadudewhohacks/face-api.js/master/weights 是可以的,这里也包括了所有功能所需的模型,可是github资源国内实在是访问的慢,所以尝试访问本地,发现了,不能使用相对路径,必须是域名下可公开访问的绝对路径,比如public下,/models 下。
3,实现图片的人脸识别
async detectPic() {
const canvas = this.$refs.canvas;
const image = this.$refs.image;
const context = canvas.getContext('2d')
const displaySize = { width: 640, height: 480 };
context.drawImage(image, 0, 0, 640, 480);
// debugger
//获取分析人脸的数据
const detections = await faceapi.detectAllFaces(image, new faceapi.TinyFaceDetectorOptions())
const resizedDetections = faceapi.resizeResults(detections, displaySize);
//将人脸边框绘制到canvas上
faceapi.draw.drawDetections(canvas, resizedDetections)
}
传入image和识别的算法,需要标点或者识别性别等功能,就链式调用其他算法,返回识别的结果和坐标等信息,faceapi.draw可以绘制识别的结果在canvas上,一眼得到结果。
4,传入视频流实现人脸识别
async startVideo() {
const video = this.$refs.video;
const canvas = this.$refs.canvas;
const context = canvas.getContext('2d')
navigator.mediaDevices.getUserMedia({ video: true}).then(async s => {
video.srcObject = s
this.stream = s
})
const displaySize = { width: 640, height: 480 };
faceapi.matchDimensions(canvas, displaySize); // 维度
this.timer = setInterval(async () => {
//获取分析人脸的数据
const detections = await faceapi.detectAllFaces(video, new faceapi.TinyFaceDetectorOptions({scoreThreshold:0.1}));
const resizedDetections = faceapi.resizeResults(detections, displaySize);
context.clearRect(0, 0, 640, 480);
context.drawImage(video, 0, 0, 640, 480);
debugger
//将人脸边框绘制到canvas上
faceapi.draw.drawDetections(canvas, resizedDetections);
}, 20000);
}
navigator.mediaDevices.getUserMedia({ video: true}) 会返回摄像头的视频流,也可以 {audio:true,video:true}来得到音视频流,这里音频无用,所以没加。传入video,可以得到当前帧的人脸检测结果,但是实现视频人脸识别追踪,是需要使用setInterval或者递归调用来实现,setInterval可以自己控制调用的频率。