API de recherche inversée par visage
Laisse tes users chercher sur le web par visage ! Branche la recherche faciale FaceCheck sur ton appli, ton site ou ta plateforme sans prise de tête.
Notre API REST est simple et faite pour les devs. Une recherche coûte 3 crédits, que tu peux acheter en crypto à 0.10 USD le crédit.
Pour commencer
- ou se connecter à un compte existant
- Ajoute des crédits en Bitcoin ou Litecoin
- Lance tes recherches par visage depuis ton code
Exemples de code pour chercher par visage
- Upload - Balance une image en
multipart/form-datasur/api/upload_picet tu récupères unid_search - Recherche - Envoie l'
id_searchsur/api/searchpour lancer la recherche et suivre où ça en est - Résultats - Parcours le JSON avec les résultats
La doc complète des endpoints et des structures de données est dispo dans la spec Swagger FaceCheck.
Mode test
Le code d'exemple a TESTING_MODE=True par défaut. En mode test, on scanne que 100 000 visages. Ça tourne vite, ça pompe pas de ressources et ça te bouffe pas tes crédits - par contre les résultats servent à rien.
Quand t'es prêt à passer en prod, mets TESTING_MODE=False.
import time
import requests
import urllib.request
TESTING_MODE = True
APITOKEN = 'YOUR_API_TOKEN' # Your API Token
# Download the photo of the person you want to find
urllib.request.urlretrieve('https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300', "daniel.jpg")
image_file = 'daniel.jpg'
def search_by_face(image_file):
if TESTING_MODE:
print('****** TESTING MODE search, results are inacurate, and queue wait is long, but credits are NOT deducted ******')
site='https://facecheck.id'
headers = {'accept': 'application/json', 'Authorization': APITOKEN}
files = {'images': open(image_file, 'rb'), 'id_search': None}
response = requests.post(site+'/api/upload_pic', headers=headers, files=files).json()
if response['error']:
return f"{response['error']} ({response['code']})", None
id_search = response['id_search']
print(response['message'] + ' id_search='+id_search)
json_data = {'id_search': id_search, 'with_progress': True, 'status_only': False, 'demo': TESTING_MODE}
while True:
response = requests.post(site+'/api/search', headers=headers, json=json_data).json()
if response['error']:
return f"{response['error']} ({response['code']})", None
if response['output']:
return None, response['output']['items']
print(f'{response["message"]} progress: {response["progress"]}%')
time.sleep(1)
# Search the Internet by face
error, urls_images = search_by_face(image_file)
if urls_images:
for im in urls_images: # Iterate search results
score = im['score'] # 0 to 100 score how well the face is matching found image
url = im['url'] # url to webpage where the person was found
image_base64 = im['base64'] # thumbnail image encoded as base64 string
print(f"{score} {url} {image_base64[:32]}...")
else:
print(error)
using System.Net;
namespace FaceCheckAPI
{
public class SearchItem
{
public string? guid { get; set; }
public int score { get; set; }
public string? base64 { get; set; }
public string? url { get; set; }
public int index { get; set; } = -1;
}
public class Search_Results
{
public List<SearchItem>? items { get; set; }
}
public class InputImage
{
public string? base64 { get; set; }
public string? id_pic { get; set; }
}
public class BrowserJsonResponse
{
public string? id_search { get; set; }
public string? message { get; set; }
public int? progress { get; set; }
public string? error { get; set; }
public string? code { get; set; }
public Search_Results? output { get; set; }
public List<InputImage>? input { get; set; }
}
public class FaceCheckAPI
{
static bool TESTING_MODE = true;
static string APITOKEN = "YOUR_API_TOKEN"; // Your API Token
static string site = "https://facecheck.id";
static readonly HttpClient client = new HttpClient();
static FaceCheckAPI()
{
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", APITOKEN);
}
public static async Task<List<SearchItem>?> Search_by_FaceAsync(string image_file)
{
if (TESTING_MODE) Console.WriteLine("****** TESTING MODE search, results are inaccurate, and queue wait is long, but credits are NOT deducted ******");
using var content = new MultipartFormDataContent("Upload----" + DateTime.Now.Ticks.ToString("x"));
using var ImageStream = new FileStream(image_file, FileMode.Open, FileAccess.Read, FileShare.None);
content.Add(new StreamContent(ImageStream), "images", Path.GetFileName(image_file));
using var message = await client.PostAsync(site + "/api/upload_pic", content);
var input = await message.Content.ReadAsStringAsync();
BrowserJsonResponse? a = System.Text.Json.JsonSerializer.Deserialize<BrowserJsonResponse?>(input);
if (a.error != null) throw new Exception(a.error);
Console.WriteLine(a.message + " id_search=" + a.id_search);
while (true)
{
BrowserJsonResponse? b = await PostSearch(Convert.ToString(a.id_search));
if (b.error != null) throw new Exception(b.error);
if (b.output != null) return b.output.items;
Console.WriteLine($"{b.message} Progress: {b.progress}%");
await Task.Delay(1000);
}
}
private static async Task<BrowserJsonResponse?> PostSearch(string? id_search)
{
using var _Body = new StringContent($"{{\"id_search\":\"{id_search}\",\"with_progress\":true,\"status_only\":false,\"demo\":{(TESTING_MODE ? "true" : "false")}}}");
_Body.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
using var msg = await client.PostAsync(site + "/api/search", _Body);
string json = await msg.Content.ReadAsStringAsync();
return Utf8Json.JsonSerializer.Deserialize<BrowserJsonResponse>(json);
}
}
internal class Program
{
static async Task Main(string[] args)
{
try
{
//download a test image
using (WebClient webClient = new WebClient())
webClient.DownloadFile("https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300", "daniel.jpg");
//Search the Internet by face
var images = await FaceCheckAPI.Search_by_FaceAsync("daniel.jpg");
if (images != null)
foreach (SearchItem im in images) //Iterate search results
{
var score = im.score; // 0 to 100 score how well the face is matching found image
var url = im.url; // url to webpage where the person was found
var image_base64 = im.base64; // thumbnail image encoded as base64 string
//convert to binary .WEBP image
byte[] webp_image = Convert.FromBase64String(image_base64.Substring(image_base64.IndexOf(' ') + 1));
Console.WriteLine($"{score} {url} {image_base64?.Substring(0, 32)}...");
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
Console.ReadKey();
}
}
}
const axios = require('axios');
const FormData = require('form-data');
const fs = require('fs');
const https = require('https');
const TESTING_MODE = true;
const APITOKEN = 'YOUR_API_TOKEN';
const downloadImage = (url, filename) => {
return new Promise((resolve, reject) => {
const file = fs.createWriteStream(filename);
https.get(url, response => {
response.pipe(file);
file.on('finish', () => {
file.close(resolve);
});
file.on('error', reject);
});
});
};
const search_by_face = async (image_file) => {
if (TESTING_MODE) {
console.log('****** TESTING MODE search, results are inacurate, and queue wait is long, but credits are NOT deducted ******');
}
const site = 'https://facecheck.id';
const headers = {
accept: 'application/json',
Authorization: APITOKEN,
};
let form = new FormData();
form.append('images', fs.createReadStream(image_file));
form.append('id_search', '');
let response = await axios.post(site+'/api/upload_pic', form, { headers: {
...form.getHeaders(),
'accept': 'application/json',
'Authorization': APITOKEN
} });
response = response.data;
if (response.error) {
return [`${response.error} (${response.code})`, null];
}
const id_search = response.id_search;
console.log(`${response.message} id_search=${id_search}`);
const json_data = {
id_search: id_search,
with_progress: true,
status_only: false,
demo: TESTING_MODE,
};
while (true) {
response = await axios.post(site+'/api/search', json_data, { headers: headers });
response = response.data;
if (response.error) {
return [`${response.error} (${response.code})`, null];
}
if (response.output) {
return [null, response.output.items];
}
console.log(`${response.message} progress: ${response.progress}%`);
await new Promise(r => setTimeout(r, 1000));
}
};
const run = async () => {
await downloadImage('https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300', 'daniel.jpg');
// Search the Internet by face
const [error, urls_images] = await search_by_face('daniel.jpg');
if (urls_images) {
urls_images.forEach(im => {
const score = im.score; // 0 to 100 score how well the face is matching found image
const url = im.url; // url to webpage where the person was found
const image_base64 = im.base64; // thumbnail image encoded as base64 string
console.log(`${score} ${url} ${image_base64.slice(0, 32)}...`);
});
} else {
console.log(error);
}
}
run().catch(console.error);
const TESTING_MODE = true;
const APITOKEN = 'YOUR_API_TOKEN';
async function downloadTestImage(url: string, filepath: string): Promise<void> {
const fs = await import('fs');
const response = await fetch(url);
const buffer = await response.arrayBuffer();
fs.writeFileSync(filepath, Buffer.from(buffer));
}
async function searchByFace(imageFile: string) {
if (TESTING_MODE) {
console.log('****** TESTING MODE - results are inaccurate, queue is slow, but no credits deducted ******');
}
const fs = await import('fs');
const site = 'https://facecheck.id';
const headers = { 'Authorization': APITOKEN };
// Upload image
const formData = new FormData();
const imageBuffer = fs.readFileSync(imageFile);
const imageBlob = new Blob([imageBuffer]);
formData.append('images', imageBlob, imageFile);
const uploadRes = await fetch(`${site}/api/upload_pic`, {
method: 'POST',
headers,
body: formData
});
const uploadData = await uploadRes.json();
if (uploadData.error) {
throw new Error(`${uploadData.error} (${uploadData.code})`);
}
const idSearch = uploadData.id_search;
console.log(`${uploadData.message} id_search=${idSearch}`);
// Poll for results
const searchPayload = {
id_search: idSearch,
with_progress: true,
status_only: false,
demo: TESTING_MODE
};
while (true) {
const searchRes = await fetch(`${site}/api/search`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify(searchPayload)
});
const searchData = await searchRes.json();
if (searchData.error) {
throw new Error(`${searchData.error} (${searchData.code})`);
}
if (searchData.output) {
return searchData.output.items;
}
console.log(`${searchData.message} progress: ${searchData.progress}%`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
}
// Main
(async () => {
await downloadTestImage(
'https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300',
'daniel.jpg'
);
try {
const results = await searchByFace('daniel.jpg');
for (const item of results) {
console.log(`${item.score} ${item.url} ${item.base64.substring(0, 32)}...`);
}
} catch (error) {
console.error(error instanceof Error ? error.message : String(error));
}
})();
import org.json.JSONArray;
import org.json.JSONObject;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.NoRouteToHostException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
public class API_TEST {
private static final boolean TESTING_MODE = true;
private static final String APITOKEN = "YOUR_API_TOKEN";
private static final String IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";
public static void main(String[] args) {
try {
String imageFilePath = downloadImage();
JSONArray urlsImages;
if (TESTING_MODE) {
System.out.println("****** TESTING MODE search, results are bad, and queue wait is long, but credits are NOT deducted ******");
}
String site = "https://facecheck.id";
String authToken = APITOKEN;
// Upload the image
JSONObject uploadResponse = uploadImage(site, authToken, imageFilePath);
// System.out.println(uploadResponse);
if (uploadResponse.has("error") && !uploadResponse.isNull("error")) {
System.out.println("Error Code: " + uploadResponse.getString("code") + " , " + uploadResponse.getString("error"));
return;
}
String idSearch = uploadResponse.getString("id_search");
System.out.println(uploadResponse.getString("message") + " id_search=" + idSearch);
JSONObject jsonData = new JSONObject()
.put("id_search", idSearch)
.put("with_progress", true)
.put("status_only", false)
.put("demo", TESTING_MODE);
while (true) {
JSONObject searchResponse = searchImage(site, authToken, jsonData);
if (searchResponse.has("error") && !searchResponse.isNull("error")) {
System.out.println("Error Code: " + searchResponse.getString("code") + " , " + searchResponse.getString("error"));
return;
}
if (searchResponse.has("output") && !searchResponse.isNull("output")) {
urlsImages = searchResponse.getJSONObject("output").getJSONArray("items");
break;
}
System.out.println(searchResponse.getString("message") + " progress: " + searchResponse.getInt("progress") + "%");
Thread.sleep(1000);
}
if (urlsImages != null) {
for (int i = 0; i < urlsImages.length(); i++) {
JSONObject im = urlsImages.getJSONObject(i);
int score = im.getInt("score");
String url = im.getString("url");
String imageBase64 = im.getString("base64");
System.out.println(score + " " + url + " " + imageBase64.substring(0, 32) + "...");
}
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
public static String getImageExtensionFromURL(String imageUrl) throws MalformedURLException {
try {
URL url = new URL(imageUrl);
String path = url.getPath();
String fileName = path.substring(path.lastIndexOf('/') + 1);
return fileName.substring(fileName.lastIndexOf('.') + 1);
} catch (Exception exception) {
System.out.println(exception.getMessage());
throw exception;
}
}
private static String downloadImage() throws IOException {
String imageFileName = "SearchImage." + getImageExtensionFromURL(IMAGE_URL) ;
URL imageUrl = new URL(IMAGE_URL);
try (InputStream in = imageUrl.openStream()) {
Files.copy(in, Paths.get(imageFileName), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException exception) {
System.out.println(exception.getMessage());
throw exception;
}
return imageFileName;
}
private static JSONObject uploadImage(String site, String authToken, String imageFilePath) throws IOException {
String boundary = "*****" + Long.toHexString(System.currentTimeMillis()) + "*****";
String lineEnd = "\r\n";
String twoHyphens = "--";
URL url = new URL(site + "/api/upload_pic");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("accept", "application/json");
connection.setRequestProperty("Authorization", authToken);
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
dos.writeBytes(twoHyphens + boundary + lineEnd);
dos.writeBytes("Content-Disposition: form-data; name=\"images\";filename=\"" + imageFilePath + "\"" + lineEnd);
dos.writeBytes(lineEnd);
try (FileInputStream fis = new FileInputStream(imageFilePath)) {
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = fis.read(buffer)) != -1) {
dos.write(buffer, 0, bytesRead);
}
}
dos.writeBytes(lineEnd);
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
dos.flush();
}
try (InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line);
}
return new JSONObject(response.toString());
}
}
private static JSONObject searchImage(String site, String authToken, JSONObject jsonData) throws IOException {
URL url = new URL(site + "/api/search");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("accept", "application/json");
connection.setRequestProperty("Authorization", authToken);
connection.setRequestProperty("Content-Type", "application/json");
try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
dos.writeBytes(jsonData.toString());
dos.flush();
} catch (Exception exception) {
System.out.println(exception.getMessage());
throw exception;
}
try (InputStream is = connection.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
StringBuilder response = new StringBuilder();
String line;
while ((line = br.readLine()) != null) {
response.append(line);
}
return new JSONObject(response.toString());
} catch (NoRouteToHostException exception) {
System.out.println(exception.getMessage());
throw exception;
}
}
}
//#define CURL_STATICLIB
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <thread>
#include "curl/curl.h"
#include "json/json.h"
using namespace std;
const bool TESTING_MODE = true;
const std::string APITOKEN = "YOUR_API_TOKEN";
const std::string IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";
std::string getImageExtensionFromURL(const std::string& url) {
// Find the last occurrence of '.' in the URL
size_t dotPos = url.find_last_of('.');
if (dotPos == std::string::npos) {
// No extension found
return "";
}
// Find the first occurrence of '?' after the last dot position
size_t queryParamPos = url.find_first_of('?', dotPos);
// Extract the extension from the URL
std::string extension;
if (queryParamPos != std::string::npos) {
extension = url.substr(dotPos + 1, queryParamPos - dotPos - 1);
} else {
extension = url.substr(dotPos + 1);
}
return "jpg";
}
std::string downloadImage() {
std::string imageFileName = "SearchImage." + getImageExtensionFromURL(IMAGE_URL);
cout << "MESSAGE: Downloading Image..." << endl;
CURL* curl = curl_easy_init();
if (!curl) {
std::cout << "Error: Failed to initialize CURL." << std::endl;
exit(EXIT_FAILURE);
}
FILE* imageFile;
#ifdef _WIN32
fopen_s(&imageFile, imageFileName.c_str(), "wb");
#else
imageFile = fopen(imageFileName.c_str(), "wb");
#endif
if (!imageFile) {
std::cout << "Error: Failed to create image file." << std::endl;
curl_easy_cleanup(curl);
exit(EXIT_FAILURE);
}
curl_easy_setopt(curl, CURLOPT_URL, IMAGE_URL.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, imageFile);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
CURLcode res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(imageFile);
if (res != CURLE_OK) {
std::cout << "Error: Failed to download image." << std::endl;
exit(EXIT_FAILURE);
}
return imageFileName;
}
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* output) {
size_t totalSize = size * nmemb;
output->append(static_cast<char*>(contents), totalSize);
return totalSize;
}
Json::Value uploadImage(const std::string& site, const std::string& authToken, const std::string& imageFilePath) {
std::string boundary = "*****" + std::to_string(std::time(nullptr)) + "*****";
std::string url = site + "/api/upload_pic";
CURL* curl = curl_easy_init();
if (!curl) {
std::cout << "Error: Failed to initialize CURL." << std::endl;
exit(EXIT_FAILURE);
}
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, ("Authorization: " + authToken).c_str());
headers = curl_slist_append(headers, "accept: application/json");
std::string responseString; // To store the response data
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
// Create the form data
curl_mime* form = curl_mime_init(curl);
curl_mimepart* part = curl_mime_addpart(form);
curl_mime_name(part, "images");
curl_mime_filedata(part, imageFilePath.c_str());
// Attach the form data to the request
curl_easy_setopt(curl, CURLOPT_MIMEPOST, form);
// Set the write callback function
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
// Set the pointer to responseString as the user data to pass to the callback function
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
CURLcode res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_mime_free(form);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
std::cout << "Error: Failed to upload image." << std::endl;
exit(EXIT_FAILURE);
}
Json::Value response;
Json::CharReaderBuilder reader;
std::string errors;
std::istringstream iss(responseString);
if (!Json::parseFromStream(reader, iss, &response, &errors)) {
std::cout << "Error: Failed to parse JSON response." << std::endl;
exit(EXIT_FAILURE);
}
return response;
}
Json::Value searchImage(const std::string& site, const std::string& authToken, const Json::Value& jsonData) {
std::string url = site + "/api/search";
CURL* curl = curl_easy_init();
if (!curl) {
std::cout << "Error: Failed to initialize CURL." << std::endl;
exit(EXIT_FAILURE);
}
struct curl_slist* headers = nullptr;
headers = curl_slist_append(headers, ("Authorization: " + authToken).c_str());
headers = curl_slist_append(headers, "accept: application/json");
headers = curl_slist_append(headers, "Content-Type: application/json");
string responseString;
std::string jsonDataStr = jsonData.toStyledString();
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, jsonDataStr.c_str());
curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L);
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
//curl_easy_setopt(curl, CURLOPT_WRITEDATA, stdout);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
// Set the pointer to responseString as the user data to pass to the callback function
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseString);
// Set the option to suppress the output
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0L);
CURLcode res = curl_easy_perform(curl);
curl_slist_free_all(headers);
curl_easy_cleanup(curl);
if (res != CURLE_OK) {
std::cout << "Error: Failed to perform search." << std::endl;
exit(EXIT_FAILURE);
}
Json::Value response;
Json::CharReaderBuilder reader;
std::string errors;
std::istringstream iss(responseString);
if (!Json::parseFromStream(reader, iss, &response, &errors)) {
std::cout << "Error: Failed to parse JSON response." << std::endl;
exit(EXIT_FAILURE);
}
return response;
}
int main() {
try {
std::string imageFilePath = downloadImage();
Json::Value urlsImages;
if (TESTING_MODE) {
std::cout << "****** TESTING MODE search, results are bad, but credits are NOT deducted ******" << std::endl;
}
std::string site = "https://facecheck.id";
std::string authToken = APITOKEN;
// Upload the image
Json::Value uploadResponse = uploadImage(site, authToken, imageFilePath);
if(uploadResponse.isMember("error")) {
if (uploadResponse.isMember("error") && !uploadResponse["error"].isNull()) {
std::cout << "Error Code: " << uploadResponse["code"].asString() << " , " << uploadResponse["error"].asString() << std::endl;
return 1;
}
}
std::string idSearch = uploadResponse["id_search"].asString();
std::cout << uploadResponse["message"].asString() << " id_search=" << idSearch << std::endl;
Json::Value jsonData;
jsonData["id_search"] = idSearch;
jsonData["with_progress"] = true;
jsonData["status_only"] = false;
jsonData["demo"] = TESTING_MODE;
while (true) {
Json::Value searchResponse = searchImage(site, authToken, jsonData);
if (searchResponse.isMember("error") && !searchResponse["error"].isNull()) {
std::cout << "Error Code: " << searchResponse["code"].asString() << " , " << searchResponse["error"].asString() << std::endl;
return 1;
}
if (searchResponse.isMember("output") && !searchResponse["output"].isNull()) {
urlsImages = searchResponse["output"]["items"];
break;
}
std::cout<< searchResponse["message"].asString() << " progress: " << searchResponse["progress"] << "%" << std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
cout << "MESSAGE: Image Search Completed!" << endl;
if (!urlsImages.isNull()) {
for (unsigned int i = 0; i < urlsImages.size(); ++i) {
Json::Value im = urlsImages[i];
int score = im["score"].asInt();
std::string url = im["url"].asString();
std::string imageBase64 = im["base64"].asString();
std::cout << score << " " << url << " " << imageBase64.substr(0, 32) << "..." << std::endl;
}
}
}
catch (const std::exception& e) {
std::cout << "Exception: " << e.what() << std::endl;
return 1;
}
return 0;
}
import org.json.JSONArray
import org.json.JSONObject
import java.io.*
import java.net.HttpURLConnection
import java.net.MalformedURLException
import java.net.URL
import java.nio.file.Files
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
object FaceCheck {
private const val TESTING_MODE = true
private const val APITOKEN = "YOUR_API_TOKEN" // Your API Token
private const val IMAGE_URL = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300"
@JvmStatic
fun main(args: Array<String>) {
try {
val imageFilePath = downloadImage()
val urlsImages: JSONArray?
if (TESTING_MODE) {
println("****** TESTING MODE search, results are bad, but credits are NOT deducted ******")
}
val site = "https://facecheck.id"
val authToken = APITOKEN
// Upload the image
val uploadResponse = uploadImage(site, authToken, imageFilePath)
if (uploadResponse.has("error") && !uploadResponse.isNull("error")) {
println(
"Error Code: " + uploadResponse.getString("code") + " , " + uploadResponse.getString("error")
)
return
}
val idSearch = uploadResponse.getString("id_search")
println(uploadResponse.getString("message") + " id_search=$idSearch")
val jsonData = JSONObject()
.put("id_search", idSearch)
.put("with_progress", true)
.put("status_only", false)
.put("demo", TESTING_MODE)
while (true) {
val searchResponse = searchImage(site, authToken, jsonData)
if (searchResponse.has("error") && !searchResponse.isNull("error")) {
println(
"Error Code: " + searchResponse.getString("code") + " , " + searchResponse.getString("error")
)
return
}
if (searchResponse.has("output") && !searchResponse.isNull("output")) {
urlsImages = searchResponse.getJSONObject("output").getJSONArray("items")
break
}
println(
searchResponse.getString("message") + " progress: " + searchResponse.getInt("progress") + "%"
)
Thread.sleep(1000)
}
if (urlsImages != null) {
for (i in 0 until urlsImages.length()) {
val im = urlsImages.getJSONObject(i)
val score = im.getInt("score")
val url = im.getString("url")
val imageBase64 = im.getString("base64")
println("$score $url ${imageBase64.substring(0, 32)}...")
}
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: InterruptedException) {
e.printStackTrace()
}
}
@Throws(IOException::class)
private fun downloadImage(): String {
val imageFileName = "SearchImage.${getImageExtensionFromURL(IMAGE_URL)}"
val imageUrl = URL(IMAGE_URL)
imageUrl.openStream().use { `in` ->
Files.copy(`in`, Paths.get(imageFileName), StandardCopyOption.REPLACE_EXISTING)
}
return imageFileName
}
@Throws(IOException::class)
private fun uploadImage(site: String, authToken: String, imageFilePath: String): JSONObject {
val boundary = "*****" + java.lang.Long.toHexString(System.currentTimeMillis()) + "*****"
val lineEnd = "\r\n"
val twoHyphens = "--"
val url = URL("$site/api/upload_pic")
val connection = url.openConnection() as HttpURLConnection
connection.doOutput = true
connection.requestMethod = "POST"
connection.setRequestProperty("accept", "application/json")
connection.setRequestProperty("Authorization", authToken)
connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=$boundary")
DataOutputStream(connection.outputStream).use { dos ->
dos.writeBytes(twoHyphens + boundary + lineEnd)
dos.writeBytes("Content-Disposition: form-data; name=\"images\";filename=\"$imageFilePath\"$lineEnd")
dos.writeBytes(lineEnd)
FileInputStream(imageFilePath).use { fis ->
val buffer = ByteArray(1024)
var bytesRead: Int
while (fis.read(buffer).also { bytesRead = it } != -1) {
dos.write(buffer, 0, bytesRead)
}
}
dos.writeBytes(lineEnd)
dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd)
dos.flush()
}
val response = StringBuilder()
connection.inputStream.bufferedReader().use { br ->
var line: String?
while (br.readLine().also { line = it } != null) {
response.append(line)
}
}
return JSONObject(response.toString())
}
@Throws(IOException::class)
private fun searchImage(site: String, authToken: String, jsonData: JSONObject): JSONObject {
val url = URL("$site/api/search")
val connection = url.openConnection() as HttpURLConnection
connection.doOutput = true
connection.requestMethod = "POST"
connection.setRequestProperty("accept", "application/json")
connection.setRequestProperty("Authorization", authToken)
connection.setRequestProperty("Content-Type", "application/json")
DataOutputStream(connection.outputStream).use { dos ->
dos.writeBytes(jsonData.toString())
dos.flush()
}
val response = StringBuilder()
connection.inputStream.bufferedReader().use { br ->
var line: String?
while (br.readLine().also { line = it } != null) {
response.append(line)
}
}
return JSONObject(response.toString())
}
@Throws(MalformedURLException::class)
fun getImageExtensionFromURL(imageUrl: String): String {
try {
val url = URL(imageUrl)
val path = url.path
val fileName = path.substring(path.lastIndexOf('/') + 1)
return fileName.substring(fileName.lastIndexOf('.') + 1)
} catch (exception: Exception) {
// If any error occurs, return null or an appropriate default value
println(exception.message)
throw exception
}
}
}
use reqwest;
use serde::{Deserialize, Serialize};
use std::fs::File;
use std::io::Write;
use tokio;
const TESTING_MODE: bool = true;
const API_TOKEN: &str = "YOUR_API_TOKEN";
#[derive(Debug, Deserialize)]
struct UploadResponse {
error: Option<String>,
code: Option<String>,
id_search: Option<String>,
message: Option<String>,
}
#[derive(Debug, Deserialize)]
struct SearchResponse {
error: Option<String>,
code: Option<String>,
message: Option<String>,
progress: Option<u32>,
output: Option<SearchOutput>,
}
#[derive(Debug, Deserialize)]
struct SearchOutput {
items: Vec<SearchResult>,
}
#[derive(Debug, Deserialize)]
struct SearchResult {
score: f64,
url: String,
base64: String,
}
#[derive(Debug, Serialize)]
struct SearchRequest {
id_search: String,
with_progress: bool,
status_only: bool,
demo: bool,
}
async fn download_file(url: &str, filename: &str) -> Result<(), Box<dyn std::error::Error>> {
let response = reqwest::get(url).await?;
let bytes = response.bytes().await?;
let mut file = File::create(filename)?;
file.write_all(&bytes.to_vec())?;
Ok(())
}
async fn search_by_face(image_file: &str) -> Result<Vec<SearchResult>, Box<dyn std::error::Error>> {
if TESTING_MODE {
println!("****** TESTING MODE search, results are inaccurate, and queue wait is long, but credits are NOT deducted ******");
}
let site = "https://facecheck.id";
let client = reqwest::Client::new();
// Upload the image
let file = tokio::fs::read(image_file).await?;
let part = reqwest::multipart::Part::bytes(file)
.file_name(image_file.to_string())
.mime_str("image/jpeg")?;
let form = reqwest::multipart::Form::new()
.part("images", part);
let upload_response: UploadResponse = client
.post(format!("{}/api/upload_pic", site))
.header("accept", "application/json")
.header("Authorization", API_TOKEN)
.multipart(form)
.send()
.await?
.json()
.await?;
if let Some(error) = upload_response.error {
return Err(format!("{} ({})", error, upload_response.code.unwrap_or_default()).into());
}
let id_search = upload_response.id_search
.ok_or("No id_search in response")?;
println!("{} id_search={}", upload_response.message.unwrap_or_default(), id_search);
// Poll for results
let search_request = SearchRequest {
id_search: id_search.clone(),
with_progress: true,
status_only: false,
demo: TESTING_MODE,
};
loop {
let search_response: SearchResponse = client
.post(format!("{}/api/search", site))
.header("accept", "application/json")
.header("Authorization", API_TOKEN)
.json(&search_request)
.send()
.await?
.json()
.await?;
if let Some(error) = search_response.error {
return Err(format!("{} ({})", error, search_response.code.unwrap_or_default()).into());
}
if let Some(output) = search_response.output {
return Ok(output.items);
}
println!(
"{} progress: {}%",
search_response.message.unwrap_or_default(),
search_response.progress.unwrap_or(0)
);
tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
}
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Download the photo
let image_url = "https://www.indiewire.com/wp-content/uploads/2018/01/daniel-craig.jpg?w=300";
let image_file = "daniel.jpg";
download_file(image_url, image_file).await?;
// Search the Internet by face
match search_by_face(image_file).await {
Ok(urls_images) => {
for im in urls_images {
let score = im.score;
let url = im.url;
let base64_preview = if im.base64.len() > 32 {
&im.base64[..32]
} else {
&im.base64
};
println!("{} {} {}...", score, url, base64_preview);
}
}
Err(error) => {
println!("{}", error);
}
}
Ok(())
}