feat(测量): 接口1/6 返回与标注图一致的竖线坐标
前端需要按标注图重绘竖线,坐标与画线共用同一套几何。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -381,8 +381,8 @@ def _run_face_measure_data(image, variant="v1", landmarks_override=None):
|
||||
不含标注图(annotated_image_*),供接口5 容错复用;接口1 调用后再自行生成标注图。
|
||||
任何分割/七眼计算异常均内部吞掉(七眼相关字段不出现),不影响主测量结果。
|
||||
|
||||
variant="v1"(接口1/接口5):完整四庭七眼 + eye1~eye7(含头部端线段)。
|
||||
variant="v6"(接口6):去顶庭、不画端线、无 eye1~eye7。
|
||||
variant="v1"(接口1/接口5):完整四庭七眼 + eye1~eye7(含头部端线段)+ vertical_lines。
|
||||
variant="v6"(接口6):去顶庭、不画端线、无 eye1/eye7,vertical_lines 仅 6 条内线。
|
||||
"""
|
||||
h, w = image.shape[:2]
|
||||
from face_analysis.detector import detector
|
||||
@@ -428,30 +428,29 @@ def _run_face_measure_data(image, variant="v1", landmarks_override=None):
|
||||
# 占比、标注图仍按三庭处理,显示效果不变。
|
||||
|
||||
# 七眼段宽度(cm)。eye1=左耳外段 eye2=左脸颊 eye3=左眼 eye4=两眼间距 eye5=右眼 eye6=右脸颊 eye7=右耳外段。
|
||||
# eye2~eye6(5段)只用内部分点,接口1/6 共用;eye1/eye7 需耳朵分割端线,仅接口1 有。
|
||||
# eye2~eye6(5段)只用内部分点,接口1/6 共用;eye1/eye7 用竖线坐标里的人头端线,仅接口1 有。
|
||||
# vertical_lines 与标注图竖线同一套几何。
|
||||
try:
|
||||
from face_analysis.annotation import vertical_line_geometry
|
||||
epts = result.eyes["points"]
|
||||
lcx, rcx = epts["left_cheek"][0], epts["right_cheek"][0]
|
||||
pc = result.px_per_cm
|
||||
inner_xs = [lcx, epts["left_outer"][0], epts["left_inner"][0],
|
||||
epts["right_inner"][0], epts["right_outer"][0], rcx]
|
||||
geom = vertical_line_geometry(
|
||||
result, w, h, ear_mask=ear_mask, hair_mask=hair_mask, variant=variant)
|
||||
data["vertical_lines"] = geom
|
||||
inner_xs = [epts["left_cheek"][0], epts["left_outer"][0], epts["left_inner"][0],
|
||||
epts["right_inner"][0], epts["right_outer"][0], epts["right_cheek"][0]]
|
||||
for i in range(5):
|
||||
a, b = inner_xs[i], inner_xs[i + 1]
|
||||
data["seven_eyes"][f"eye{i + 2}"] = (
|
||||
None if (a is None or b is None) else round((b - a) / pc, 2))
|
||||
if variant != "v6":
|
||||
# 接口1 额外算 eye1/eye7(左/右耳外段),需耳朵分割端线。
|
||||
# 竖向范围上界用头顶(hair_top 始终可用)。
|
||||
from face_analysis.annotation import _ear_edges_from_mask
|
||||
top_y = vd["hair_top"][1]
|
||||
head_l, head_r = _ear_edges_from_mask(
|
||||
ear_mask, hair_mask,
|
||||
top_y, vd["chin_tip"][1],
|
||||
lcx, rcx, (lcx + rcx) / 2)
|
||||
by_name = {line["name"]: line["x"] for line in geom["lines"]}
|
||||
head_l = by_name.get("left_head_edge")
|
||||
head_r = by_name.get("right_head_edge")
|
||||
data["seven_eyes"]["eye1"] = (
|
||||
None if (head_l is None) else round((lcx - head_l) / pc, 2))
|
||||
None if head_l is None else round((by_name["left_cheek"] - head_l) / pc, 2))
|
||||
data["seven_eyes"]["eye7"] = (
|
||||
None if (head_r is None) else round((head_r - rcx) / pc, 2))
|
||||
None if head_r is None else round((head_r - by_name["right_cheek"]) / pc, 2))
|
||||
except Exception as seg_e: # noqa: BLE001
|
||||
logger.warning("七眼段宽度计算失败:%s", seg_e)
|
||||
|
||||
@@ -901,6 +900,7 @@ async def _face_measure_impl(image_file, image_url, image_base64, variant="v1"):
|
||||
- 四庭(顶庭/上庭/中庭/下庭)各段**厘米数值及占比**
|
||||
- 七眼(眼宽/脸宽/两眼间距)**厘米数值及占比**
|
||||
- 五个关键分界点的**原图像素坐标**(头顶/发际线/眉心/鼻翼下缘/下巴尖)
|
||||
- 竖线坐标 `vertical_lines`(与标注图同一套:共用 y 范围 + 从左到右的 x)
|
||||
|
||||
{_image_fields_desc}
|
||||
|
||||
@@ -956,6 +956,19 @@ async def _face_measure_impl(image_file, image_url, image_base64, variant="v1"):
|
||||
"nose_bottom": {"x": 540, "y": 1050},
|
||||
"chin_tip": {"x": 540, "y": 1360},
|
||||
},
|
||||
"vertical_lines": {
|
||||
"y_top": 98, "y_bottom": 1410,
|
||||
"lines": [
|
||||
{"name": "left_head_edge", "x": 120},
|
||||
{"name": "left_cheek", "x": 210},
|
||||
{"name": "left_eye_outer", "x": 310},
|
||||
{"name": "left_eye_inner", "x": 420},
|
||||
{"name": "right_eye_inner", "x": 560},
|
||||
{"name": "right_eye_outer", "x": 670},
|
||||
{"name": "right_cheek", "x": 780},
|
||||
{"name": "right_head_edge", "x": 890},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1032,6 +1045,7 @@ async def face_measure_debug(
|
||||
- 三庭(上庭/中庭/下庭)各段**厘米数值及占比**(**不含顶庭**)
|
||||
- 五眼段宽(eye2~eye6:左脸颊/左眼/两眼间距/右眼/右脸颊)**厘米数值**,另含眼宽/脸宽/两眼间距
|
||||
- 四个关键分界点的**原图像素坐标**(发际线/眉心/鼻翼下缘/下巴尖)
|
||||
- 竖线坐标 `vertical_lines`(发际线→下巴尖,仅 6 条内线,无人头两端)
|
||||
|
||||
基于接口1 的变体,与接口1 的差异:
|
||||
- **去顶庭**:不画头顶横线、不返回顶庭数据;`face_total_height_cm` 为三庭之和
|
||||
@@ -1089,6 +1103,17 @@ async def face_measure_debug(
|
||||
"nose_bottom": {"x": 540, "y": 1050},
|
||||
"chin_tip": {"x": 540, "y": 1360},
|
||||
},
|
||||
"vertical_lines": {
|
||||
"y_top": 430, "y_bottom": 1360,
|
||||
"lines": [
|
||||
{"name": "left_cheek", "x": 210},
|
||||
{"name": "left_eye_outer", "x": 310},
|
||||
{"name": "left_eye_inner", "x": 420},
|
||||
{"name": "right_eye_inner", "x": 560},
|
||||
{"name": "right_eye_outer", "x": 670},
|
||||
{"name": "right_cheek", "x": 780},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user