使用effet.js 拿到特征值就行人脸比对
前言
effet.js 是一款轻量级的人脸样式框架,专注于为网页呈现生动的面部动画效果。它基于 facemesh.js 进行二次开发,提供简单易用的 API,并支持获取 468 个精确的人脸特征点。
1.提取特征值
我们已经人脸添加为示例,拿到468点位
代码示例:
<template>
<div>
<div ref="faceVueTest" id="faceId" ></div>
<el-button @click="startFace">开启人脸</el-button>
<el-button @click="restartFace">重启人脸</el-button>
<el-button @click="closeFace">关闭人脸</el-button>
</div>
</template>
<script>
// $faceEffet 对象是在main.js 注册好的全局对象
export default {
name: "index",
data(){
return {
}
},
beforeDestroy(){
if (this.$faceEffet){
this.$faceEffet.close();
}
},
methods:{
startFace(){
// 人脸容器的初始化
this.$faceEffet.init({
el:this.$refs.faceVueTest, // 直接传入html元素 也可以直接传入字符 'faceId'
type:'addFace',
callBack:this.callBack // 阶段回调函数,会打印每个执行步骤,一般是在这个方法调用后端接口
})
},
callBack(data){
// 验证过程的回调打印
console.log(data)
},
restartFace(){
// 重启人脸容器
this.$faceEffet.restart()
},
closeFace(){
// 关闭人脸容器
this.$faceEffet.close();
}
}
}
</script>
其中features是我们人脸的特征点
callBack 打印的结果:

2.保存特征值
我们可以将features数组数据存入到我们的数据
将某个人的人脸特征值(整个 features 数组)保存为文件或数据库条目,例如 JSON 格式:
{
"id": "person_1",
"features": [
[x1, y1, z1],
[x2, y2, z2],
...
[x468, y468, z468]
]
}
可以使用 JSON 文件或数据库存储这些特征值,供后续比对使用。
3.计算相似度
当需要比对两个人脸时,核心是计算两个 features 特征数组的相似度。通常采用以下方法:
(1)欧几里得距离
计算两个 features 中每个关键点的欧几里得距离,然后将这些距离的平均值作为整体相似度:
公式:

代码示例:
function calculateDistance(point1, point2) {
return Math.sqrt(
Math.pow(point1[0] - point2[0], 2) +
Math.pow(point1[1] - point2[1], 2) +
Math.pow(point1[2] - point2[2], 2)
);
}
function compareFaces(features1, features2) {
let totalDistance = 0;
for (let i = 0; i < features1.length; i++) {
totalDistance += calculateDistance(features1[i], features2[i]);
}
return totalDistance / features1.length; // 返回平均距离
}
距离越小,相似度越高。如果平均距离低于某个阈值(例如 0.05),就可以认为两张脸相似。
(2)余弦相似度
用余弦相似度计算两组向量的相似性,适合特征值向量化后使用。
公式:

代码示例:
function calculateCosineSimilarity(features1, features2) {
let dotProduct = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < features1.length; i++) {
dotProduct += features1[i][0] * features2[i][0] +
features1[i][1] * features2[i][1] +
features1[i][2] * features2[i][2];
normA += Math.pow(features1[i][0], 2) + Math.pow(features1[i][1], 2) + Math.pow(features1[i][2], 2);
normB += Math.pow(features2[i][0], 2) + Math.pow(features2[i][1], 2) + Math.pow(features2[i][2], 2);
}
normA = Math.sqrt(normA);
normB = Math.sqrt(normB);
return dotProduct / (normA * normB); // 返回相似度,范围在 -1 到 1
}
结果越接近 1,表示两张脸越相似。
4.比对过程
完整流程如下:
- 从数据库中加载保存的特征值。
- 用 effet.js 提取待比对人脸的
features。 - 使用上述算法(欧几里得距离或余弦相似度)进行比对。
- 根据相似度或距离结果判断是否为同一张脸。
5.优化和注意事项
- 归一化处理:由于人脸的比例可能不同(例如距离摄像头远近),建议对关键点进行归一化处理,将特征值标准化到 [0, 1] 范围。
示例:
function normalize(features) {
const min = Math.min(...features.flat());
const max = Math.max(...features.flat());
return features.map(([x, y, z]) => [(x - min) / (max - min), (y - min) / (max - min), (z - min) / (max - min)]);
}
- 检测精度:在低光照或部分遮挡的情况下,检测精度可能降低,可以结合多个检测框架提升准确率。
更多资源
- 官方文档:faceeffet.com/
- GitHub 开源仓库:github.com/typsusan/ef…
- Gitee 开源仓库:gitee.com/susantyp/ef…