Skip to content

Instantly share code, notes, and snippets.

@alexanderk23
Created December 8, 2016 14:15
Show Gist options
  • Save alexanderk23/8cde2992d53951c51cc67651c5e2a4ab to your computer and use it in GitHub Desktop.
Save alexanderk23/8cde2992d53951c51cc67651c5e2a4ab to your computer and use it in GitHub Desktop.
FindFace API example (PHP)
<?php
define('DATEFMT', 'Y-m-d\TH:i:s.u');
/* Bounded box from "Common objects" */
class BBox {
var $x1, $y1, $x2, $y2;
function __construct($x1, $y1, $x2, $y2) {
$this->x1 = $x1;
$this->y1 = $y1;
$this->x2 = $x2;
$this->y2 = $y2;
}
/* from JSON object or array */
static function fromJSON($json) {
if (is_array($json)) {
return new BBox($json[0], $json[1], $json[2], $json[3]);
} else if (is_object($json)) {
return new BBox($json->x1, $json->y1, $json->x2, $json->y2);
}
}
function toJSON() {
return array("x1" => $this->x1, "y1" => $this->y1,
"x2" => $this->x2, "y2" => $this->y2);
}
}
/* Face from "Common objects" */
class Face {
var $id, $timestamp, $photo, $photo_hash, $bbox, $meta, $galleries;
static function fromJSON($json) {
$face = new Face();
foreach (array('id', 'timestamp', 'photo', 'photo_hash', 'meta', 'galleries') as $f) {
$face->{$f} = $json->{$f};
}
$face->timestamp = DateTime::createFromFormat(DATEFMT, $json->timestamp);
$face->bbox = BBox::fromJSON($json);
return $face;
}
}
/* FacenAPI wrapper */
class FacenAPI {
private $base_url, $token;
private $ch;
private function do_post($method, $rq) {
$body = json_encode($rq);
curl_reset($this->ch);
curl_setopt($this->ch, CURLOPT_POST, true);
curl_setopt($this->ch, CURLOPT_URL, $this->base_url . $method);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $body);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($this->ch, CURLOPT_HTTPHEADER, array(
'Content-Type: application/json',
'Authorization: Token ' . $this->token,
'Content-Length: ' . strlen($body)));
$result = curl_exec($this->ch);
$status = curl_getinfo($this->ch, CURLINFO_HTTP_CODE);
$response = json_decode($result);
if ((int)($status / 100) == 2)
return $response;
if ($response && property_exists($response, 'reason')) {
throw new Exception($response->code . ': ' . $response->reason);
} elseif ($status == 403) {
throw new Exception('AUTH error');
} elseif ($status == 400) {
throw new Exception('BAD request');
}
throw new Exception('BAD facenapi response code: ' . $status);
}
function __construct($base_url, $token) {
$this->base_url = $base_url;
$this->token = $token;
$this->ch = curl_init();
}
/* Detect faces found on image */
function detect($photo_url, $bbox = NULL) {
$rq = array("photo" => $photo_url);
if ($bbox) {
if (is_array($bbox)) {
if (count($bbox) != 4) {
throw new Exception('Invalid bbox size (' . count($bbox) . ')');
}
$rq['bbox'] = $bbox;
} else {
$rq['bbox'] = $bbox->toJSON();
}
}
$r = $this->do_post('/v0/detect', $rq);
$faces = array();
foreach ($r->faces as $box) {
$faces[] = BBox::fromJSON($box);
}
return $faces;
}
/* Check similarity of two faces
* @param optvars is an associative array with the following keys:
* "threshold" => float or string
* "mf_selector" => string
* limitations: bbox input parameter is not supported
*/
function verify($url1, $url2, $optvars = NULL) {
$rq = array("photo1" => $url1, "photo2" => $url2);
if (is_array($optvars)) {
$rq = array_merge($rq,
array_intersect_key($optvars,
array("threshold" => 0, "mf_selector" => 0)));
}
$rs = $this->do_post('/v0/verify', $rq);
$out = array();
foreach ($rs->results as $r) {
$out[] = (object)array("bbox1" => BBox::fromJSON($r->bbox1),
"bbox2" => BBox::fromJSON($r->bbox2),
"confidence" => (float)$r->confidence);
}
return $out;
}
/* Returns array of identified faces:
* [ { box: $src_match, matches: [ {confidence: $confidence, face: Face_Object} ] }
* limitations: bbox input parameter is not supported
*/
function identify($photo_url, $n = 1, $optvars = NULL) {
$rq = array("photo" => $photo_url, "n" => $n);
if (is_array($optvars)) {
$rq = array_merge($rq,
array_intersect_key($optvars,
array("threshold" => 0, "mf_selector" => 0)));
}
$rs = $this->do_post('/v0/identify', $rq);
$out = array();
foreach ($rs->results as $b => $faces) { // iterate over all boxes
$box = BBox::fromJSON(json_decode($b));
$matched = array();
foreach ($faces as $f) {
$matched[] = (object)array("confidence" => $f->confidence, "face" => Face::fromJSON($f->face));
}
$out[] = (object)array("box" => $box, "matches" => $matched);
}
return $out;
}
/* Enroll photo to the server
* Returns array of enrolled faces
*/
function enroll($photo_url, $optvars = NULL) {
$rq = array("photo" => $photo_url);
if (is_array($optvars)) {
$rq = array_merge($rq,
array_intersect_key($optvars,
array("mf_selector" => 0)));
}
print_r($rq);
$rs = $this->do_post('/v0/face', $rq);
$out = array();
foreach ($rs->results as $face) { // iterate over all faces
$out[] = Face::fromJSON($face);
}
return $out;
}
}
$api = new FacenAPI('https://api.findface.pro', 'YOUR_API_TOKEN');
$photos = array(
"http://static.findface.pro/sample.jpg",
"http://static.findface.pro/sample2.jpg"
// ...
);
// enrolls each of your photo URIs to the server
foreach($photos as $photo) {
$faces = $api->enroll($photo);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment