1. 接口说明
证件照成品检测 API:对已经生成好的证件照图片进行智能检测,不做裁剪/换底/美颜等生成处理,只返回该张照片的尺寸、人脸位置与角度、遮挡情况、光照与曝光、背景颜色等检测结果,并给出普通/高级合规结论。
1.1 主要功能
- 面部识别:
- 检测是否存在人脸、人脸个数,并输出人脸在证件照中的宽度、高度及与边缘的距离、旋转角度等指标。
- 遮挡检测:
- 识别是否存在帽子、眼镜、墨镜、耳机/耳塞、耳饰、口罩等遮挡元素,并给出对应布尔与评分结果。
- 质量与光照评估:
- 检测脸部是否模糊、过曝/欠曝、阴阳脸、肤色异常、黑白照片、反光等质量问题。
- 姿势与视线:
- 返回人脸三维姿态(yaw/pitch/roll)、双眼连线角度、视线偏移情况,判断是否平视前方,姿势是否合规。
- 背景与服饰:
- 输出背景主色及其是否符合要求;检测衣服颜色、是否浅色、是否与背景颜色相近、是否光膀/背心/吊带、是否穿臃肿外套等。
- 普通/高级合规判断:
- 普通合规侧重尺寸与人脸位置;高级合规侧重姿势、遮挡、光照、饰品、妆容等,分别返回布尔结果与中文说明。
1.2 接入场景
适用于线上办证前置审核、线下采集终端自动质检、证件照App/小程序成片检测等场景。开发者可以在用户上传或拍照后,对成品证件照调用本接口,实时反馈是否合规以及不合规原因,从而减少人工审核成本与用户反复上传次数。
2. 请求信息
2.1 请求地址(URL)
POST https://api.shiliuai.com/api/id_photo/v1/qualify
2.2 请求方式
POST
2.3 请求头(header)
| 参数 | 类型 | 说明 |
|---|---|---|
| Content-Type | string | application/json |
| APIKEY | string | 您的 API KEY |
2.4 请求体(body)
| 参数 | 是否必填 | 类型 | 说明 |
|---|---|---|---|
| 图片 | |||
| base64 | 必须填写其中之一 | string | base64 编码的图片文件(小于 15M),需要传入 base64 或者 id |
| id | string | 图片 id,对于已经请求过的图片,如果需要重复检测或更改参数,使用 id 而无需再上传 base64 | |
| 规格 | |||
| specID | 否 | int | 规格 ID,对应证件照的尺寸、背景色、人脸尺寸以及高级合规检测标准,请参考 规格列表 |
| specVersion | 否 | int | 规格版本 |
| 人脸尺寸 | |||
| faceWidth | 否 | int | 人脸宽度(像素) |
| minFaceWidth | 否 | int | 最小人脸宽度(像素) |
| maxFaceWidth | 否 | int | 最大人脸宽度(像素) |
| faceHeight | 否 | int | 人脸长度(像素) |
| minFaceHeight | 否 | int | 最小人脸长度(像素) |
| maxFaceHeight | 否 | int | 最大人脸长度(像素) |
| headTop | 否 | int | 头顶与上边距离(像素) |
| minHeadTop | 否 | int | 头顶与上边最小距离(像素) |
| maxHeadTop | 否 | int | 头顶与上边最大距离(像素) |
| chinTop | 否 | int | 下巴与上边距离(像素) |
| minChinTop | 否 | int | 下巴与上边最小距离(像素) |
| maxChinTop | 否 | int | 下巴与上边最大距离(像素) |
| eyesTop | 否 | int | 眼睛与上边距离(像素) |
| minEyesTop | 否 | int | 眼睛与上边最小距离(像素) |
| maxEyesTop | 否 | int | 眼睛与上边最大距离(像素) |
| 合规检测 | |||
| qualify | 否 | int | 0 或 1,是否返回普通合规信息,默认为 1 |
| advancedQualify | 否 | int | 0 或 1,是否返回高级合规信息,默认为 1 |
3. 返回信息
3.1 返回类型
JSON
3.2 返回字段
| 参数 | 说明 |
|---|---|
| code | 错误码 |
| msg | 错误信息(英文) |
| msg_cn | 错误信息(中文) |
| id | 图片 id,用于同一张图片的多次请求,id 的有效时间为 6 小时(当 code==0 时会有该返回值) |
| info | 普通合规信息(当 code==0 且请求参数 qualify==1 时会有该返回值) |
| advanced_info | 高级合规信息(当 code==0 且请求参数 advancedQualify==1 时会有该返回值) |
| request_id | 请求 ID,请求的唯一码 |
3.3 返回示例
{
"code": 0,
"msg": "OK",
"msg_cn": "成功",
"id": "xxxxxx",
"info": {
"qualified": true,
"msg": "OK",
"msg_cn": "普通合规",
"width": 413,
"height": 626
},
"advanced_info": {
"qualified": true,
"msg": "OK",
"msg_cn": "高级合规"
},
"request_id": "req_xxxxxxxx"
}
3.4 错误码说明
| 错误码 | 说明 |
|---|---|
| 0 | 成功 |
| 1 | 图片错误 |
| 3 | 服务器繁忙 |
| 4 | 参数错误,具体错误看 msg 或 msg_cn |
| 6 | 未知错误 |
| 7 | 图片 id 无效,可能已过期 |
| 101 | API-KEY 不正确 |
| 102 | 未知用户 |
| 103 | 积分已用完 |
| 104 | 扣除积分失败 |
3.5 普通合规信息
| 分类 | 参数 | 类型 | 说明 |
|---|---|---|---|
| 综合 | |||
| qualified | bool | 是否合规(默认由face_width, face_height, head_top, eyes_top, eyes_angle决定);(specID存在由thresholds里的阈值决定) | |
| thresholds | dict | specID存在时:用来判断qualified的项目的阈值,有min/max_face_width, min/max_face_height等组成 | |
| msg | string | 合规消息(英文) | |
| msg_cn | string | 合规消息(中文) | |
| 尺寸 | |||
| width | int | 证件照宽度(像素) | |
| height | int | 证件照高度(像素) | |
| 人脸 | |||
| has_face | bool | 是否检测到人脸 | |
| face_count | int | 原图人脸数 | |
| rotation | int | 图片旋转角度(0度,90度,180度,或者270度) | |
| 判断 | |||
| face_width_qualified | bool | 人脸宽度是否合规 | |
| face_left_qualified | bool | 左侧脸颊到左侧边框距离是否合规 | |
| face_right_qualified | bool | 右侧脸颊到右侧边框距离是否合规 | |
| face_height_qualified | bool | 人脸长度是否合规 | |
| head_top_qualified | bool | 头顶至上边距离是否合规 | |
| chin_top_qualified | bool | 下巴至上边距离是否合规 | |
| eyes_top_qualified | bool | 眼睛至上边距离是否合规 | |
| eyes_angle_qualified | bool | 双眼连线角度是否合规 | |
| 距离与角度 | |||
| face_width | int | 生成证件照中人脸宽度(像素) | |
| face_left | int | 左侧脸颊到左侧边框距离(像素) | |
| face_right | int | 右侧脸颊到右侧边框距离(像素) | |
| face_height | int | 人脸长度(像素) | |
| head_top | int | 头顶至上边距离(像素) | |
| chin_top | int | 下巴至上边距离(像素) | |
| eyes_top | int | 眼睛至上边距离(像素) | |
| eyes_angle | float | [-pi/2, pi/2],双眼连线角度 | |
| pupil_distance | int | 瞳距(像素) | |
| eyes_center_from_left | int | 双眼中心与左边距离(像素) | |
| eyes_center_from_bottom | int | 双眼中心与下边距离(像素) |
3.6 高级合规信息
| 分类 | 参数 | 类型 | 说明 |
|---|---|---|---|
| 综合 | |||
| qualified | bool | 是否合规。(默认)如果无人脸,戴帽子,墨镜,耳机,手机,口罩,模糊,过曝或欠曝,眉毛遮挡,嘴巴张开,则不合规。 注意:其他项目不计入判断。(specID存在)由thresholds里的阈值决定 | |
| thresholds | dict | specID存在时返回:用来判断qualified的项目的阈值,由specID决定 | |
| msg | string | 合规消息(英文) | |
| msg_cn | string | 合规消息(中文) | |
| 人脸 | |||
| has_face | bool | 是否检测到人脸 | |
| face_count | int | 原图人脸个数 | |
| 姿势 | |||
| yaw | float | [-90, 90],人脸偏航角(左右转头角度),参与 pose_abnormal 判断 | |
| pitch | float | [-90, 90],人脸俯仰角(上下抬头角度),参与 pose_abnormal 判断 | |
| roll | float | [-90, 90],人脸翻滚角(歪头角度),参与 pose_abnormal 判断 | |
| pose_abnormal | bool | 人脸角度是否异常,默认:abs(yaw)>10 或 abs(pitch)>15 或 abs(roll)>10 时为 true | |
| 质量 | |||
| face_overexposed_score | float | [0,1],脸部过曝程度,默认阈值 0.5,决定 face_overexposed | |
| face_overexposed | bool | 是否脸部过曝 | |
| face_underexposed_score | float | [0,1],脸部欠曝程度,默认阈值 0.5,决定 face_underexposed | |
| face_underexposed | bool | 是否脸部欠曝 | |
| face_exposure_uneven_score | float | [0,1],阴阳脸程度,默认阈值 0.2,决定 face_exposure_uneven | |
| face_exposure_uneven | bool | 是否阴阳脸 | |
| face_blur_score | float | [0,1],脸部模糊程度,默认阈值 0.6,决定 face_blur | |
| face_blur | bool | 是否脸部模糊 | |
| face_dark_score | float | [0,1],脸部过暗程度,默认阈值 0.5,决定 face_dark | |
| face_dark | bool | 是否脸部过暗 | |
| face_color_abnormal_score | float | [0,1],肤色不正常程度,默认阈值 0.5,决定 face_color_abnormal | |
| face_color_abnormal | bool | 是否肤色不正常 | |
| image_gray_score | float | [0,1],黑白照片程度,默认阈值 0.5,决定 image_gray | |
| image_gray | bool | 是否黑白照片 | |
| face_glare_score | float | [0,1],脸部反光程度,默认阈值 0.5,决定 face_glare | |
| face_glare | bool | 是否脸部反光 | |
| 遮挡 | |||
| left_eye_occlusion_score | float | [0,1],左眼遮挡程度,默认阈值 0.2,决定 left_eye_occlusion | |
| left_eye_occlusion | bool | 是否左眼遮挡 | |
| right_eye_occlusion_score | float | [0,1],右眼遮挡程度,默认阈值 0.2,决定 right_eye_occlusion | |
| right_eye_occlusion | bool | 是否右眼遮挡 | |
| eye_occlusion | bool | 是否眼睛遮挡 | |
| mouth_occlusion_score | float | [0,1],嘴巴遮挡程度,默认阈值 0.2,决定 mouth_occlusion | |
| mouth_occlusion | bool | 是否嘴巴遮挡 | |
| nose_occlusion_score | float | [0,1],鼻子遮挡程度,默认阈值 0.2,决定 nose_occlusion | |
| nose_occlusion | bool | 是否鼻子遮挡 | |
| left_cheek_occlusion_score | float | [0,1],左脸遮挡程度,默认阈值 0.3,决定 left_cheek_occlusion | |
| left_cheek_occlusion | bool | 是否左脸遮挡 | |
| right_cheek_occlusion_score | float | [0,1],右脸遮挡程度,默认阈值 0.3,决定 right_cheek_occlusion | |
| right_cheek_occlusion | bool | 是否右脸遮挡 | |
| cheek_occlusion | bool | 是否脸颊遮挡(左脸或右脸遮挡时为 true) | |
| eyebrow_occlusion_score | float | [0,1],眉毛遮挡程度,默认阈值 0.3,决定 eyebrow_occlusion | |
| eyebrow_occlusion | bool | 是否眉毛遮挡 | |
| ear_occlusion_score | float | [0,1],耳朵遮挡程度,默认阈值 0.8,决定 ear_occlusion | |
| ear_occlusion | bool | 是否耳朵遮挡 | |
| 头发 | |||
| hair_incomplete_score | float | [0,1],头发不完整程度,默认阈值 0.1,决定 hair_incomplete | |
| hair_incomplete | bool | 是否头发不完整 | |
| hair_color_r | float | [0,255],头发颜色红色分量 | |
| hair_color_g | float | [0,255],头发颜色绿色分量 | |
| hair_color_b | float | [0,255],头发颜色蓝色分量 | |
| hair_dyed_score | float | [0,1],染发程度,默认阈值 0.5,决定 hair_dyed | |
| hair_dyed | bool | 是否染发 | |
| 眼睛 | |||
| eye_close_score | float | [0,1],闭眼程度,默认阈值 0.5,决定 eye_close | |
| eye_close | bool | 是否闭眼 | |
| gaze_horizontal_score | float | [0,1],视线水平偏移程度,默认阈值 0.15,决定 gaze_horizontal | |
| gaze_horizontal | bool | 是否视线水平偏移 | |
| gaze_vertical_score | float | [0,1],视线竖直偏移程度,默认阈值 0.1,决定 gaze_vertical | |
| gaze_vertical | bool | 是否视线竖直偏移 | |
| gaze_abnormal | bool | 视线是否未平视前方(视线水平或竖直偏移为真时为 true) | |
| red_eye_score | float | [0,1],红眼程度,默认阈值 0.5,决定 red_eye | |
| red_eye | bool | 是否红眼 | |
| colored_contacts_score | float | [0,1],有色隐形眼镜分数,默认阈值 0.5,决定 colored_contacts | |
| colored_contacts | bool | 是否佩戴有色隐形眼镜 | |
| 耳朵 | |||
| ears_asymmetric_score | float | [0,1],双耳不对称程度,默认阈值 0.5,决定 ears_asymmetric | |
| ears_asymmetric | bool | 是否双耳不对称 | |
| 嘴巴 | |||
| mouth_open_score | float | [0,1],嘴巴张开程度,默认阈值 0.1,决定 mouth_open | |
| mouth_open | bool | 是否嘴巴张开 | |
| 饰品 | |||
| hat | int | 0 或 1,是否戴帽子 | |
| glasses | int | 0 或 1,是否戴眼镜 | |
| sunglasses | int | 0 或 1,是否戴墨镜 | |
| headphone | int | 0 或 1,是否戴头戴式耳机 | |
| earphone | int | 0 或 1,是否戴耳塞 | |
| cellphone | int | 0 或 1,是否使用手机 | |
| earring | int | 0 或 1,是否戴耳饰 | |
| mask | int | 0 或 1,是否戴口罩 | |
| necklace | int | 0 或 1,是否戴项链 | |
| glasses_glare_score | float | [0,1],眼镜反光程度,默认阈值 0.5,决定 glasses_glare | |
| glasses_glare | bool | 是否眼镜反光 | |
| heavy_makeup_score | float | [0,1],浓妆程度,默认阈值 0.5,决定 heavy_makeup | |
| heavy_makeup | bool | 是否浓妆 | |
| 肩膀 | |||
| shoulder_incomplete_score | float | [0,1],肩膀不完整程度,默认阈值 0.5,决定 shoulder_incomplete | |
| shoulder_incomplete | bool | 是否肩膀不完整 | |
| shoulder_imbalance_score | float | [0,1],肩膀不平衡程度,默认阈值 0.5,决定 shoulder_imbalance | |
| shoulder_imbalance | bool | 是否肩膀不平衡 | |
| 衣服 | |||
| clothes_color_r | float | [0,255],衣服颜色红色分量 | |
| clothes_color_g | float | [0,255],衣服颜色绿色分量 | |
| clothes_color_b | float | [0,255],衣服颜色蓝色分量 | |
| clothes_color_light_score | float | [0,1],衣服浅色程度,默认阈值 0.75,决定 clothes_color_light | |
| clothes_color_light | bool | 是否浅色衣服 | |
| clothes_bg_similar_score | float | [0,1],衣服与背景颜色相近程度,默认阈值 0.8,决定 clothes_bg_similar | |
| clothes_bg_similar | bool | 是否衣服背景颜色相近 | |
| shirtless_score | float | [0,1],光膀程度,默认阈值 0.5,决定 shirtless | |
| shirtless | bool | 是否光膀 | |
| sleeveless_score | float | [0,1],背心或吊带分数,默认阈值 0.5,决定 sleeveless | |
| sleeveless | bool | 是否穿背心或吊带 | |
| big_clothes_score | float | [0,1],臃肿外套分数,默认阈值 0.5,决定 big_clothes | |
| big_clothes | bool | 是否穿臃肿外套 | |
| 背景 | |||
| bg_color_r | float | [0,255],背景颜色红色分量 | |
| bg_color_g | float | [0,255],背景颜色绿色分量 | |
| bg_color_b | float | [0,255],背景颜色蓝色分量 | |
| bg_color_wrong_score | float | [0,1],背景颜色错误程度,默认阈值 0.5,决定 bg_color_wrong | |
| bg_color_wrong | bool | 是否背景颜色错误 | |
| 图片 | |||
| image_gray_score | float | [0,1],黑白照片程度,默认阈值 0.5,决定 image_gray | |
| image_gray | bool | 是否黑白照片 |
4. 示例代码
4.1 Python
# -*- coding: utf-8 -*-
import requests
import base64
import json
api_key = '******' # 你的API KEY
file_path = '...' # 图片路径
with open(file_path, 'rb') as fp:
photo_base64 = base64.b64encode(fp.read()).decode('utf8')
url = 'https://api.shiliuai.com/api/id_photo/v1/qualify'
headers = {'APIKEY': api_key, "Content-type": "application/json"}
data = {
"base64": photo_base64,
"qualify": 1,
"advancedQualify": 1
}
response = requests.post(url=url, headers=headers, json=data)
response = json.loads(response.content)
"""
成功:{'code': 0, 'msg': 'OK', 'msg_cn': '成功', 'id': id, 'info': info, 'advanced_info': advanced_info}
or
失败:{'code': error_code, 'msg': error_msg, 'msg_cn': 错误信息}
"""
4.2 PHP
<?php $url = "https://api.shiliuai.com/api/id_photo/v1/qualify"; $method = "POST"; $apikey = "******"; $header = array(); array_push($header, "APIKEY:" . $apikey); array_push($header, "Content-Type:application/json"); $file_path = "..."; $handle = fopen($file_path, "r"); $photo = fread($handle, filesize($file_path)); fclose($handle); $photo_base64 = base64_encode($photo); $data = array( "base64"=> $photo_base64, "qualify"=> 1, "advancedQualify"=> 1 ); $post_data = json_encode($data); $curl = curl_init(); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); $response = curl_exec($curl); var_dump($response);
4.3 Java
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.Base64;
import org.json.JSONObject;
public class IDPhotoQualifyAPIExample {
public static void main(String[] args) {
String apiKey = "******"; // 你的API KEY
String filePath = "path/to/your/image.jpg"; // 图片路径
try {
// 读取图片并编码为 Base64
byte[] fileBytes = Files.readAllBytes(new File(filePath).toPath());
String photoBase64 = Base64.getEncoder().encodeToString(fileBytes);
// API 请求的 URL
String apiUrl = "https://api.shiliuai.com/api/id_photo/v1/qualify";
// 请求参数
JSONObject requestData = new JSONObject();
requestData.put("base64", photoBase64);
requestData.put("qualify", 1);
requestData.put("advancedQualify", 1);
// 发送 POST 请求
JSONObject response = sendPostRequest(apiUrl, apiKey, requestData);
// 检查响应是否成功
if (response.getInt("code") == 0) {
System.out.println("检测成功");
System.out.println("普通合规信息: " + response.getJSONObject("info").toString());
System.out.println("高级合规信息: " + response.getJSONObject("advanced_info").toString());
} else {
System.out.println("请求失败: " + response.getString("msg_cn"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
// 发送 POST 请求
private static JSONObject sendPostRequest(String urlStr, String apiKey, JSONObject jsonData) throws IOException {
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("APIKEY", apiKey);
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
// 写入请求数据
try (OutputStream os = conn.getOutputStream()) {
byte[] input = jsonData.toString().getBytes("utf-8");
os.write(input, 0, input.length);
}
// 读取响应
StringBuilder response = new StringBuilder();
try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))) {
String responseLine;
while ((responseLine = br.readLine()) != null) {
response.append(responseLine.trim());
}
}
return new JSONObject(response.toString());
}
}
4.4 JavaScript
const fs = require('fs');
const fetch = require('node-fetch'); // 需安装:npm install node-fetch
const apiKey = '******'; // 你的API KEY
const filePath = 'path/to/your/image.jpg'; // 图片路径
(async () => {
try {
// 读取图片并编码为 Base64
const fileBuffer = fs.readFileSync(filePath);
const photoBase64 = fileBuffer.toString('base64');
// API 请求的 URL
const apiUrl = 'https://api.shiliuai.com/api/id_photo/v1/qualify';
// 请求参数
const requestData = {
base64: photoBase64,
qualify: 1,
advancedQualify: 1
};
// 发送 POST 请求
let response = await fetch(apiUrl, {
method: 'POST',
headers: {
'APIKEY': apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
});
const responseData = await response.json();
// 检查响应是否成功
if (responseData.code === 0) {
console.log('检测成功');
console.log('普通合规信息:', responseData.info);
console.log('高级合规信息:', responseData.advanced_info);
} else {
console.error('请求失败:', responseData.msg_cn);
}
} catch (error) {
console.error('发生错误:', error);
}
})();