人脸分析 API
分析图片中的人脸信息,包括人脸数量、位置、角度等
POST
/
portrait
/
analysis
/
face-analysis
Face Analysis
curl --request POST \
--url https://api.aihairstyle.cn/portrait/analysis/face-analysis \
--header 'Content-Type: multipart/form-data' \
--header 'ailabapi-api-key: <api-key>' \
--form task_type=async \
--form image='@example-file'import requests
url = "https://api.aihairstyle.cn/portrait/analysis/face-analysis"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = { "task_type": "async" }
headers = {"ailabapi-api-key": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('task_type', 'async');
form.append('image', '<string>');
const options = {method: 'POST', headers: {'ailabapi-api-key': '<api-key>'}};
options.body = form;
fetch('https://api.aihairstyle.cn/portrait/analysis/face-analysis', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.aihairstyle.cn/portrait/analysis/face-analysis",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"ailabapi-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.aihairstyle.cn/portrait/analysis/face-analysis"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("ailabapi-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.aihairstyle.cn/portrait/analysis/face-analysis")
.header("ailabapi-api-key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aihairstyle.cn/portrait/analysis/face-analysis")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["ailabapi-api-key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
},
"result": {
"face_num": 123,
"face_info": [
{
"face_rect": {
"left": 123,
"top": 123,
"width": 123,
"height": 123
},
"face_angle": {
"yaw": 123,
"pitch": 123,
"roll": 123
},
"face_proportion": 123
}
]
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}请求
- URL: /portrait/analysis/face-analysis
- 方法:
POST
人脸分析 API
分析图片中的人脸信息,包括人脸数量、位置、角度等,用于前端验证和图片质量检查。功能特点
- 人脸检测:准确检测图片中的人脸数量
- 位置分析:获取人脸在图片中的精确位置
- 角度分析:分析人脸的偏航角、俯仰角、翻滚角
- 比例计算:计算人脸在图片中的占比
- 质量评估:评估图片是否适合发型编辑
应用场景
- 前端验证:在用户上传图片前进行质量检查
- 图片预处理:根据人脸位置进行智能裁剪
- 质量筛选:过滤不符合要求的图片
- 用户体验:提供即时的图片质量反馈
图片要求
为了获得准确的检测结果,请确保上传的图片符合以下要求:
- 图片中必须包含清晰的人脸
- 人脸不应被严重遮挡或模糊
- 光线充足,避免过暗或过亮
- 图片分辨率建议不低于 200x200 像素
支持的图片格式
- 格式:PNG、JPG、JPEG
- 大小:不超过 3MB
- 分辨率:200x200px ~ 1999x1999px
异步处理流程
对于异步任务,完整的处理流程如下:- 提交任务:调用 API 提交处理任务
- 获取 task_id:API 返回 task_id
- 查询结果:使用 task_id 查询处理结果
- 获取最终结果:当任务完成时获取最终结果
响应示例(异步任务查询API获取)
成功响应
{
"request_id": "123456789",
"log_id": "987654321",
"error_code": 0,
"error_msg": "",
"error_detail": {
"status_code": 200,
"code": "",
"code_message": "",
"message": ""
},
"result": {
"face_num": 1,
"face_info": [
{
"face_rect": {
"left": 100,
"top": 50,
"width": 200,
"height": 250
},
"face_angle": {
"yaw": 5.2,
"pitch": -2.1,
"roll": 1.8
},
"face_proportion": 0.35
}
]
}
}
错误响应
{
"request_id": "123456789",
"log_id": "987654321",
"error_code": 422,
"error_msg": "No face detected in the file",
"error_detail": {
"status_code": 422,
"code": "ERROR_NO_FACE_IN_FILE",
"code_message": "No face detected in the file",
"message": "pic not has face"
}
}
响应字段说明
主要字段
| 字段 | 类型 | 说明 |
|---|---|---|
face_num | integer | 检测到的人脸数量 |
face_info | array | 人脸信息数组 |
人脸信息字段
| 字段 | 类型 | 说明 |
|---|---|---|
face_rect | object | 人脸矩形区域 |
face_angle | object | 人脸角度信息 |
face_proportion | number | 人脸占比 |
矩形区域字段
| 字段 | 类型 | 说明 |
|---|---|---|
left | integer | 左边界坐标 |
top | integer | 上边界坐标 |
width | integer | 宽度 |
height | integer | 高度 |
角度字段
| 字段 | 类型 | 说明 | 有效范围 |
|---|---|---|---|
yaw | number | 偏航角(左右转动) | ±45° |
pitch | number | 俯仰角(上下点头) | ±30° |
roll | number | 翻滚角(左右倾斜) | ±30° |
验证标准
人脸数量验证
// 检查人脸数量
if (result.result.face_num === 0) {
throw new Error('未检测到人脸');
} else if (result.result.face_num > 1) {
throw new Error('检测到多个人脸,请使用单人照片');
}
人脸占比验证
// 检查人脸占比
const faceInfo = result.result.face_info[0];
const faceProportion = faceInfo.face_proportion;
if (faceProportion < 0.2) {
throw new Error('人脸占比过小,请使用更近的照片');
} else if (faceProportion > 0.8) {
throw new Error('人脸占比过大,请使用更远的照片');
}
人脸角度验证
// 检查人脸角度
const { yaw, pitch, roll } = faceInfo.face_angle;
if (Math.abs(yaw) > 45 || Math.abs(pitch) > 30 || Math.abs(roll) > 30) {
throw new Error('人脸角度过大,请使用正面照片');
}
最佳实践
1. 前端验证流程
async function validateImage(imageFile) {
// 1. 调用人脸分析 API
const analysisResult = await analyzeFace(imageFile);
// 2. 检查人脸数量
if (analysisResult.face_num !== 1) {
throw new Error('请使用包含且仅包含一个人脸的照片');
}
// 3. 检查人脸占比
const faceInfo = analysisResult.face_info[0];
if (faceInfo.face_proportion < 0.2 || faceInfo.face_proportion > 0.8) {
throw new Error('人脸占比应在20%-80%之间');
}
// 4. 检查人脸角度
const { yaw, pitch, roll } = faceInfo.face_angle;
if (Math.abs(yaw) > 45 || Math.abs(pitch) > 30 || Math.abs(roll) > 30) {
throw new Error('请使用正面照片,人脸角度不应过大');
}
return true;
}
相关链接
Authorizations
API Key for authentication
Body
multipart/form-data
Was this page helpful?
⌘I
Face Analysis
curl --request POST \
--url https://api.aihairstyle.cn/portrait/analysis/face-analysis \
--header 'Content-Type: multipart/form-data' \
--header 'ailabapi-api-key: <api-key>' \
--form task_type=async \
--form image='@example-file'import requests
url = "https://api.aihairstyle.cn/portrait/analysis/face-analysis"
files = { "image": ("example-file", open("example-file", "rb")) }
payload = { "task_type": "async" }
headers = {"ailabapi-api-key": "<api-key>"}
response = requests.post(url, data=payload, files=files, headers=headers)
print(response.text)const form = new FormData();
form.append('task_type', 'async');
form.append('image', '<string>');
const options = {method: 'POST', headers: {'ailabapi-api-key': '<api-key>'}};
options.body = form;
fetch('https://api.aihairstyle.cn/portrait/analysis/face-analysis', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.aihairstyle.cn/portrait/analysis/face-analysis",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--",
CURLOPT_HTTPHEADER => [
"Content-Type: multipart/form-data",
"ailabapi-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.aihairstyle.cn/portrait/analysis/face-analysis"
payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("ailabapi-api-key", "<api-key>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.aihairstyle.cn/portrait/analysis/face-analysis")
.header("ailabapi-api-key", "<api-key>")
.body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.aihairstyle.cn/portrait/analysis/face-analysis")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["ailabapi-api-key"] = '<api-key>'
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"task_type\"\r\n\r\nasync\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"image\"; filename=\"example-file\"\r\nContent-Type: application/octet-stream\r\n\r\n<string>\r\n-----011000010111000001101001--"
response = http.request(request)
puts response.read_body{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
},
"result": {
"face_num": 123,
"face_info": [
{
"face_rect": {
"left": 123,
"top": 123,
"width": 123,
"height": 123
},
"face_angle": {
"yaw": 123,
"pitch": 123,
"roll": 123
},
"face_proportion": 123
}
]
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}{
"request_id": "<string>",
"log_id": "<string>",
"error_code": 123,
"error_msg": "<string>",
"error_detail": {
"status_code": 123,
"code": "<string>",
"code_message": "<string>",
"message": "<string>"
}
}