Skip to content

人脸比对

检测出两张图片中的最相似人脸

通用OCR文档

概述

人脸比对是人脸识别中一项重要的功能,其主要目标是从两张图片中找出最相似的人脸,并提供其位置信息以及相似度评分。这项功能在实际应用中具有广泛的用途,例如犯罪调查、身份验证、社交媒体应用等等。思核的人脸比对功能以其快速的处理速度和高精度的结果而受到青睐。

通过人脸比对的API,您只需输入两张图片,API将返回两张图片中最相似的人脸的位置信息以及它们之间的相似度。

API访问点

  • URL: https://mono-backend.sihe.cloud/api/ai_service/v1/face_verify
  • 请求方法: POST

AK/SK

将API集成到项目中之前,您首先需要在平台中创建属于自己账户的AccessKey ID 和 AccessKey Secret,用于API调用的授权。创建方式详见下图。 ak-sk管理.jpg

请求头

json
{"Content-Type": xxxx, "Accept": "application/json", "Authorization": xxxx}
// 其中ContentType和Authorization的获取请参考下方代码示例
{"Content-Type": xxxx, "Accept": "application/json", "Authorization": xxxx}
// 其中ContentType和Authorization的获取请参考下方代码示例

请求参数

请求参数应该以multipart/form-data格式在请求中发送。

参数名类型必需描述
img_url1字符串待比对图片1地址链接
img_file1File待比对图片1文件(与链接二选一)
img_url2字符串待比对图片2地址链接
img_file2File待比对图片2文件(与链接二选一)

响应

API的响应以JSON格式返回。

响应内容说明

Key类型描述
distance数值两张人脸的距离,越小代表相似度越高
verified布尔是否认为是相似
threshold数值判断相似时的参考阈值
similarity_metric字符串计算距离的方法
facial_area列表分别包含img1和img2中人脸的x、y坐标和宽度w高度h

成功响应示例

json
{
    "result": {
        "verified": true,
        "distance": 0.23841556131645913,
        "threshold": 0.3,
        "similarity_metric": "cosine",
        "facial_areas": {
            "img1": {
                "x": 299,
                "y": 41,
                "w": 85,
                "h": 85
            },
            "img2": {
                "x": 137,
                "y": 44,
                "w": 81,
                "h": 81
            }
        }
    }
}
{
    "result": {
        "verified": true,
        "distance": 0.23841556131645913,
        "threshold": 0.3,
        "similarity_metric": "cosine",
        "facial_areas": {
            "img1": {
                "x": 299,
                "y": 41,
                "w": 85,
                "h": 85
            },
            "img2": {
                "x": 137,
                "y": 44,
                "w": 81,
                "h": 81
            }
        }
    }
}

代码示例

Python示例

python
import requests
import hashlib
import hmac
import base64
from requests_toolbelt import MultipartEncoder

# 此处替换为您的AccessKey信息
ak = 'xxxxxxx'
sk = 'xxxxxxxxxxxxxxxx'


class SignClient:
    @staticmethod
    def _get_canonicalized_headers(headers):
        canon_keys = []
        for k in headers:
            if k.startswith('x-acs-'):
                canon_keys.append(k)
        canon_keys = sorted(canon_keys)
        canon_header = ''
        for k in canon_keys:
            canon_header += '%s:%s' % (k, headers[k])
        return canon_header

    @staticmethod
    def _get_canonicalized_resource(pathname, query):
        if len(query) <= 0:
            return pathname
        resource = '%s?' % pathname
        query_list = sorted(list(query))
        for key in query_list:
            if query[key] is not None:
                if query[key] == '':
                    s = '%s&' % key
                else:
                    s = '%s=%s&' % (key, query[key])
                resource += s
        return resource[:-1]

    @staticmethod
    def get_string_to_sign(request, path):
        """
        Get the string to be signed according to request
        @param request  which contains signed messages
        @return the signed string
        """
        method, pathname, headers, query = request.method, path, request.headers, request.params

        accept = '' if headers.get('Accept') is None else headers.get('Accept')
        content_md5 = '' if headers.get('Content-MD5') is None else headers.get('Content-MD5')
        content_type = '' if headers.get('Content-Type') is None else headers.get('Content-Type')
        date = '' if headers.get('Date') is None else headers.get('Date')

        header = '%s\n%s\n%s\n%s\n%s\n' % (method, accept, content_md5, content_type, date)
        canon_headers = SignClient._get_canonicalized_headers(headers)
        canon_resource = SignClient._get_canonicalized_resource(pathname, query)
        sign_str = header + canon_headers + canon_resource
        return sign_str

    @staticmethod
    def get_signature(sign, secret):
        """
        Get signature according to stringToSign, secret
        @param sign the signed string
        @param secret accesskey secret
        @return the signature
        """
        hash_val = hmac.new(secret.encode('utf-8'), sign.encode('utf-8'), hashlib.sha1).digest()
        signature = base64.b64encode(hash_val).decode('utf-8')
        return signature


if __name__ == '__main__':

    url = "https://mono-backend.sihe.cloud"
    pathname = '/api/ai_service/v1/face_verify'

    data = MultipartEncoder(
        fields={
            'img_url1': 'https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500'
            'img_url2': 'https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500'
        }
    )
    # data = MultipartEncoder(
    #     fields={
    #         'img_file1': ('20230707-223601.png', open('C:\Users\gousq\Desktop\20230707-223601.png', 'rb'), 'image/jpeg'),
    #         'img_file2': ('20230707-223601.png', open('C:\Users\gousq\Desktop\20230707-223601.png', 'rb'), 'image/jpeg')
    #     }
    # )

    header = {"Content-Type": data.content_type, "Accept": "application/json"}

    # 图片地址和文件二选一
    request = requests.Request('POST', url + pathname, headers=header, data=data)

    signToString = SignClient.get_string_to_sign(request, pathname)
    sign = SignClient.get_signature(signToString, sk)
    request.headers['Authorization'] = 'acs ' + ak + ':' + sign

    # 发送请求
    s = requests.Session()
    response = s.send(request.prepare(), timeout=10)
    print(response.text)
import requests
import hashlib
import hmac
import base64
from requests_toolbelt import MultipartEncoder

# 此处替换为您的AccessKey信息
ak = 'xxxxxxx'
sk = 'xxxxxxxxxxxxxxxx'


class SignClient:
    @staticmethod
    def _get_canonicalized_headers(headers):
        canon_keys = []
        for k in headers:
            if k.startswith('x-acs-'):
                canon_keys.append(k)
        canon_keys = sorted(canon_keys)
        canon_header = ''
        for k in canon_keys:
            canon_header += '%s:%s' % (k, headers[k])
        return canon_header

    @staticmethod
    def _get_canonicalized_resource(pathname, query):
        if len(query) <= 0:
            return pathname
        resource = '%s?' % pathname
        query_list = sorted(list(query))
        for key in query_list:
            if query[key] is not None:
                if query[key] == '':
                    s = '%s&' % key
                else:
                    s = '%s=%s&' % (key, query[key])
                resource += s
        return resource[:-1]

    @staticmethod
    def get_string_to_sign(request, path):
        """
        Get the string to be signed according to request
        @param request  which contains signed messages
        @return the signed string
        """
        method, pathname, headers, query = request.method, path, request.headers, request.params

        accept = '' if headers.get('Accept') is None else headers.get('Accept')
        content_md5 = '' if headers.get('Content-MD5') is None else headers.get('Content-MD5')
        content_type = '' if headers.get('Content-Type') is None else headers.get('Content-Type')
        date = '' if headers.get('Date') is None else headers.get('Date')

        header = '%s\n%s\n%s\n%s\n%s\n' % (method, accept, content_md5, content_type, date)
        canon_headers = SignClient._get_canonicalized_headers(headers)
        canon_resource = SignClient._get_canonicalized_resource(pathname, query)
        sign_str = header + canon_headers + canon_resource
        return sign_str

    @staticmethod
    def get_signature(sign, secret):
        """
        Get signature according to stringToSign, secret
        @param sign the signed string
        @param secret accesskey secret
        @return the signature
        """
        hash_val = hmac.new(secret.encode('utf-8'), sign.encode('utf-8'), hashlib.sha1).digest()
        signature = base64.b64encode(hash_val).decode('utf-8')
        return signature


if __name__ == '__main__':

    url = "https://mono-backend.sihe.cloud"
    pathname = '/api/ai_service/v1/face_verify'

    data = MultipartEncoder(
        fields={
            'img_url1': 'https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500'
            'img_url2': 'https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500'
        }
    )
    # data = MultipartEncoder(
    #     fields={
    #         'img_file1': ('20230707-223601.png', open('C:\Users\gousq\Desktop\20230707-223601.png', 'rb'), 'image/jpeg'),
    #         'img_file2': ('20230707-223601.png', open('C:\Users\gousq\Desktop\20230707-223601.png', 'rb'), 'image/jpeg')
    #     }
    # )

    header = {"Content-Type": data.content_type, "Accept": "application/json"}

    # 图片地址和文件二选一
    request = requests.Request('POST', url + pathname, headers=header, data=data)

    signToString = SignClient.get_string_to_sign(request, pathname)
    sign = SignClient.get_signature(signToString, sk)
    request.headers['Authorization'] = 'acs ' + ak + ':' + sign

    # 发送请求
    s = requests.Session()
    response = s.send(request.prepare(), timeout=10)
    print(response.text)

JAVA示例

JAVA
//依赖库
//<dependency>
//    <groupId>com.aliyun</groupId>
//    <artifactId>aliyun-java-sdk-core</artifactId>
//    <version>4.5.20</version>
//</dependency>
//<dependency>
//    <groupId>com.squareup.okhttp3</groupId>
//    <artifactId>okhttp</artifactId>
//    <!-- MinIO requires a higher version -->
//    <version>4.8.1</version>
//</dependency>

import com.aliyuncs.auth.HmacSHA1Signer;
import com.aliyuncs.auth.RoaSignatureComposer;
import com.aliyuncs.auth.Signer;
import com.aliyuncs.http.MethodType;
import kotlin.Pair;
import okhttp3.*;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class JavaDemo {

    //请替换成您的AccessKeyId和AccessKeySecret
    static final String accessKeyId = "xxxxxxx";
    static final String accessKeySecret = "xxxxxxxxxxxxxxxxxxxx";

    public static void main(String[] args){

        String url = "https://mono-backend.sihe.cloud/api/ai_service/v1/face_verify";

        // 图片地址和文件二选一
        String img_url1 = "https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500";
        String img_url2 = "https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500";
        File img_file1 = new File("C:\Users\gousq\Desktop\20230707-223601.png");
        File img_file2 = new File("C:\Users\gousq\Desktop\20230707-223602.png");

        try {

            OkHttpClient client = new OkHttpClient().newBuilder().build();
            RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                    .addFormDataPart("img_url1",img_url1)
                    .addFormDataPart("img_url2",img_url2)
//                    .addFormDataPart("img_file1",img_file1.getName(),
//                            RequestBody.create(MediaType.parse("application/octet-stream"),
//                                    img_file1))
//                    .addFormDataPart("img_file2",img_file2.getName(),
//                            RequestBody.create(MediaType.parse("application/octet-stream"),
//                                    img_file2))
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .method("POST", body)
                    .addHeader("Content-Type", body.contentType().toString())
                    .addHeader("Accept", "application/json")
                    .build();

            String sign = sign(request);
            request = request.newBuilder().addHeader("Authorization", "acs " + accessKeyId + ":" + sign).build();

            Response response = client.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String sign(Request request) {
        Signer signer = new HmacSHA1Signer();
        RoaSignatureComposer composer = new RoaSignatureComposer();
        //提取headers的map
        Map<String, String> headers = new TreeMap<>();
        for (Pair<? extends String, ? extends String> header : request.headers()) {
            headers.put(header.getFirst(), header.getSecond());
        }
        String stringToSign = composer.composeStringToSign(MethodType.valueOf(request.method()), request.url().encodedPath(), signer,
                new HashMap<>(),headers, new HashMap<>());
        return signer.signString(stringToSign, accessKeySecret);
    }
}
//依赖库
//<dependency>
//    <groupId>com.aliyun</groupId>
//    <artifactId>aliyun-java-sdk-core</artifactId>
//    <version>4.5.20</version>
//</dependency>
//<dependency>
//    <groupId>com.squareup.okhttp3</groupId>
//    <artifactId>okhttp</artifactId>
//    <!-- MinIO requires a higher version -->
//    <version>4.8.1</version>
//</dependency>

import com.aliyuncs.auth.HmacSHA1Signer;
import com.aliyuncs.auth.RoaSignatureComposer;
import com.aliyuncs.auth.Signer;
import com.aliyuncs.http.MethodType;
import kotlin.Pair;
import okhttp3.*;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class JavaDemo {

    //请替换成您的AccessKeyId和AccessKeySecret
    static final String accessKeyId = "xxxxxxx";
    static final String accessKeySecret = "xxxxxxxxxxxxxxxxxxxx";

    public static void main(String[] args){

        String url = "https://mono-backend.sihe.cloud/api/ai_service/v1/face_verify";

        // 图片地址和文件二选一
        String img_url1 = "https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500";
        String img_url2 = "https://img2.baidu.com/it/u=2451098355,3223916536&fm=253&fmt=auto&app=138&f=JPEG?w=682&h=500";
        File img_file1 = new File("C:\Users\gousq\Desktop\20230707-223601.png");
        File img_file2 = new File("C:\Users\gousq\Desktop\20230707-223602.png");

        try {

            OkHttpClient client = new OkHttpClient().newBuilder().build();
            RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
                    .addFormDataPart("img_url1",img_url1)
                    .addFormDataPart("img_url2",img_url2)
//                    .addFormDataPart("img_file1",img_file1.getName(),
//                            RequestBody.create(MediaType.parse("application/octet-stream"),
//                                    img_file1))
//                    .addFormDataPart("img_file2",img_file2.getName(),
//                            RequestBody.create(MediaType.parse("application/octet-stream"),
//                                    img_file2))
                    .build();

            Request request = new Request.Builder()
                    .url(url)
                    .method("POST", body)
                    .addHeader("Content-Type", body.contentType().toString())
                    .addHeader("Accept", "application/json")
                    .build();

            String sign = sign(request);
            request = request.newBuilder().addHeader("Authorization", "acs " + accessKeyId + ":" + sign).build();

            Response response = client.newCall(request).execute();
            System.out.println(response.body().string());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static String sign(Request request) {
        Signer signer = new HmacSHA1Signer();
        RoaSignatureComposer composer = new RoaSignatureComposer();
        //提取headers的map
        Map<String, String> headers = new TreeMap<>();
        for (Pair<? extends String, ? extends String> header : request.headers()) {
            headers.put(header.getFirst(), header.getSecond());
        }
        String stringToSign = composer.composeStringToSign(MethodType.valueOf(request.method()), request.url().encodedPath(), signer,
                new HashMap<>(),headers, new HashMap<>());
        return signer.signString(stringToSign, accessKeySecret);
    }
}