Round 11: resize the single-face no-face short-circuit to the paste canvas

Round-11 upscaler-pipeline audit (owner task: check whether the bg/face
upscaler inputs are applied correctly or erroneous, and how they compose
with final_upscale_factor):

- VERDICT: the two upscaler models are quality operators only - their
  output scales are always absorbed by resizes (batched_bg_frames /
  vendored paste / aligned path); final_upscale_factor alone fixes the
  output geometry (the paste canvas x factor), exactly as the node
  tooltip states.  Slowdown with x4 models is the documented design
  (a face upscaler disqualifies the batched paste; bg model runs per
  fallback frame; the canvas is model-widened x factor).
- CONFIRMED ERROR (the one real bug found, reproduced CPU-only in three
  configurations): the single-face no-face/affine-None short-circuit
  appended the raw _run_upscaler output without the factor/canvas
  resize, so a bg model with scale != factor or a sub-512 clip mixed row
  sizes and crashed the convert-out (np.stack ValueError).  The
  multiface sibling already resized (round 10); this applies the same
  paste_canvas_hw + LANCZOS4 resize to the single-face site.
- The twin size check (:1352) is dead code (all_restored_faces_cv2 is
  preallocated to num_input_frames) - no fix required.
- One pin's paste stub corrected to the real 512x512 canvas with a
  dated docstring; no fixture re-capture needed (only rows that crashed
  the run change pixels).

Gate: 555 passed, 6 skipped, 7 deselected, 0 failed (baseline 555).
This commit is contained in:
WildAi
2026-10-31 13:51:39 +03:00
parent f9c10eb6e5
commit 58d8b11ade
2 changed files with 21 additions and 1 deletions
+14
View File
@@ -1342,6 +1342,20 @@ class KEEPFaceProcessor:
or np.isnan(avg_landmarks_sequence[i]).any()
):
final_pasted_frame = self._run_upscaler(self.bg_upscale_model, original_frame_bgr)
# Round 11 (2026-10-31): the fix-1.1 snippet's raw
# upscaler output cannot join the IMAGE batch when
# frame x model.scale != canvas x factor (the same
# disclosed deviation as the multiface
# short-circuit's resize): the output size is the
# paste canvas, reached with the same LANCZOS4
# resize the vendored paste applied to its no-face
# frames.
canvas_h, canvas_w = paste_mod.paste_canvas_hw(
original_frame_bgr.shape[:2], final_upscale_factor, canvas_hw)
if final_pasted_frame.shape[0] != canvas_h or final_pasted_frame.shape[1] != canvas_w:
final_pasted_frame = cv2.resize(
final_pasted_frame, (canvas_w, canvas_h),
interpolation=cv2.INTER_LANCZOS4)
output_frames_cv2.append(final_pasted_frame)
# the same bookkeeping as the sibling fallback rows:
# the device-output tails index the fallback rows by
+7 -1
View File
@@ -495,6 +495,12 @@ def test_every_console_write_of_the_facelib_reaches_the_logger(
patched to ``[None, valid]``) so the paste-back print keeps firing;
the stub's paste return is canvas-sized (the background-only row and
the vendored row must stack).
Round 11 (2026-10-31): the short-circuit row is canvas-sized since the
short-circuit resize (the fix-1.1 snippet's raw output cannot join the
IMAGE batch at a mismatched shape), so the stub's return is the real
512x512 canvas the vendored paste assembles from ``input_img`` - the
pin's routing assertions are unchanged.
"""
real_estimate = processor_module.estimate_affines
@@ -513,7 +519,7 @@ def test_every_console_write_of_the_facelib_reaches_the_logger(
# row and the vendored row stack; the print stays (it is the routing probe)
def canvas_sized_paste(*args, **kwargs):
print("Warning: Mismatch between restored_faces and inverse_affine_matrices.")
return np.zeros((16, 16, 3), dtype=np.uint8)
return np.zeros((512, 512, 3), dtype=np.uint8)
face_helper.paste_faces_to_input_image = canvas_sized_paste
frames = torch.rand((2, 16, 16, 3), dtype=torch.float32)