feat: 新增42号人脸特征与72号B端关键点接口
This commit is contained in:
@@ -1585,6 +1585,49 @@ async def face_features(
|
||||
return ok({"features": features})
|
||||
|
||||
|
||||
@app.post(
|
||||
"/api/v1/face/b-end-points",
|
||||
summary="72号接口:B 端五个关键点",
|
||||
tags=["人脸分析"],
|
||||
)
|
||||
async def face_b_end_points(
|
||||
image_file: Optional[UploadFile] = File(default=None, description="上传图片文件(JPG/PNG)"),
|
||||
image_url: Optional[str] = Form(default=None, description="图片 URL"),
|
||||
image_base64: Optional[str] = Form(default=None, description="图片 base64"),
|
||||
):
|
||||
"""返回扶正裁切后的底图、六个白点标注层、坐标及距离。"""
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
|
||||
from face_analysis.b_end_points import build_b_end_annotation
|
||||
from face_analysis.special_points import NoFaceError, NonFrontalError
|
||||
from hairline.framing import NoPortraitFaceError, decode_portrait
|
||||
|
||||
raw, error = await resolve_image_bytes(image_file, image_url, image_base64)
|
||||
if error is not None:
|
||||
return error
|
||||
image = decode_portrait(raw)
|
||||
if image is None:
|
||||
return err(1008, "图片格式不支持(仅 JPG / PNG)")
|
||||
|
||||
try:
|
||||
processed, overlay, data = await run_in_threadpool(build_b_end_annotation, image)
|
||||
except (NoFaceError, NoPortraitFaceError):
|
||||
return err(1001, "无法识别人像")
|
||||
except NonFrontalError:
|
||||
return err(1003, "角度问题,请上传正面照")
|
||||
except ValueError as exc:
|
||||
return err(1003, str(exc))
|
||||
except Exception:
|
||||
logger.exception("接口72 标注生成失败")
|
||||
return err(1007, "标注生成失败")
|
||||
|
||||
data.update(
|
||||
input_image_base64=_jpg_b64(processed),
|
||||
annotated_image_base64=_rgba_png_b64(overlay),
|
||||
)
|
||||
return ok(data)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 接口 5:发际线 PNG 生成(恢复 a3fddbb 历史版本)
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -1765,21 +1808,19 @@ async def _generate_hairline52_data(image, gender, hair_styles, use_mask=True,
|
||||
compare_rules=False, normalize_image=True):
|
||||
"""Share measurement coordinates between interface 52 and its comparison page."""
|
||||
from fastapi.concurrency import run_in_threadpool
|
||||
from hairline.service import generate_hairline_pngs_52, get_landmarker
|
||||
from hairline.service import generate_hairline_pngs_52
|
||||
|
||||
original = image
|
||||
framing, normalized_landmarks, landmarks_override = None, None, None
|
||||
if normalize_image:
|
||||
from hairline.framing import normalize_portrait
|
||||
from mediapipe.framework.formats import landmark_pb2
|
||||
landmarks = await run_in_threadpool(
|
||||
get_landmarker().detect, cv2.cvtColor(image, cv2.COLOR_BGR2RGB), include_iris=True)
|
||||
if landmarks is None:
|
||||
from hairline.face_landmarks import to_landmark_list
|
||||
from hairline.framing import NoPortraitFaceError, prepare_portrait
|
||||
|
||||
try:
|
||||
image, normalized_landmarks, framing = await run_in_threadpool(prepare_portrait, image)
|
||||
except NoPortraitFaceError:
|
||||
return None, None
|
||||
image, normalized_landmarks, framing = await run_in_threadpool(normalize_portrait, image, landmarks)
|
||||
landmarks_override = landmark_pb2.NormalizedLandmarkList()
|
||||
for point in normalized_landmarks:
|
||||
landmarks_override.landmark.add(x=float(point[0]), y=float(point[1]), z=float(point[2]))
|
||||
landmarks_override = to_landmark_list(normalized_landmarks)
|
||||
fm, reference = None, None
|
||||
try:
|
||||
measured = await run_in_threadpool(_run_face_measure_data, image, landmarks_override=landmarks_override)
|
||||
|
||||
Reference in New Issue
Block a user