fix: enforce orthographic top bottom subject views
This commit is contained in:
26
api/main.py
26
api/main.py
@@ -2641,8 +2641,8 @@ SUBJECT_VIEW_LABELS: dict[str, str] = {
|
|||||||
"three_quarter_right": "右前 45°",
|
"three_quarter_right": "右前 45°",
|
||||||
"side": "侧面",
|
"side": "侧面",
|
||||||
"side_walk": "侧面走路",
|
"side_walk": "侧面走路",
|
||||||
"top": "顶部视角",
|
"top": "正投影俯视图",
|
||||||
"bottom": "底部视角",
|
"bottom": "正投影仰视图",
|
||||||
"expression_neutral": "中性表情",
|
"expression_neutral": "中性表情",
|
||||||
"expression_smile": "微笑表情",
|
"expression_smile": "微笑表情",
|
||||||
"expression_happy": "开心表情",
|
"expression_happy": "开心表情",
|
||||||
@@ -2691,11 +2691,27 @@ def _subject_view_labels(kind: SubjectKind, requested: list[str] | None = None)
|
|||||||
("back", "背面"),
|
("back", "背面"),
|
||||||
("left", "左侧"),
|
("left", "左侧"),
|
||||||
("right", "右侧"),
|
("right", "右侧"),
|
||||||
("top", "顶部"),
|
("top", "正投影俯视图"),
|
||||||
("bottom", "底部"),
|
("bottom", "正投影仰视图"),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def _subject_view_projection_clause(view: str) -> str:
|
||||||
|
if view == "top":
|
||||||
|
return (
|
||||||
|
"Patent-style orthographic top view: look straight down from directly above the product, "
|
||||||
|
"with the viewing direction perpendicular to the top face. No perspective, no tilt, no 3/4 angle, "
|
||||||
|
"no oblique overhead camera, no visible front/side depth unless it is true product thickness in orthographic projection. "
|
||||||
|
)
|
||||||
|
if view == "bottom":
|
||||||
|
return (
|
||||||
|
"Patent-style orthographic bottom view: look straight up at the underside/bottom face, "
|
||||||
|
"with the viewing direction perpendicular to the bottom face. No perspective, no tilt, no 3/4 angle, "
|
||||||
|
"no low-angle perspective camera, no visible front/side depth unless it is true product thickness in orthographic projection. "
|
||||||
|
)
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
def _attach_temporal_metrics(items: list[dict]) -> None:
|
def _attach_temporal_metrics(items: list[dict]) -> None:
|
||||||
"""相邻低清帧差异:转场 / 动作目标依赖它,不需要逐帧高分辨率扫描。"""
|
"""相邻低清帧差异:转场 / 动作目标依赖它,不需要逐帧高分辨率扫描。"""
|
||||||
for i, it in enumerate(items):
|
for i, it in enumerate(items):
|
||||||
@@ -6910,11 +6926,13 @@ def _generate_subject_assets_sync(job_id: str, idx: int, element_id: str, req: G
|
|||||||
else:
|
else:
|
||||||
view_prompt = f"complete object/product reference, {view_label} view"
|
view_prompt = f"complete object/product reference, {view_label} view"
|
||||||
view_name = view.replace("_", " ")
|
view_name = view.replace("_", " ")
|
||||||
|
projection_clause = _subject_view_projection_clause(view)
|
||||||
single_view_clause = (
|
single_view_clause = (
|
||||||
f"Single-image output rule: this output file is ONLY for the {view_label} view ({view_name}). "
|
f"Single-image output rule: this output file is ONLY for the {view_label} view ({view_name}). "
|
||||||
"Render exactly one subject, one time, in one pose and one camera angle. "
|
"Render exactly one subject, one time, in one pose and one camera angle. "
|
||||||
"Do not create a multi-view sheet, contact sheet, grid, storyboard, lineup, comparison layout, before/after layout, mirrored pair, duplicate subjects, thumbnails, labels, captions, arrows, view names, panel borders, or multiple versions in the same image. "
|
"Do not create a multi-view sheet, contact sheet, grid, storyboard, lineup, comparison layout, before/after layout, mirrored pair, duplicate subjects, thumbnails, labels, captions, arrows, view names, panel borders, or multiple versions in the same image. "
|
||||||
"Do not include any other views in this image. "
|
"Do not include any other views in this image. "
|
||||||
|
+ projection_clause
|
||||||
)
|
)
|
||||||
framing_clause = (
|
framing_clause = (
|
||||||
"For this close-up view, intentionally crop as an upper-body asset from head/neck to chest or upper back; the neck, shoulders, collarbone or upper spine area must be large, clear, and useful for placing a neck-and-shoulder massage device. "
|
"For this close-up view, intentionally crop as an upper-body asset from head/neck to chest or upper back; the neck, shoulders, collarbone or upper spine area must be large, clear, and useful for placing a neck-and-shoulder massage device. "
|
||||||
|
|||||||
@@ -1181,6 +1181,19 @@ ProductRefStateItem {
|
|||||||
<h2>变更记录</h2>
|
<h2>变更记录</h2>
|
||||||
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
<p>这个记录不是 git log 的替代品。它记录“产品理解发生了什么变化、影响了哪些源码、你以后描述需求时该怎么说”。后续每次改功能都要补一条。</p>
|
||||||
<div class="changelog">
|
<div class="changelog">
|
||||||
|
<article class="change">
|
||||||
|
<header>
|
||||||
|
<h3>2026-05-25 · 主体套图俯视和仰视改为正投影口径</h3>
|
||||||
|
<span class="tag amber">API</span>
|
||||||
|
<span class="tag violet">UI</span>
|
||||||
|
<span class="tag blue">Docs</span>
|
||||||
|
</header>
|
||||||
|
<div class="body">
|
||||||
|
<p><strong>问题:</strong>原先主体/产品套图里把 <code>top</code> 和 <code>bottom</code> 简写为“顶部/底部”或“俯视/仰视”,模型容易理解成斜上方、斜下方或 3/4 透视镜头,不符合外观专利六面正投影视图的要求。</p>
|
||||||
|
<p><strong>改动:</strong><code>api/main.py</code> 的 <code>SUBJECT_VIEW_LABELS</code>、默认物体 6 视图和主体生图 prompt 已改为“正投影俯视图 / 正投影仰视图”,并在生成单图时加入 <code>orthographic top/bottom view</code>、<code>no perspective</code>、<code>no tilt</code>、<code>no 3/4 angle</code> 约束。<code>web/components/lightbox.tsx</code>、<code>web/components/ad-recreation-board.tsx</code> 和 <code>web/components/storyboard-editor.tsx</code> 同步更新显示文案和后续分镜提示词。</p>
|
||||||
|
<p><strong>影响:</strong>以后描述专利六面图需求时应说“正投影俯视图 / 正投影仰视图”,不要只说“俯视角度 / 仰视角度”;这些视图是垂直投影,不是带角度的摄影机视角。</p>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
<article class="change">
|
<article class="change">
|
||||||
<header>
|
<header>
|
||||||
<h3>2026-05-24 · 默认首页完整重设计为多人创作平台</h3>
|
<h3>2026-05-24 · 默认首页完整重设计为多人创作平台</h3>
|
||||||
|
|||||||
@@ -2019,6 +2019,11 @@ function selectProductItemsForRow(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function subjectViewLabel(view: string) {
|
function subjectViewLabel(view: string) {
|
||||||
|
const labels: Record<string, string> = {
|
||||||
|
top: "正投影俯视图",
|
||||||
|
bottom: "正投影仰视图",
|
||||||
|
}
|
||||||
|
if (labels[view]) return labels[view]
|
||||||
return SUBJECT_ASSET_VIEWS.find((item) => item.value === view)?.label ?? view
|
return SUBJECT_ASSET_VIEWS.find((item) => item.value === view)?.label ?? view
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2034,6 +2039,8 @@ function subjectViewRoleHint(view: string) {
|
|||||||
bust_left_45: "肩颈左前近景、手部调整、佩戴贴合",
|
bust_left_45: "肩颈左前近景、手部调整、佩戴贴合",
|
||||||
bust_right_45: "肩颈右前近景、手部调整、佩戴贴合",
|
bust_right_45: "肩颈右前近景、手部调整、佩戴贴合",
|
||||||
back_neck_detail: "后颈肩背特写、触点位置、产品贴合",
|
back_neck_detail: "后颈肩背特写、触点位置、产品贴合",
|
||||||
|
top: "正投影俯视、无透视、无倾斜、产品顶部轮廓",
|
||||||
|
bottom: "正投影仰视、无透视、无倾斜、产品底部结构",
|
||||||
}
|
}
|
||||||
return hints[view] ?? "主体参考视角"
|
return hints[view] ?? "主体参考视角"
|
||||||
}
|
}
|
||||||
@@ -2050,6 +2057,8 @@ function subjectViewPromptHint(view: string) {
|
|||||||
bust_left_45: "left three-quarter neck-and-shoulder close-up, hand adjustment, wearable fit",
|
bust_left_45: "left three-quarter neck-and-shoulder close-up, hand adjustment, wearable fit",
|
||||||
bust_right_45: "right three-quarter neck-and-shoulder close-up, hand adjustment, wearable fit",
|
bust_right_45: "right three-quarter neck-and-shoulder close-up, hand adjustment, wearable fit",
|
||||||
back_neck_detail: "back-neck and upper-back detail, contact-pad position, product fit",
|
back_neck_detail: "back-neck and upper-back detail, contact-pad position, product fit",
|
||||||
|
top: "orthographic top view, straight down from above, no perspective, no tilt, no three-quarter angle",
|
||||||
|
bottom: "orthographic bottom view, straight up at underside, no perspective, no tilt, no three-quarter angle",
|
||||||
}
|
}
|
||||||
return hints[view] ?? "subject reference view"
|
return hints[view] ?? "subject reference view"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ const OBJECT_VIEW_OPTIONS = [
|
|||||||
["back", "背面"],
|
["back", "背面"],
|
||||||
["left", "左侧"],
|
["left", "左侧"],
|
||||||
["right", "右侧"],
|
["right", "右侧"],
|
||||||
["top", "顶部"],
|
["top", "正投影俯视图"],
|
||||||
["bottom", "底部"],
|
["bottom", "正投影仰视图"],
|
||||||
]
|
]
|
||||||
|
|
||||||
const LIVING_VIEW_OPTIONS = [
|
const LIVING_VIEW_OPTIONS = [
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ export function StoryboardEditor({ job, frameIndex, onClose }: Props) {
|
|||||||
📐 多视角
|
📐 多视角
|
||||||
</div>
|
</div>
|
||||||
<div className="text-[9.5px] text-white/45 leading-tight">
|
<div className="text-[9.5px] text-white/45 leading-tight">
|
||||||
侧面 / 仰视 / 俯视等同元素的不同角度
|
侧面 / 正投影俯视 / 正投影仰视等同元素不同视图
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
|
|||||||
Reference in New Issue
Block a user