javascriptpythonkerasface-detectionface-api

detectAllFaces() method can not recognize any faces in face-api.js


I'm using face-api.js Javascript API to develop a web app that user uploads her/his picture and we want to detect faces in the picture.

this is my HTML codes:

<input type="file" id="user_pic" accept="image/x-png,image/gif,image/jpeg">
<img src="images/250x250.webp" id="preview" alt="">

and following code are what I wrote to face detection:

document.addEventListener('DOMContentLoaded', function() {
    run()
});

async function run() {
    // load the models
    await faceapi.loadMtcnnModel('../faceapi_models')
    await faceapi.loadFaceRecognitionModel('../faceapi_models')
}


const user_pic = document.getElementById('user_pic')
const preview = document.getElementById('preview')

user_pic.addEventListener('change', () => {
    const reader = new FileReader()
    reader.onload = (e) => {
        preview.src = e.target.result
    }
    reader.readAsDataURL(user_pic.files[0]);

    detectFaces(user_pic.files[0])
})

preview.onclick = () => user_pic.click()


async function detectFaces(input) {

    let imgURL = URL.createObjectURL(input)

    const imgElement = new Image()
    imgElement.src = imgURL

    const results = faceapi.detectAllFaces(imgElement)
        .withFaceLandmarks()
        .withFaceExpressions()
    console.log(results)

    results.forEach(result => {
        const { x, y, width, height } = result.detection.box;
        ctx.strokeRect(x, y, width, height);
    });

}

Now whenever I select an image results variable is empty and this error occured:

Uncaught (in promise) TypeError: results.forEach is not a function

Solution

  • The withFaceExpressions() method is async. You should use await or then().

    Documentation for the reference

    Using await

    const results = await faceapi.detectAllFaces(imgElement)
       .withFaceLandmarks()
       .withFaceExpressions();
    

    Using then()

    faceapi.detectAllFaces(imgElement)
       .withFaceLandmarks()
       .withFaceExpressions()
       .then( results => {
          results.forEach(result => {
            const { x, y, width, height } = result.detection.box;
            ctx.strokeRect(x, y, width, height);
          });
       });