357 lines
8.2 KiB
Markdown
357 lines
8.2 KiB
Markdown
|
|
# 人脸特征提取API使用文档
|
|||
|
|
|
|||
|
|
## 快速开始
|
|||
|
|
|
|||
|
|
### 1. 安装依赖
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install -r requirements.txt
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 启动服务
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 基础启动
|
|||
|
|
python app.py
|
|||
|
|
|
|||
|
|
# 指定端口和地址
|
|||
|
|
python app.py --host 0.0.0.0 --port 8000
|
|||
|
|
|
|||
|
|
# 开发模式(支持热重载)
|
|||
|
|
python app.py --reload
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
服务启动后访问:
|
|||
|
|
- API服务: http://localhost:8000
|
|||
|
|
- 交互式文档: http://localhost:8000/docs
|
|||
|
|
- 健康检查: http://localhost:8000/health
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## API接口说明
|
|||
|
|
|
|||
|
|
### 接口1: 人脸特征提取
|
|||
|
|
|
|||
|
|
**接口地址**: `POST /api/extract_feature`
|
|||
|
|
|
|||
|
|
**功能**: 上传一张人脸图像,提取并返回1024维特征向量
|
|||
|
|
|
|||
|
|
**请求参数**:
|
|||
|
|
- `image` (File): 人脸图像文件 (支持 jpg, png, jpeg 格式)
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"message": "特征提取成功",
|
|||
|
|
"feature": [0.123, -0.456, 0.789, ...], // 1024维特征向量
|
|||
|
|
"feature_dim": 1024,
|
|||
|
|
"quality_passed": true,
|
|||
|
|
"processing_time": 0.235
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Python调用示例**:
|
|||
|
|
```python
|
|||
|
|
import requests
|
|||
|
|
|
|||
|
|
url = "http://localhost:8000/api/extract_feature"
|
|||
|
|
|
|||
|
|
with open("face.jpg", "rb") as f:
|
|||
|
|
files = {"image": f}
|
|||
|
|
response = requests.post(url, files=files)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
feature = result["feature"] # 获取特征向量
|
|||
|
|
print(f"特征维度: {result['feature_dim']}")
|
|||
|
|
else:
|
|||
|
|
print(f"失败: {result['message']}")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**cURL示例**:
|
|||
|
|
```bash
|
|||
|
|
curl -X POST "http://localhost:8000/api/extract_feature" \
|
|||
|
|
-F "image=@face.jpg"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 接口2: 两个特征值对比
|
|||
|
|
|
|||
|
|
**接口地址**: `POST /api/compare_features`
|
|||
|
|
|
|||
|
|
**功能**: 输入两个特征向量,计算相似度并判断是否为同一人
|
|||
|
|
|
|||
|
|
**请求体** (JSON):
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"feature1": [0.123, -0.456, ...], // 1024维特征向量
|
|||
|
|
"feature2": [0.789, 0.234, ...] // 1024维特征向量
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"message": "对比成功",
|
|||
|
|
"similarity": 0.8523,
|
|||
|
|
"is_same_person": true,
|
|||
|
|
"threshold": 0.7
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Python调用示例**:
|
|||
|
|
```python
|
|||
|
|
import requests
|
|||
|
|
import json
|
|||
|
|
|
|||
|
|
url = "http://localhost:8000/api/compare_features"
|
|||
|
|
|
|||
|
|
data = {
|
|||
|
|
"feature1": feature_vector_1, # 从接口1获取的特征
|
|||
|
|
"feature2": feature_vector_2 # 从接口1获取的特征
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
response = requests.post(url, json=data)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
print(f"相似度: {result['similarity']:.4f}")
|
|||
|
|
print(f"是否同一人: {result['is_same_person']}")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**cURL示例**:
|
|||
|
|
```bash
|
|||
|
|
curl -X POST "http://localhost:8000/api/compare_features" \
|
|||
|
|
-H "Content-Type: application/json" \
|
|||
|
|
-d '{
|
|||
|
|
"feature1": [0.1, 0.2, ...],
|
|||
|
|
"feature2": [0.3, 0.4, ...]
|
|||
|
|
}'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 接口3: 人脸图像和特征值对比 (组合接口)
|
|||
|
|
|
|||
|
|
**接口地址**: `POST /api/compare_image_feature`
|
|||
|
|
|
|||
|
|
**功能**: 上传一张图像和一个特征向量,自动提取图像特征后进行对比
|
|||
|
|
|
|||
|
|
**请求参数**:
|
|||
|
|
- `image` (File): 人脸图像文件
|
|||
|
|
- `feature` (Form): 特征向量的JSON字符串
|
|||
|
|
|
|||
|
|
**响应示例**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": true,
|
|||
|
|
"message": "对比成功",
|
|||
|
|
"similarity": 0.8234,
|
|||
|
|
"is_same_person": true,
|
|||
|
|
"threshold": 0.7,
|
|||
|
|
"processing_time": 0.245
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Python调用示例**:
|
|||
|
|
```python
|
|||
|
|
import requests
|
|||
|
|
import json
|
|||
|
|
|
|||
|
|
url = "http://localhost:8000/api/compare_image_feature"
|
|||
|
|
|
|||
|
|
# 已有的特征向量
|
|||
|
|
known_feature = [0.123, -0.456, ...] # 1024维
|
|||
|
|
|
|||
|
|
with open("test_face.jpg", "rb") as f:
|
|||
|
|
files = {"image": f}
|
|||
|
|
data = {"feature": json.dumps(known_feature)}
|
|||
|
|
response = requests.post(url, files=files, data=data)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
print(f"相似度: {result['similarity']:.4f}")
|
|||
|
|
print(f"是否同一人: {result['is_same_person']}")
|
|||
|
|
else:
|
|||
|
|
print(f"失败: {result['message']}")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**cURL示例**:
|
|||
|
|
```bash
|
|||
|
|
curl -X POST "http://localhost:8000/api/compare_image_feature" \
|
|||
|
|
-F "image=@face.jpg" \
|
|||
|
|
-F 'feature=[0.1, 0.2, 0.3, ...]'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 完整工作流程示例
|
|||
|
|
|
|||
|
|
### 场景: 人脸识别系统
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
import requests
|
|||
|
|
import json
|
|||
|
|
|
|||
|
|
API_BASE = "http://localhost:8000"
|
|||
|
|
|
|||
|
|
# 步骤1: 注册用户 - 提取并存储特征
|
|||
|
|
def register_user(user_id, image_path):
|
|||
|
|
"""注册用户人脸"""
|
|||
|
|
url = f"{API_BASE}/api/extract_feature"
|
|||
|
|
|
|||
|
|
with open(image_path, "rb") as f:
|
|||
|
|
files = {"image": f}
|
|||
|
|
response = requests.post(url, files=files)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
# 将特征向量存储到数据库
|
|||
|
|
feature = result["feature"]
|
|||
|
|
save_to_database(user_id, feature)
|
|||
|
|
print(f"✓ 用户 {user_id} 注册成功")
|
|||
|
|
return feature
|
|||
|
|
else:
|
|||
|
|
print(f"✗ 注册失败: {result['message']}")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
# 步骤2: 验证用户 - 使用组合接口
|
|||
|
|
def verify_user(user_id, image_path):
|
|||
|
|
"""验证用户身份"""
|
|||
|
|
# 从数据库获取已存储的特征
|
|||
|
|
stored_feature = get_from_database(user_id)
|
|||
|
|
|
|||
|
|
if not stored_feature:
|
|||
|
|
print(f"✗ 用户 {user_id} 不存在")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
# 使用组合接口进行对比
|
|||
|
|
url = f"{API_BASE}/api/compare_image_feature"
|
|||
|
|
|
|||
|
|
with open(image_path, "rb") as f:
|
|||
|
|
files = {"image": f}
|
|||
|
|
data = {"feature": json.dumps(stored_feature)}
|
|||
|
|
response = requests.post(url, files=files, data=data)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
is_verified = result["is_same_person"]
|
|||
|
|
similarity = result["similarity"]
|
|||
|
|
print(f"{'✓' if is_verified else '✗'} 验证结果: {similarity:.4f}")
|
|||
|
|
return is_verified
|
|||
|
|
else:
|
|||
|
|
print(f"✗ 验证失败: {result['message']}")
|
|||
|
|
return False
|
|||
|
|
|
|||
|
|
# 步骤3: 1对N识别 - 在数据库中搜索最相似的人脸
|
|||
|
|
def identify_user(image_path):
|
|||
|
|
"""识别用户(1:N匹配)"""
|
|||
|
|
# 先提取待识别图像的特征
|
|||
|
|
url = f"{API_BASE}/api/extract_feature"
|
|||
|
|
|
|||
|
|
with open(image_path, "rb") as f:
|
|||
|
|
files = {"image": f}
|
|||
|
|
response = requests.post(url, files=files)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if not result["success"]:
|
|||
|
|
print(f"✗ 特征提取失败: {result['message']}")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
query_feature = result["feature"]
|
|||
|
|
|
|||
|
|
# 与数据库中所有用户特征进行对比
|
|||
|
|
all_users = get_all_users_from_database()
|
|||
|
|
|
|||
|
|
best_match = None
|
|||
|
|
best_similarity = 0.0
|
|||
|
|
|
|||
|
|
for user_id, stored_feature in all_users.items():
|
|||
|
|
# 使用接口2对比特征
|
|||
|
|
url = f"{API_BASE}/api/compare_features"
|
|||
|
|
data = {
|
|||
|
|
"feature1": query_feature,
|
|||
|
|
"feature2": stored_feature
|
|||
|
|
}
|
|||
|
|
response = requests.post(url, json=data)
|
|||
|
|
result = response.json()
|
|||
|
|
|
|||
|
|
if result["success"]:
|
|||
|
|
similarity = result["similarity"]
|
|||
|
|
if similarity > best_similarity:
|
|||
|
|
best_similarity = similarity
|
|||
|
|
best_match = user_id
|
|||
|
|
|
|||
|
|
# 判断是否超过阈值
|
|||
|
|
if best_similarity >= 0.7:
|
|||
|
|
print(f"✓ 识别为: {best_match} (相似度: {best_similarity:.4f})")
|
|||
|
|
return best_match
|
|||
|
|
else:
|
|||
|
|
print(f"✗ 未识别到已注册用户 (最高相似度: {best_similarity:.4f})")
|
|||
|
|
return None
|
|||
|
|
|
|||
|
|
# 使用示例
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
# 注册用户
|
|||
|
|
register_user("user001", "photos/user001.jpg")
|
|||
|
|
register_user("user002", "photos/user002.jpg")
|
|||
|
|
|
|||
|
|
# 验证用户
|
|||
|
|
verify_user("user001", "photos/user001_verify.jpg")
|
|||
|
|
|
|||
|
|
# 识别用户
|
|||
|
|
identify_user("photos/unknown.jpg")
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 错误处理
|
|||
|
|
|
|||
|
|
### 常见错误码
|
|||
|
|
|
|||
|
|
- `400`: 请求参数错误 (图像无法解析、特征维度不匹配等)
|
|||
|
|
- `500`: 服务器内部错误 (模型加载失败、处理异常等)
|
|||
|
|
- `503`: 服务不可用 (健康检查失败)
|
|||
|
|
|
|||
|
|
### 错误响应示例
|
|||
|
|
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"success": false,
|
|||
|
|
"message": "未检测到合格的人脸",
|
|||
|
|
"processing_time": 0.123
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 性能优化建议
|
|||
|
|
|
|||
|
|
1. **批量处理**: 对于大量图像,建议使用异步并发请求
|
|||
|
|
2. **特征缓存**: 已提取的特征应缓存到数据库,避免重复计算
|
|||
|
|
3. **负载均衡**: 高并发场景下可部署多个实例
|
|||
|
|
4. **GPU加速**: 如有GPU,可安装 `onnxruntime-gpu` 加速推理
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 相似度阈值说明
|
|||
|
|
|
|||
|
|
默认阈值: **0.7**
|
|||
|
|
|
|||
|
|
- `>= 0.7`: 认为是同一人
|
|||
|
|
- `< 0.7`: 认为不是同一人
|
|||
|
|
|
|||
|
|
可根据实际业务需求调整阈值:
|
|||
|
|
- **安全要求高**: 提高阈值 (0.75 - 0.85)
|
|||
|
|
- **用户体验优先**: 降低阈值 (0.6 - 0.65)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 技术支持
|
|||
|
|
|
|||
|
|
- 查看交互式API文档: http://localhost:8000/docs
|
|||
|
|
- 查看示例代码: `examples/api_client_example.py`
|