feat: 新增42号人脸特征与72号B端关键点接口

This commit is contained in:
xsl
2026-11-07 20:35:55 +08:00
parent ccb9c142c4
commit c9a47a76c9
16 changed files with 983 additions and 25 deletions
+19
View File
@@ -66,6 +66,25 @@ class FaceLandmarker:
pass
def to_landmark_list(landmarks):
from mediapipe.framework.formats import landmark_pb2
result = landmark_pb2.NormalizedLandmarkList()
for x, y, z in landmarks:
result.landmark.add(x=float(x), y=float(y), z=float(z))
return result
_landmarker = None
def get_landmarker() -> FaceLandmarker:
global _landmarker
if _landmarker is None:
_landmarker = FaceLandmarker(static_image_mode=True)
return _landmarker
class SolutionsFaceLandmarker:
"""CPU-oriented fallback using mediapipe.solutions.face_mesh."""
+13
View File
@@ -216,3 +216,16 @@ def normalize_portrait(photo, landmarks, profile=None):
"reference_image_url": profile["reference_image_url"],
}
return image, moved, metadata
class NoPortraitFaceError(ValueError):
"""The portrait landmarker could not find a face."""
def prepare_portrait(photo):
"""Shared interface-52 preprocessing, including the same landmark model/profile."""
from .face_landmarks import get_landmarker
landmarks = get_landmarker().detect(cv2.cvtColor(photo, cv2.COLOR_BGR2RGB), include_iris=True)
if landmarks is None:
raise NoPortraitFaceError("未检出人脸")
return normalize_portrait(photo, landmarks)
+1 -9
View File
@@ -12,7 +12,7 @@ import numpy as np
from . import constants as C
from . import comfyui
from .face_landmarks import FaceLandmarker
from .face_landmarks import get_landmarker
from .face_parsing import FaceParser
from .hairline_2d import (
smooth_hairline, sample_hairline, align_hairline_for_template,
@@ -115,18 +115,10 @@ _TEXTURE_DIRS = {
# torch 2.7.1+cu128 已支持 RTX 5090 (sm_120),SegFormer 走 GPU(~0.05s/张)
_SEG_DEVICE = os.getenv("SEG_DEVICE", "cuda")
_landmarker = None
_parser = None
_texture_maps: dict = {} # {level: {gender: [(key, path)]}},按档位缓存
def get_landmarker() -> FaceLandmarker:
global _landmarker
if _landmarker is None:
_landmarker = FaceLandmarker(static_image_mode=True)
return _landmarker
def get_parser() -> FaceParser:
global _parser
if _parser is None: