持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情
一般人脸识别加处理都是后端来处理,现在尝试下用前端来实现一下
主要用的的库是face-api.js
www.npmjs.com/package/fac…
这个库基于tensorflow
又封装了一层,使得可以在浏览器和node环境中运行,
本文在浏览器环境简单实现一个demo
首先引入包,然后本地引入项目中的训练模型,在weights/
目录下
引入包后,可以通过挂载到window上的 faceapi 变量调用方法
- 引入模型
// 加载模型
async function loadModel() {
await faceapi.nets.ssdMobilenetv1.load("./weights");
await faceapi.loadFaceLandmarkModel("./weights/face_landmark");
}
loadFaceLandmarkModel 是获取五官和脸部轮廓的标记点
- 分析图片(实时图片或者视频都可以通过循环调用方法来实现)
这里先做一个静态图片分析
传入 img dom 或者视频等
const getFace = async () => {
const detections = await faceapi
.detectAllFaces(imgDom.value)
.withFaceLandmarks();
pointList.value = detections[0].landmarks._positions;
pointList.value.forEach((point, index) => {
drwaPoint(index, point);
});
};
此时在landmarks的positions 里面可以拿到人脸轮廓的标记点
能拿到点后我们能做的事就很多了,比如想给人脸增加一个眼镜,鼻子,嘴巴等
- 通过canvas 把 人脸的标记点绘制出来
const drwaPoint = (index, point) => {
const heightLightList = [36, 45, 30, 33, 48, 54];
cxt.value.fillStyle = heightLightList.includes(index) ? "blue" : "red";
cxt.value.font = "5px bold";
cxt.value.textAlign = "center";
cxt.value.textBaseline = "middle";
cxt.value.fillText(index, point.x, point.y);
};
此时人脸上就会显示轮廓标记
将几个关键的点做区分标记,方便后面做操作
4.拿到特殊点,然后根据点使用canvas绘制图片上去m
const addImg = (src, pointList, offsetX, offSetY) => {
const img = new Image();
img.src = src;
const point1 = pointList[0];
const point2 = pointList[1];
const width =
Math.sqrt((point2.x - point1.x) ** 2 + (point2.y - point1.y) ** 2) + 20;
img.onload = () => {
cxt.value.drawImage(
img,
point1.x - offsetX,// 图片没找到合适的,适当增加偏移量
point1.y - offSetY,// 图片没找到合适的,适当增加偏移量
width,
width
);
};
};
然后依次绘制眼镜,鼻子,嘴巴
addImg("assets/yanjing.png", [pointList.value[36], pointList.value[45]], 10, 60);
addImg( "assets/zuiba.png",[pointList.value[48], pointList.value[54]], 10, 40);
addImg("assets/bizi.png", [pointList.value[29], pointList.value[33]], 20, 20);
效果如下
现在只是简单的实现了人脸轮廓,后续可以增加视频实时采集
打印一下 faceapi.nets
看到里面还有很多有意思的方法
- ageGenderNet: new AgeGenderNet() // 年龄识别
- faceExpressionNet: new FaceExpressionNet(), // 表情识别
- faceLandmark68Net: new FaceLandmark68Net(), // 面部点位识别(68点)
- faceLandmark68TinyNet: new FaceLandmark68TinyNet(), // 面部快速点位识别
- faceRecognitionNet: new FaceRecognitionNet(), // 面部识别
...
比如识别一下年龄
// 先加载对应模型
await faceapi.nets.ageGenderNet.load("/weights/age");
...
const detections = await faceapi
.detectAllFaces(imgDom.value)
.withFaceLandmarks()
// 调用年龄识别api
.withAgeAndGender();
这时候就能拿到对应的年龄数据
其他的api,有兴趣的小伙伴可以试试。
还可以使用 tensorflow
获取更精细的一些标记点,根据点来判断人物状态,比如是否微笑,是否点头等