前言
最近负责的项目需要做一个前端的人脸检测,问过老大告诉我,人脸检测一般都需要很多资源包这些资源包呢一般都是几M起步,所以放在前端做不现实。但是对于好奇心强烈的我呢,没接触过的东西,只有两个想法,能实现或者不能实现。接下来进入正题。
寻找可用的js库
经过一番搜索,找到了两个可实现的库,一个是tracking.js还有一个是face-api.js(当然可能还有其他的我没有找到)。github地址:tracking.js、face-api.js。
效果对比
face-api.js:
tracking.js:
可以看到二者都是可以实现的但是 tracking.js与face-api 相比的话有点差强人意,也许是我的使用方式不正确(doge),从实际体验来说 tracking.js 会出现不稳定检测人脸现象,该现象在face-api.js也有只不过相比而言比较偶现。
接下来启动摄像头对人脸进行测试,也得出face-api.js对比tracking.js的想过更为理想,但是对角度光线等等环境因素也有一定的要求。感兴趣的可以自己尝试一下。
实现
face-api.js:
<script src="./face-api.min.js"></script>
<script src="./utils.js"></script>
<script async>
const video = $("#myVideo"), canvas = $("#myCanvas"), text = $("#text");
const MODEL_URL = '/models';
// 打开摄像头
// openCamera(video);
const detection = async () => {
// await faceapi.loadTinyFaceDetectorModel(MODEL_URL)
// common sizes are 128, 160, 224, 320, 416, 512, 608, for face tracking via webcam I would recommend using smaller sizes
// scoreThreshold?: number minimum confidence threshold default: 0.5
const options = new faceapi.TinyFaceDetectorOptions({ inputSize: 512 })
const fullFaceDescriptions = faceapi.detectSingleFace(video, options)
// withAgeAndGender
const dims = faceapi.matchDimensions(canvas, video, true)
try {
const resizedResults = await faceapi.resizeResults(fullFaceDescriptions, dims)
console.table(resizedResults)
if (resizedResults) {
text.innerText = "检测到有人"
// draw
faceapi.draw.drawDetections(canvas, resizedResults)
}
else {
text.innerText = "没有检测到人"
}
} catch(e) {
console.log(e)
}
}
(async () => {
await faceapi.loadTinyFaceDetectorModel(MODEL_URL)
text.innerText = "初始化完成"
})()
video.onplay = () => {
setInterval(detection, 200);
};
</script>
MODEL_URL是所需的资源包路径 所有的资源包都在该仓库中 资源包地址
tracking.js:
<script src="https://cdn.bootcdn.net/ajax/libs/tracking.js/1.1.3/tracking-min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/tracking.js/1.1.3/data/face.js"></script>
<script src="./utils.js"></script>
<script>
const canvasEl = $("#canvasEl"), videoEl = $("#videoEl"), text = $("#text");
const context = canvasEl.getContext("2d");
var objects = new tracking.ObjectTracker(['face']);
const drawTime = 300;
let prevNow = Date.now();
objects.on('track', function(event) {
if (event.data.length === 0) {
// No objects were detected in this frame.
context.clearRect(0, 0, canvasEl.width, canvasEl.height);
text.innerText = "没有检测到人"
} else {
text.innerText = "检测到有人"
event.data.forEach(function(rect) {
// draw
// rect.x, rect.y, rect.height, rect.width
const now = Date.now();
const usageTime = now - prevNow;
if (usageTime < drawTime) return;
prevNow = now;
context.strokeStyle = "#6eff00";
context.lineWidth = 1;
context.clearRect(0, 0, canvasEl.width, canvasEl.height);
context.strokeRect(rect.x, rect.y, rect.width, rect.height);
});
}
});
tracking.track('#videoEl', objects);
// openCamera(videoEl);
</script>
🥱前端萌新初来乍到,第一次发文,写得不好,望见谅,如有错误望指出!