Generalize scene camera profiles
This commit is contained in:
@@ -413,13 +413,13 @@ The translator accepts the Qwen labels such as `front-right quarter view`,
|
|||||||
as the native camera nodes. `suppress_phone_visibility` is enabled by default so
|
as the native camera nodes. `suppress_phone_visibility` is enabled by default so
|
||||||
generic Qwen camera views do not add `phone hidden` or other phone wording.
|
generic Qwen camera views do not add `phone hidden` or other phone wording.
|
||||||
|
|
||||||
For coworking-style locations, the prompt builder also uses the translated
|
For camera-aware locations, the prompt builder also uses the translated camera
|
||||||
camera geometry to add a location-aware framing sentence. It currently targets
|
geometry to add a location-aware framing sentence. It currently has scene
|
||||||
`coworking lounge`, `business cafe`, and empty office scenes: front/side/back
|
profiles for coworking/business-office spaces and classical library/book-stack
|
||||||
views, zoom, and elevation change which desks, windows, laptop tables, glass
|
spaces: front/side/back views, zoom, and elevation change which desks, windows,
|
||||||
partitions, counters, or office rows are kept visible. In male-POV setups this
|
partitions, bookshelves, reading tables, lamps, or aisles are kept visible. In
|
||||||
becomes a first-person spatial description and the external camera sentence is
|
male-POV setups this becomes a first-person spatial description and the
|
||||||
suppressed.
|
external camera sentence is suppressed.
|
||||||
|
|
||||||
`SxCP SDXL Formatter` rewrites prompt builder output or `metadata_json` into
|
`SxCP SDXL Formatter` rewrites prompt builder output or `metadata_json` into
|
||||||
comma-tag SDXL/Pony-style prompts. Connect `metadata_json` when possible so
|
comma-tag SDXL/Pony-style prompts. Connect `metadata_json` when possible so
|
||||||
|
|||||||
@@ -648,12 +648,15 @@ Camera handling:
|
|||||||
|
|
||||||
Current camera-aware scene adapter:
|
Current camera-aware scene adapter:
|
||||||
|
|
||||||
- Coworking/business-cafe/office scenes are detected by `_is_coworking_scene`.
|
- Scene profiles live in `scene_camera_adapters.SCENE_CAMERA_PROFILES`.
|
||||||
- Location profile comes from `_coworking_location_profile`.
|
- Coworking/business-cafe/office scenes and classical library/book-stack scenes
|
||||||
- Direction, distance, and elevation details come from `_coworking_direction_detail`,
|
are detected by `scene_camera_profile`.
|
||||||
`_coworking_distance_detail`, and `_coworking_elevation_detail`.
|
- Direction, distance, and elevation details come from profile-aware helpers
|
||||||
- Composition cleanup for coworking outfit-check wording happens in
|
such as `scene_direction_detail`, `scene_distance_detail`, and
|
||||||
`_coworking_composition_prompt`.
|
`scene_elevation_detail`.
|
||||||
|
- Composition cleanup for mismatched outfit-check, mirror, bag, or shoes
|
||||||
|
wording happens in `contextual_composition_prompt`; compatibility wrappers
|
||||||
|
keep the old coworking function names available.
|
||||||
|
|
||||||
Important POV rule:
|
Important POV rule:
|
||||||
|
|
||||||
|
|||||||
+209
-70
@@ -25,26 +25,120 @@ CAMERA_DISTANCES = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def is_coworking_scene(scene_text: Any) -> bool:
|
SCENE_CAMERA_PROFILES: tuple[dict[str, Any], ...] = (
|
||||||
text = str(scene_text or "").lower()
|
{
|
||||||
return any(
|
"key": "business_cafe",
|
||||||
term in text
|
"family": "coworking",
|
||||||
for term in (
|
"terms": ("business cafe", "work cafe", "cafe"),
|
||||||
|
"layout_label": "Business cafe camera layout",
|
||||||
|
"place": "business cafe coworking counter",
|
||||||
|
"foreground": "counter edge, laptop corner, and small plant",
|
||||||
|
"midground": "bar stools, warm desk lamps, and coffee-counter work spots",
|
||||||
|
"background": "plants, mirror strip, menu wall, and repeated cafe work tables",
|
||||||
|
"detail_label": "cafe details",
|
||||||
|
"composition": {
|
||||||
|
"woman": "business-cafe selfie frame with the woman near a counter edge and warm work-table depth behind her",
|
||||||
|
"man": "business-cafe portrait frame with the man near a counter edge and warm work-table depth behind him",
|
||||||
|
"default": "business-cafe frame with the subjects near a counter edge and warm work-table depth behind them",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "office_after_hours",
|
||||||
|
"family": "coworking",
|
||||||
|
"terms": ("corporate office", "office after hours", "copier", "office lounge"),
|
||||||
|
"layout_label": "Office camera layout",
|
||||||
|
"place": "empty after-hours office",
|
||||||
|
"foreground": "copier alcove edge, chair backs, and nearest desk corner",
|
||||||
|
"midground": "repeating desks, glass partition seams, and muted monitor glow",
|
||||||
|
"background": "rows of empty workstations, city-light windows, and quiet office depth",
|
||||||
|
"detail_label": "office details",
|
||||||
|
"composition": {
|
||||||
|
"woman": "after-hours office frame with the woman near a desk edge and glass-partition depth behind her",
|
||||||
|
"man": "after-hours office frame with the man near a desk edge and glass-partition depth behind him",
|
||||||
|
"default": "after-hours office frame with the subjects near a desk edge and glass-partition depth behind them",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "coworking_lounge",
|
||||||
|
"family": "coworking",
|
||||||
|
"terms": (
|
||||||
"coworking",
|
"coworking",
|
||||||
"cowork",
|
"cowork",
|
||||||
"office lounge",
|
|
||||||
"business cafe",
|
|
||||||
"work cafe",
|
|
||||||
"shared office",
|
"shared office",
|
||||||
"corporate office",
|
|
||||||
"office after hours",
|
|
||||||
"laptops",
|
"laptops",
|
||||||
"warm desks",
|
"warm desks",
|
||||||
"repeating desks",
|
"repeating desks",
|
||||||
"glass partitions",
|
"glass partitions",
|
||||||
"copier alcove",
|
),
|
||||||
)
|
"layout_label": "Coworking camera layout",
|
||||||
)
|
"place": "coworking lounge",
|
||||||
|
"foreground": "near desk edge, laptop corner, and chair back",
|
||||||
|
"midground": "warm work desks, laptop tables, and glass partition seams",
|
||||||
|
"background": "tall windows, repeated desk rows, plants, and soft shared-office depth",
|
||||||
|
"detail_label": "coworking details",
|
||||||
|
"composition": {
|
||||||
|
"woman": "coworking lounge selfie frame with the woman near a desk edge and tall-window depth behind her",
|
||||||
|
"man": "coworking lounge portrait frame with the man near a desk edge and tall-window depth behind him",
|
||||||
|
"default": "coworking lounge frame with the subjects near a desk edge and tall-window depth behind them",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "classical_library",
|
||||||
|
"family": "library",
|
||||||
|
"terms": (
|
||||||
|
"classical library",
|
||||||
|
"library stacks",
|
||||||
|
"large library",
|
||||||
|
"grand library",
|
||||||
|
"reading room",
|
||||||
|
"bookshelves",
|
||||||
|
"book shelves",
|
||||||
|
"book stacks",
|
||||||
|
"rare-books",
|
||||||
|
"rare books",
|
||||||
|
"rolling ladders",
|
||||||
|
),
|
||||||
|
"layout_label": "Library camera layout",
|
||||||
|
"place": "classical library",
|
||||||
|
"foreground": "near bookshelf edge, reading-table corner, and brass lamp",
|
||||||
|
"midground": "towering bookshelves, rolling ladders, carved columns, and marble floor lines",
|
||||||
|
"background": "arched windows, repeated book aisles, warm brass lamps, and deep quiet library depth",
|
||||||
|
"detail_label": "library details",
|
||||||
|
"composition": {
|
||||||
|
"woman": "classical library frame with the woman near a bookshelf edge and long shelf depth behind her",
|
||||||
|
"man": "classical library frame with the man near a bookshelf edge and long shelf depth behind him",
|
||||||
|
"default": "classical library frame with the subjects near a bookshelf edge and long shelf depth behind them",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
MISMATCHED_COMPOSITION_TERMS = (
|
||||||
|
"outfit-check",
|
||||||
|
"outfit check",
|
||||||
|
"mirror view",
|
||||||
|
"mirror pose",
|
||||||
|
"bag",
|
||||||
|
"shoes",
|
||||||
|
"footwear",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def scene_camera_profile(scene_text: Any) -> dict[str, Any]:
|
||||||
|
text = str(scene_text or "").lower()
|
||||||
|
if not text:
|
||||||
|
return {}
|
||||||
|
for profile in SCENE_CAMERA_PROFILES:
|
||||||
|
if any(term in text for term in profile["terms"]):
|
||||||
|
return dict(profile)
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
|
def is_coworking_scene(scene_text: Any) -> bool:
|
||||||
|
return scene_camera_profile(scene_text).get("family") == "coworking"
|
||||||
|
|
||||||
|
|
||||||
|
def is_scene_camera_aware(scene_text: Any) -> bool:
|
||||||
|
return bool(scene_camera_profile(scene_text))
|
||||||
|
|
||||||
|
|
||||||
def _compact_label(value: Any, compact_labels: Mapping[str, str] | None = None) -> str:
|
def _compact_label(value: Any, compact_labels: Mapping[str, str] | None = None) -> str:
|
||||||
@@ -97,30 +191,10 @@ def camera_distance_from_text(text: Any) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def coworking_location_profile(scene_text: Any) -> dict[str, str]:
|
def coworking_location_profile(scene_text: Any) -> dict[str, str]:
|
||||||
text = str(scene_text or "").lower()
|
profile = scene_camera_profile(scene_text)
|
||||||
if "business cafe" in text or "work cafe" in text or "cafe" in text:
|
if profile.get("family") == "coworking":
|
||||||
return {
|
return profile
|
||||||
"layout_label": "Business cafe camera layout",
|
return scene_camera_profile("coworking lounge")
|
||||||
"place": "business cafe coworking counter",
|
|
||||||
"foreground": "counter edge, laptop corner, and small plant",
|
|
||||||
"midground": "bar stools, warm desk lamps, and coffee-counter work spots",
|
|
||||||
"background": "plants, mirror strip, menu wall, and repeated cafe work tables",
|
|
||||||
}
|
|
||||||
if "corporate office" in text or "office after hours" in text or "copier" in text:
|
|
||||||
return {
|
|
||||||
"layout_label": "Office camera layout",
|
|
||||||
"place": "empty after-hours office",
|
|
||||||
"foreground": "copier alcove edge, chair backs, and nearest desk corner",
|
|
||||||
"midground": "repeating desks, glass partition seams, and muted monitor glow",
|
|
||||||
"background": "rows of empty workstations, city-light windows, and quiet office depth",
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
"layout_label": "Coworking camera layout",
|
|
||||||
"place": "coworking lounge",
|
|
||||||
"foreground": "near desk edge, laptop corner, and chair back",
|
|
||||||
"midground": "warm work desks, laptop tables, and glass partition seams",
|
|
||||||
"background": "tall windows, repeated desk rows, plants, and soft shared-office depth",
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def coworking_subject_terms(subject_kind: str, pov_labels: list[str] | None = None) -> tuple[str, str]:
|
def coworking_subject_terms(subject_kind: str, pov_labels: list[str] | None = None) -> tuple[str, str]:
|
||||||
@@ -135,7 +209,7 @@ def coworking_subject_terms(subject_kind: str, pov_labels: list[str] | None = No
|
|||||||
return "the subjects", "them"
|
return "the subjects", "them"
|
||||||
|
|
||||||
|
|
||||||
def coworking_direction_detail(
|
def scene_direction_detail(
|
||||||
direction: str,
|
direction: str,
|
||||||
profile: dict[str, str],
|
profile: dict[str, str],
|
||||||
pov_labels: list[str] | None = None,
|
pov_labels: list[str] | None = None,
|
||||||
@@ -145,12 +219,13 @@ def coworking_direction_detail(
|
|||||||
foreground = profile["foreground"]
|
foreground = profile["foreground"]
|
||||||
midground = profile["midground"]
|
midground = profile["midground"]
|
||||||
background = profile["background"]
|
background = profile["background"]
|
||||||
|
detail_label = profile.get("detail_label") or "location details"
|
||||||
subject, pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
subject, pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
||||||
if pov_labels:
|
if pov_labels:
|
||||||
if "right side" in direction:
|
if "right side" in direction:
|
||||||
return f"{subject} is in right-side profile; {midground} run behind {pronoun} toward {background}, with coworking details kept at the frame edges"
|
return f"{subject} is in right-side profile; {midground} run behind {pronoun} toward {background}, with {detail_label} kept at the frame edges"
|
||||||
if "left side" in direction:
|
if "left side" in direction:
|
||||||
return f"{subject} is in left-side profile; {midground} run behind {pronoun} toward {background}, with coworking details kept at the frame edges"
|
return f"{subject} is in left-side profile; {midground} run behind {pronoun} toward {background}, with {detail_label} kept at the frame edges"
|
||||||
if "back-right" in direction or "back-left" in direction:
|
if "back-right" in direction or "back-left" in direction:
|
||||||
return f"{subject} stays close in one continuous diagonal first-person body angle; {midground} lead toward {background} behind {pronoun} at the edges, not in the lower foreground"
|
return f"{subject} stays close in one continuous diagonal first-person body angle; {midground} lead toward {background} behind {pronoun} at the edges, not in the lower foreground"
|
||||||
if direction == "back view":
|
if direction == "back view":
|
||||||
@@ -169,7 +244,16 @@ def coworking_direction_detail(
|
|||||||
return f"{subject} faces camera beside the {foreground}; {midground} sit between {pronoun} and {background}"
|
return f"{subject} faces camera beside the {foreground}; {midground} sit between {pronoun} and {background}"
|
||||||
|
|
||||||
|
|
||||||
def coworking_distance_detail(
|
def coworking_direction_detail(
|
||||||
|
direction: str,
|
||||||
|
profile: dict[str, str],
|
||||||
|
pov_labels: list[str] | None = None,
|
||||||
|
subject_kind: str = "subjects",
|
||||||
|
) -> str:
|
||||||
|
return scene_direction_detail(direction, profile, pov_labels, subject_kind)
|
||||||
|
|
||||||
|
|
||||||
|
def scene_distance_detail(
|
||||||
distance: str,
|
distance: str,
|
||||||
profile: dict[str, str],
|
profile: dict[str, str],
|
||||||
subject_kind: str,
|
subject_kind: str,
|
||||||
@@ -179,18 +263,27 @@ def coworking_distance_detail(
|
|||||||
subject, _pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
subject, _pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
||||||
if pov_labels:
|
if pov_labels:
|
||||||
if "wide" in distance or "full-body" in distance or "full body" in distance:
|
if "wide" in distance or "full-body" in distance or "full body" in distance:
|
||||||
return f"wide POV keeps {subject} readable with coworking context behind them"
|
return f"wide POV keeps {subject} readable with {profile['place']} context behind them"
|
||||||
if "close" in distance:
|
if "close" in distance:
|
||||||
return f"close POV keeps {subject} dominant with coworking context only at the sides or background"
|
return f"close POV keeps {subject} dominant with {profile['place']} context only at the sides or background"
|
||||||
return f"medium POV keeps {subject} dominant with room context behind them"
|
return f"medium POV keeps {subject} dominant with room context behind them"
|
||||||
if "wide" in distance or "full-body" in distance or "full body" in distance:
|
if "wide" in distance or "full-body" in distance or "full body" in distance:
|
||||||
return "wide crop keeps floor aisle, table rows, and window depth readable"
|
return f"wide crop keeps the {profile['foreground']}, {profile['midground']}, and {profile['background']} readable"
|
||||||
if "close" in distance:
|
if "close" in distance:
|
||||||
return "close crop keeps one desk or counter anchor visible"
|
return f"close crop keeps one anchor from the {profile['foreground']} visible"
|
||||||
return f"medium crop keeps {subject} dominant"
|
return f"medium crop keeps {subject} dominant"
|
||||||
|
|
||||||
|
|
||||||
def coworking_elevation_detail(
|
def coworking_distance_detail(
|
||||||
|
distance: str,
|
||||||
|
profile: dict[str, str],
|
||||||
|
subject_kind: str,
|
||||||
|
pov_labels: list[str] | None = None,
|
||||||
|
) -> str:
|
||||||
|
return scene_distance_detail(distance, profile, subject_kind, pov_labels)
|
||||||
|
|
||||||
|
|
||||||
|
def scene_elevation_detail(
|
||||||
elevation: str,
|
elevation: str,
|
||||||
profile: dict[str, str],
|
profile: dict[str, str],
|
||||||
subject_kind: str,
|
subject_kind: str,
|
||||||
@@ -200,29 +293,39 @@ def coworking_elevation_detail(
|
|||||||
subject, pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
subject, pronoun = coworking_subject_terms(subject_kind, pov_labels)
|
||||||
if pov_labels:
|
if pov_labels:
|
||||||
if "low-angle" in elevation:
|
if "low-angle" in elevation:
|
||||||
return f"low angle keeps POV body cues low while windows and partition lines rise behind {pronoun}"
|
return f"low angle keeps POV body cues low while the {profile['background']} rises behind {pronoun}"
|
||||||
if "elevated" in elevation:
|
if "elevated" in elevation:
|
||||||
return f"elevated POV keeps the viewer's eye line slightly higher than {subject}, with tabletop and glass lines only behind or at the side edges"
|
return f"elevated POV keeps the viewer's eye line slightly higher than {subject}, with {profile['foreground']} only behind or at the side edges"
|
||||||
if "high-angle" in elevation:
|
if "high-angle" in elevation:
|
||||||
return f"high angle looks down from the viewer's position with desks and aisle only in the background"
|
return f"high angle looks down from the viewer's position with {profile['midground']} only in the background"
|
||||||
return f"eye-level angle keeps tabletop lines and glass seams behind {pronoun}"
|
return f"eye-level angle keeps {profile['midground']} behind {pronoun}"
|
||||||
if "low-angle" in elevation:
|
if "low-angle" in elevation:
|
||||||
return f"low angle keeps the foreground desk edge low while windows and partitions rise behind {pronoun}"
|
return f"low angle keeps the {profile['foreground']} low while {profile['background']} rises behind {pronoun}"
|
||||||
if "elevated" in elevation:
|
if "elevated" in elevation:
|
||||||
return f"elevated angle shows tabletop surfaces, laptop shapes, chairs, and walking aisle around {pronoun}"
|
return f"elevated angle shows the {profile['foreground']} and {profile['midground']} around {pronoun}"
|
||||||
if "high-angle" in elevation:
|
if "high-angle" in elevation:
|
||||||
return f"high angle shows the desk grid, chairs, floor aisle, and placement of {pronoun}"
|
return f"high angle shows the {profile['place']} layout and placement of {pronoun}"
|
||||||
return f"eye-level angle keeps tabletop lines and glass seams straight"
|
return f"eye-level angle keeps {profile['midground']} visually stable"
|
||||||
|
|
||||||
|
|
||||||
def coworking_camera_scene_directive(
|
def coworking_elevation_detail(
|
||||||
|
elevation: str,
|
||||||
|
profile: dict[str, str],
|
||||||
|
subject_kind: str,
|
||||||
|
pov_labels: list[str] | None = None,
|
||||||
|
) -> str:
|
||||||
|
return scene_elevation_detail(elevation, profile, subject_kind, pov_labels)
|
||||||
|
|
||||||
|
|
||||||
|
def scene_camera_directive(
|
||||||
scene_text: Any,
|
scene_text: Any,
|
||||||
parsed: dict[str, Any],
|
parsed: dict[str, Any],
|
||||||
pov_labels: list[str] | None = None,
|
pov_labels: list[str] | None = None,
|
||||||
subject_kind: str = "subjects",
|
subject_kind: str = "subjects",
|
||||||
compact_labels: Mapping[str, str] | None = None,
|
compact_labels: Mapping[str, str] | None = None,
|
||||||
) -> str:
|
) -> str:
|
||||||
if not is_coworking_scene(scene_text):
|
profile = scene_camera_profile(scene_text)
|
||||||
|
if not profile:
|
||||||
return ""
|
return ""
|
||||||
direction = str(parsed.get("orbit_direction") or "").strip()
|
direction = str(parsed.get("orbit_direction") or "").strip()
|
||||||
elevation = str(parsed.get("orbit_elevation_label") or "").strip()
|
elevation = str(parsed.get("orbit_elevation_label") or "").strip()
|
||||||
@@ -233,10 +336,9 @@ def coworking_camera_scene_directive(
|
|||||||
distance = distance or camera_distance_from_text(custom_prompt)
|
distance = distance or camera_distance_from_text(custom_prompt)
|
||||||
if not any((direction, elevation, distance, custom_prompt)):
|
if not any((direction, elevation, distance, custom_prompt)):
|
||||||
return ""
|
return ""
|
||||||
profile = coworking_location_profile(scene_text)
|
direction_detail = scene_direction_detail(direction, profile, pov_labels, subject_kind)
|
||||||
direction_detail = coworking_direction_detail(direction, profile, pov_labels, subject_kind)
|
distance_detail = scene_distance_detail(distance, profile, subject_kind, pov_labels)
|
||||||
distance_detail = coworking_distance_detail(distance, profile, subject_kind, pov_labels)
|
elevation_detail = scene_elevation_detail(elevation, profile, subject_kind, pov_labels)
|
||||||
elevation_detail = coworking_elevation_detail(elevation, profile, subject_kind, pov_labels)
|
|
||||||
if pov_labels:
|
if pov_labels:
|
||||||
return (
|
return (
|
||||||
f"{profile['layout_label']} from POV: {direction_detail}. "
|
f"{profile['layout_label']} from POV: {direction_detail}. "
|
||||||
@@ -250,19 +352,56 @@ def coworking_camera_scene_directive(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def coworking_composition_prompt(scene_text: Any, composition: Any, subject_kind: str = "subjects") -> str:
|
def coworking_camera_scene_directive(
|
||||||
|
scene_text: Any,
|
||||||
|
parsed: dict[str, Any],
|
||||||
|
pov_labels: list[str] | None = None,
|
||||||
|
subject_kind: str = "subjects",
|
||||||
|
compact_labels: Mapping[str, str] | None = None,
|
||||||
|
) -> str:
|
||||||
|
if not is_coworking_scene(scene_text):
|
||||||
|
return ""
|
||||||
|
return scene_camera_directive(scene_text, parsed, pov_labels, subject_kind, compact_labels)
|
||||||
|
|
||||||
|
|
||||||
|
def profile_composition_text(profile: dict[str, Any], subject_kind: str) -> str:
|
||||||
|
composition = profile.get("composition") if isinstance(profile.get("composition"), dict) else {}
|
||||||
|
if subject_kind == "woman" and composition.get("woman"):
|
||||||
|
return str(composition["woman"])
|
||||||
|
if subject_kind == "man" and composition.get("man"):
|
||||||
|
return str(composition["man"])
|
||||||
|
text = str(composition.get("default") or f"{profile['place']} frame with the subjects clearly placed in the room")
|
||||||
|
if subject_kind == "couple":
|
||||||
|
text = text.replace("the subjects", "the couple")
|
||||||
|
if "composition" not in text.lower():
|
||||||
|
text = f"{text} composition"
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def contextual_composition_prompt(scene_text: Any, composition: Any, subject_kind: str = "subjects") -> str:
|
||||||
text = str(composition or "").strip()
|
text = str(composition or "").strip()
|
||||||
if not text or not is_coworking_scene(scene_text):
|
if not text:
|
||||||
|
return text
|
||||||
|
profile = scene_camera_profile(scene_text)
|
||||||
|
if not profile:
|
||||||
return text
|
return text
|
||||||
lower = text.lower()
|
lower = text.lower()
|
||||||
if not any(term in lower for term in ("office-lobby", "office lobby", "walking composition", "outfit-check")):
|
profile_lower = " ".join(
|
||||||
|
str(profile.get(key, "")).lower()
|
||||||
|
for key in ("place", "foreground", "midground", "background")
|
||||||
|
)
|
||||||
|
already_matches = any(term and term in lower for term in profile_lower.replace(",", " ").split())
|
||||||
|
mismatched = any(term in lower for term in MISMATCHED_COMPOSITION_TERMS)
|
||||||
|
office_generic = any(term in lower for term in ("office-lobby", "office lobby", "walking composition", "outfit-check"))
|
||||||
|
if not mismatched and not office_generic and already_matches:
|
||||||
return text
|
return text
|
||||||
subject, _pronoun = coworking_subject_terms(subject_kind)
|
if not mismatched and not office_generic and profile.get("family") != "coworking":
|
||||||
if subject_kind == "woman":
|
return text
|
||||||
return "coworking lounge selfie frame with the woman near a desk edge and tall-window depth behind her"
|
return profile_composition_text(profile, subject_kind)
|
||||||
if subject_kind == "man":
|
|
||||||
return "coworking lounge portrait frame with the man near a desk edge and tall-window depth behind him"
|
|
||||||
return f"coworking lounge frame with {subject} near a desk edge and tall-window depth behind them"
|
def coworking_composition_prompt(scene_text: Any, composition: Any, subject_kind: str = "subjects") -> str:
|
||||||
|
return contextual_composition_prompt(scene_text, composition, subject_kind)
|
||||||
|
|
||||||
|
|
||||||
def camera_scene_directive_for_context(
|
def camera_scene_directive_for_context(
|
||||||
@@ -277,7 +416,7 @@ def camera_scene_directive_for_context(
|
|||||||
or parsed_camera_config.get("camera_mode") == "disabled"
|
or parsed_camera_config.get("camera_mode") == "disabled"
|
||||||
):
|
):
|
||||||
return ""
|
return ""
|
||||||
return coworking_camera_scene_directive(
|
return scene_camera_directive(
|
||||||
scene_text,
|
scene_text,
|
||||||
parsed_camera_config,
|
parsed_camera_config,
|
||||||
pov_labels,
|
pov_labels,
|
||||||
|
|||||||
@@ -548,6 +548,28 @@ def smoke_row_camera_policy() -> None:
|
|||||||
"coworking lounge frame with the couple near a desk edge" in updated.get("composition", ""),
|
"coworking lounge frame with the couple near a desk edge" in updated.get("composition", ""),
|
||||||
"row camera policy did not adapt coworking composition for couple rows",
|
"row camera policy did not adapt coworking composition for couple rows",
|
||||||
)
|
)
|
||||||
|
library_row = {
|
||||||
|
"prompt": "A generated adult prompt. Composition: vertical polished mirror view with bag and shoes visible. Avoid: low quality.",
|
||||||
|
"caption": "sxcppnl7, generated adult prompt, polished mirror view with bag and shoes visible, illustration",
|
||||||
|
"scene_text": "grand classical library hall with towering dark-wood bookshelves, carved columns, rolling ladders, marble floor, and warm brass lamps",
|
||||||
|
"composition": "polished mirror view with bag and shoes visible",
|
||||||
|
"subject_type": "woman",
|
||||||
|
"women_count": 1,
|
||||||
|
"men_count": 0,
|
||||||
|
}
|
||||||
|
updated_library = row_camera.apply_camera_config(
|
||||||
|
library_row,
|
||||||
|
_orbit_camera(horizontal_angle=315, vertical_angle=0, zoom=5.0),
|
||||||
|
compact_labels=pb.CAMERA_COMPACT_LABELS,
|
||||||
|
)
|
||||||
|
library_scene = _expect_text("row_camera_policy.library_scene", updated_library.get("camera_scene_directive"), 40)
|
||||||
|
library_composition = _expect_text("row_camera_policy.library_composition", updated_library.get("composition"), 20)
|
||||||
|
_expect("Library camera layout" in library_scene, "row camera policy missed library layout")
|
||||||
|
_expect("front-left quarter view" in library_scene, "row camera library layout missed orbit direction")
|
||||||
|
_expect("bookshelf" in library_scene.lower() or "bookshelves" in library_scene.lower(), "row camera library layout missed shelf anchors")
|
||||||
|
_expect("bag" not in library_composition.lower(), "row camera library composition leaked bag wording")
|
||||||
|
_expect("shoes" not in library_composition.lower(), "row camera library composition leaked shoes wording")
|
||||||
|
_expect("library" in library_composition.lower(), "row camera library composition did not become location-aware")
|
||||||
|
|
||||||
|
|
||||||
def smoke_config_route_location_theme() -> None:
|
def smoke_config_route_location_theme() -> None:
|
||||||
@@ -588,8 +610,12 @@ def smoke_config_route_location_theme() -> None:
|
|||||||
scene = _expect_text("config_route_location_theme.scene_text", row.get("scene_text"), 20)
|
scene = _expect_text("config_route_location_theme.scene_text", row.get("scene_text"), 20)
|
||||||
composition = _expect_text("config_route_location_theme.composition", row.get("composition"), 10)
|
composition = _expect_text("config_route_location_theme.composition", row.get("composition"), 10)
|
||||||
camera = _expect_text("config_route_location_theme.camera_directive", row.get("camera_directive"), 20)
|
camera = _expect_text("config_route_location_theme.camera_directive", row.get("camera_directive"), 20)
|
||||||
|
scene_directive = _expect_text("config_route_location_theme.camera_scene_directive", row.get("camera_scene_directive"), 40)
|
||||||
_expect("library" in scene.lower() or "bookshelves" in scene.lower(), "location theme did not drive scene")
|
_expect("library" in scene.lower() or "bookshelves" in scene.lower(), "location theme did not drive scene")
|
||||||
_expect("books" in composition.lower() or "shelf" in composition.lower() or "library" in composition.lower(), "location theme did not drive composition")
|
_expect("books" in composition.lower() or "shelf" in composition.lower() or "library" in composition.lower(), "location theme did not drive composition")
|
||||||
|
_expect("Library camera layout" in scene_directive, "location theme did not drive library camera-scene adapter")
|
||||||
|
_expect("front-left quarter view" in scene_directive, "library camera-scene adapter missed orbit direction")
|
||||||
|
_expect("bag" not in composition.lower() and "shoes" not in composition.lower(), "location theme composition leaked outfit-check props")
|
||||||
_expect("315-degree front-left quarter view" in camera, "config route did not preserve orbit camera directive")
|
_expect("315-degree front-left quarter view" in camera, "config route did not preserve orbit camera directive")
|
||||||
seed_config = row.get("seed_config") if isinstance(row.get("seed_config"), dict) else {}
|
seed_config = row.get("seed_config") if isinstance(row.get("seed_config"), dict) else {}
|
||||||
_expect(seed_config.get("pose_seed") == 3302, "seed lock did not reroll pose axis")
|
_expect(seed_config.get("pose_seed") == 3302, "seed lock did not reroll pose axis")
|
||||||
@@ -608,6 +634,7 @@ def smoke_config_route_location_theme() -> None:
|
|||||||
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single")
|
krea = krea_formatter.format_krea2_prompt("", metadata_json=_json(row), target="single")
|
||||||
prompt = krea.get("krea_prompt") or ""
|
prompt = krea.get("krea_prompt") or ""
|
||||||
_expect("library" in prompt.lower() or "bookshelves" in prompt.lower(), "Krea config route lost theme scene")
|
_expect("library" in prompt.lower() or "bookshelves" in prompt.lower(), "Krea config route lost theme scene")
|
||||||
|
_expect("Library camera layout" in prompt, "Krea config route lost library camera-scene directive")
|
||||||
_expect("315-degree front-left quarter view" in prompt, "Krea config route lost camera directive")
|
_expect("315-degree front-left quarter view" in prompt, "Krea config route lost camera directive")
|
||||||
_expect_formatter_outputs(row, "config_route_location_theme", target="single")
|
_expect_formatter_outputs(row, "config_route_location_theme", target="single")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user