I am working with a heavily modified version of the OpenFace real-time web demo and needed to be able to detect an unknown face. The standard version of the demo, once trained with at least two people, always chooses the best fit even if it isn’t very good. Turns out it isn’t too hard to modify it to get extra information that’s helpful in making this extra decision.
If you look at demos/web/websocketserver.py in the OpenFace GitHub repo, line 243 looks like this:
self.svm = GridSearchCV(SVC(C=1), param_grid, cv=5).fit(X,y)
To get the extra information, the estimator constructor needs to be changed to:
self.svm = GridSearchCV(SVC(C=1, probability=True), param_grid, cv=5).fit(X,y)
This tells the estimator to return probabilities in addition to the best identity. The predictor is called in line 306:
identity = self.svm.predict(rep)
However, due to the change in the estimator, this new call will return probabilities:
probs = self.svm.predict_proba(rep)
There will be one entry in the probs list for each identity. The best match is obviously the one with the highest probability. I am thresholding this at 0.85 which seems to work reasonably well. If the best probability is lower than 0.85, I set the identity to -1 (=Unknown). Otherwise, identity is set to the index in the probs list with the highest value.