fix(发际线): 修正不对称刘海导致的模板叠加倾斜
按 MediaPipe 左右对应额头点协调模板延伸距离,保留人脸姿态与头部轮廓钳制,统一预览白线和生发遮罩的几何。补充对齐回归测试并更新贴图顺序测试及实现说明。 验证:13 项相关测试通过;两张用户图片完成前后对比,新图男性 7 型接口与生发图均成功返回。
This commit is contained in:
@@ -124,6 +124,46 @@ def build_hairline_mask(parse_map: np.ndarray) -> np.ndarray:
|
||||
return build_hair_mask(parse_map)
|
||||
|
||||
|
||||
def align_hairline_for_template(
|
||||
landmarks_norm: np.ndarray,
|
||||
hairline_norm: np.ndarray,
|
||||
valid: np.ndarray,
|
||||
image_shape: tuple[int, int],
|
||||
) -> np.ndarray:
|
||||
"""Keep a designed template aligned with the face rather than the fringe.
|
||||
|
||||
Uneven bangs can make the detected hair boundary much higher on one
|
||||
side, shearing an otherwise balanced template. Average the upward
|
||||
extension of each anatomical anchor pair, measured in image pixels.
|
||||
Keep the face anchors and the perpendicular component unchanged so
|
||||
facial roll/perspective remain visible; do not level the curve in the
|
||||
image. Missing ray hits retain their fallback and never influence a
|
||||
valid partner. Call silhouette clamping afterwards to bound the result.
|
||||
|
||||
This is for template placement only, not measurement of the real hairline.
|
||||
"""
|
||||
h, w = image_shape
|
||||
scale = np.array([w, h], dtype=np.float64)
|
||||
up = face_up_vector(landmarks_norm) * scale
|
||||
length = np.linalg.norm(up)
|
||||
if length < 1e-9:
|
||||
return hairline_norm.copy()
|
||||
up /= length
|
||||
|
||||
anchors = landmarks_norm[C.MP_TOP_ANCHORS, :2] * scale
|
||||
points = hairline_norm * scale
|
||||
distances = (points - anchors) @ up
|
||||
indices = {mp_idx: i for i, mp_idx in enumerate(C.MP_TOP_ANCHORS)}
|
||||
for left, right in C.MP_TOP_ANCHOR_PAIRS:
|
||||
i, j = indices[left], indices[right]
|
||||
if not (valid[i] and valid[j]):
|
||||
continue
|
||||
mean_distance = (distances[i] + distances[j]) / 2.0
|
||||
for k in (i, j):
|
||||
points[k] += (mean_distance - distances[k]) * up
|
||||
return (points / scale).astype(np.float32)
|
||||
|
||||
|
||||
def smooth_hairline(
|
||||
hairline_norm: np.ndarray,
|
||||
valid: np.ndarray,
|
||||
|
||||
Reference in New Issue
Block a user