Face Recognition

The parameters are the following:

type

object

properties

  • image_input

../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

  • success

type

boolean

  • fingerprint

type

array

items

type

number

additionalProperties

False