Face Recognition
The parameters are the following:
type |
object |
properties |
|
|
../common/image_input.yml |
additionalProperties |
False |
The OpenAPI definition of the HTTP interface is the following:
swagger: "2.0"
info:
description: "Face recognition aiapp."
version: "0.0.1"
title: "Face recognition"
paths:
/inference:
post:
summary: "Perform inference on image"
description: ""
consumes:
- "image/jpeg"
- "image/png"
produces:
- "application/json"
parameters:
- in: "body"
name: "body"
description: "Image to analyze"
required: true
schema:
type: string
format: binary
responses:
200:
description: "Success"
schema:
"$ref": 'results.yml'
The C++ interface definition is the following:
///
/// Ai-app interface for face recognition
///
/// \copyright 2018 NVISO SA. All rights reserved.
/// \license This project is released under the XXXXXX License.
///
#pragma once
#include "image_based.hpp"
#include <vector>
#include <numeric>
#include <cmath>
#include <cassert>
namespace lpdnn {
namespace ai_app {
/// Face recognition Ai-app
class Face_recognition : virtual public Image_based {
public:
struct Result {
bool success{};
std::vector<float> fingerprint;
enum class Distance {
l2,
cosine
};
/// Compute distance between two face_id
static float distance(const std::vector<float>& id1, const std::vector<float>& id2, Distance d);
/// Check if two ids represent the same face
/// \param threshold: max distance for two faces to be considered the same
static bool match(const std::vector<float>& id1, const std::vector<float>& id2, Distance d, float threshold);
private:
static float norm(const std::vector<float>& v);
};
/// Perform inference.
virtual Result execute(const Image& input, const std::vector<lpdnn::ai_app::Blob>& additional_inputs) = 0;
virtual Result execute(const Image& input) = 0;
/// @return our aiapp class id
const char* interface_name() const override { return ai_interface_name; }
static constexpr char const* ai_interface_name = "com_bonseyes/interfaces#face_recognition";
using Ai_interface_class = Face_recognition;
};
inline float Face_recognition::Result::norm(const std::vector<float>& v) {
return std::sqrt(std::inner_product(v.begin(), v.end(), v.begin(), 0.0L));
}
/// Check if two ids represent the same face
/// \param threshold: max distance for two faces to be considered the same
inline bool Face_recognition::Result::match(const std::vector<float>& id1, const std::vector<float>& id2, Distance d, float threshold) {
return distance(id1, id2, d) <= threshold;
}
inline float Face_recognition::Result::distance(const std::vector<float>& id1, const std::vector<float>& id2, Distance d) {
assert(id1.size() == id2.size());
double acc = 0;
switch (d) {
case Distance::l2:
for(size_t i = 0; i < id1.size(); i++) {
float diff = id1[i] - id2[i];
acc += diff * diff;
}
return sqrt(acc);
case Distance::cosine:
// https://stats.stackexchange.com/questions/146221/is-cosine-similarity-identical-to-l2-normalized-euclidean-distance/146279
// cosine distance = 1 - cosine similarity
return 1 - std::inner_product(id1.begin(), id1.end(), id2.begin(), 0.0L) / (norm(id1) * norm(id2));
default:
assert(false);
}
return acc;
}
} // namespace ai_app
} // namespace lpdnn
The default JSON ground truth schema is the following:
Face recognition AI App ground truth
Unique ID of the person depicted in the image |
|
type |
integer |
The default JSON result serialization is the following:
Face recognition AI App Result
type |
object |
||
properties |
|||
|
type |
boolean |
|
|
type |
array |
|
items |
type |
number |
|
additionalProperties |
False |