rcmalli / keras-vggface

VGGFace implementation with Keras Framework
MIT License
928 stars 416 forks source link

get celebrity name in keras-vggface based on index in tensorflowjs #90

Open ahmadbadpey opened 1 year ago

ahmadbadpey commented 1 year ago

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.

On the other hand I used VGGface 16 model json formatted to predict that user uploaded image is similar to which celebrity.

following are my javascript codes:

const MODEL_URL = '../faceapi_models'
Promise.all([
    faceapi.nets.ssdMobilenetv1.loadFromUri(MODEL_URL),
    faceapi.nets.faceRecognitionNet.loadFromUri(MODEL_URL),
])
    .then((val) => {
        console.log('val')
    })
    .catch((err) => {
        console.log(err)
    })

let model

async function loadModel() {
    model = await tf.loadLayersModel('../web_model/vgg_model.json');
}

loadModel()
    .then((val) => {
        console.log('Model is Loaded');
    })
    .catch((err) => {
        console.log('Model Not Load : ' + err)
    })

let croppedImage = null;
const user_pic = document.getElementById('user_pic')
const preview = document.getElementById('preview')
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

window.onload = function () {
    canvas.width = preview.width;
    canvas.height = preview.height;
    ctx.drawImage(preview, 0, 0);
};

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

user_pic.addEventListener('change', () => {
    const reader = new FileReader()
    reader.onload = (e) => {
        const img = new Image();
        img.onload = function () {
            canvas.width = img.width;
            canvas.height = img.height;
            ctx.drawImage(img, 0, 0);
        };
        img.src = e.target.result;
    }
    reader.readAsDataURL(user_pic.files[0]);

    detectFaces(user_pic.files[0])
})

async function detectFaces(input) {
    let imgURL = URL.createObjectURL(input)
    const imgElement = new Image()
    imgElement.src = imgURL

    const results = await faceapi.detectAllFaces(imgElement)
        .then(results => {

            if (Array.isArray(results) && results.forEach) {
                results.forEach(result => {
                    // console.log(result)
                    const {x, y, width, height} = result.box;
                    const xInt = Math.floor(x);
                    const yInt = Math.floor(y);
                    const widthInt = Math.floor(width);
                    const heightInt = Math.floor(height);

                    const crop = ctx.getImageData(xInt, yInt, widthInt, heightInt);
                    croppedImage = new ImageData(crop.data, widthInt, heightInt);

                    const input = tf.browser.fromPixels(croppedImage);

                    const resizedImage = tf.image.resizeBilinear(input, [224, 224]);
                    const inputTensor = resizedImage.expandDims(0);

                    // Make predictions
                  model.predict(inputTensor).data()
                      .then(predictions =>{
                          const predictionsArray = Array.from(predictions)
                          const celebrityIndex = predictionsArray.indexOf(Math.max(...predictionsArray));
                          console.log(celebrityIndex)

                          /*const celebrityName = classNames[celebrityIndex] || 'Unknown';
                          console.log(celebrityName);*/
                          //Display the results
                          /*const resultDisplay = document.getElementById('result');
                          resultDisplay.innerHTML = `Most similar celebrity: ${celebrityName}`;*/

                      });

                });
            } else {
                console.error('Results is not an array or does not have a forEach function.');
            }
        });
}

All things work fine and I get index of predicted celebrity. but now I do not know how to get name of that celebrity.

in python example code we use utils.decode_predictions method like this :

predict = vggface.predict(samples)
print(predict)

output = utils.decode_predictions(predict)
print(output)

# for result in output[0]:
#     print('%s: %.3f%%' % (result[0], result[1]*100))
prediction = output[0][0][0].replace("b'", "").replace("'","")

prediction

And it return name of celebrity that have most similarity to image.

But I do not know how can I implement this in tensorflow js ?