Skip to content

ArcFaceTF v1.1.0

Compare
Choose a tag to compare
@Shankar203 Shankar203 released this 31 May 21:55
· 48 commits to main since this release

TensorFlow.js implementation of ArcFace

ArcFace (Additive Angular Margin Loss for Deep Face Recognition), published in CVPR 2019. Was officially implemented by DeepInsight available here. This Model was pretrained and benchmarked on MS1M, VGG2 and CASIA-Webface datasets, It is exported to TensorFlow.js to run inference on node backend,

Additive Angular Margin Loss(ArcFace) has a clear geometric interpretation due to the exact correspondence to the geodesic distance on the hypersphere, and consistently outperforms the state-of-the-art and can be easily implemented with negligible computational overhead.

Run Model Inference on TensorflowJS

Model takes input of the path pointing to model.json file, The input shape of the model on which it is trained is [112,112], and outputs embeddings of shape (1,512). Do the basic preprocessing stuff changing dtype, resizing, dividing by 255, Remember during resizing the aspect ratio shouldn't change. As this is keras model use use tf.loadLayersModel to run model inference, aslo don't forget to Normalize the embeddings before passing it to cosineDistance function.

const tf = require("@tensorflow/tfjs-node");

const ArcFace_MODEL_PTH = "https://github.com/Shankar203/Microsoft-Engage-FaceRecognition/releases/download/ArcFace/model.json";
const ArcFace_INPUT_SHAPE = [112, 112];
const ArcFace_THRESHOLD   = 0.68;

const processImg = (img, tarSize) => {
	img = tf.cast(img, "float32");
	img = resizeImg(img, tarSize);
	img = tf.expandDims(img, 0);
	img = tf.div(img, 255);
	return img;
};

// Resize image without changing aspect ratio (imp)
const resizeImg = (img, tarSize) => {
	var [h, w] = img.shape;
	var [h_tar, w_tar] = tarSize;
	var ratio = Math.max(h/h_tar, w/w_tar);
	var padh = parseInt((h_tar*ratio - h) / 2);
	var padw = parseInt((w_tar*ratio - w) / 2);
	img = tf.pad(img, [[padh,padh],[padw, padw],[0,0]]);
	img = tf.image.resizeBilinear(img, tarSize);
	return img;
};

const getEmbeddings = async (img) => {
	var img = processImg(img, ArcFace_INPUT_SHAPE);
	var model = await await tf.loadLayersModel(ArcFace_MODEL_PTH);
	var ebd = model.predict(img);
        ebd = ebd.div(ebd.norm()).squeeze();
	return ebd;
};

const compare = async (imgBuffer1, imgBuffer2, threshold = ArcFace_THRESHOLD) => {
	var img1 = tf.node.decodeImage(imgBuffer1, (channels = 3));
	var img1 = tf.node.decodeImage(imgBuffer1, (channels = 3));
	var ebd1  = await getEmbeddings(img1);
        var ebd2  = await getEmbeddings(img2);
        var cosDist = tf.losses.cosineDistance(ebd1, ebd2);
	var similar = cosDist.arraySync() <= threshold;
	return similar;
};

Convert ArcFace Model from tensorflow to tfjs

First install tensorflowjs python library using pip/conda, Now run the tensorflowjs_converter command with input_format keras to convert them to tensorflowjs layers model.

$ pip install -q tensorflowjs

$ tensorflowjs_converter --input_format keras \
                       ./arcface/arcface.h5 \
                       ./ArcFaceJS

Model Benchmarking

Backbone Head LFW AgeDB-30 CFP-FP
ResNet50 ArcFace 99.42 95.32 92.56

Model Architecture

archi

References