hdremover commited on
Commit
15c01c8
·
verified ·
1 Parent(s): 3245d2f

Update engine.py

Browse files
Files changed (1) hide show
  1. engine.py +24 -6
engine.py CHANGED
@@ -547,13 +547,22 @@ def straighten_image(image: Image.Image, angle_deg: float) -> Image.Image:
547
  old FaceBox coordinates analytically is more error-prone than just
548
  re-detecting on the already-cheap YuNet pass.
549
 
 
 
 
 
 
 
 
 
 
 
 
 
 
550
  BICUBIC resample, matching every other resize/rotate op in this file
551
  that ends up in a printed deliverable (see load_and_bound's docstring
552
- for why NEAREST is never used here). Background fill uses transparent
553
- (0,0,0,0) since this runs on the RGBA-capable `bounded` stage before
554
- background compositing — corners exposed by the rotation get painted
555
- over by the spec's background color later in the pipeline, same as
556
- crop_to_spec's existing pad logic.
557
  """
558
  if abs(angle_deg) < 0.5:
559
  return image # sub-half-degree tilt isn't worth a resample pass
@@ -573,7 +582,16 @@ def straighten_image(image: Image.Image, angle_deg: float) -> Image.Image:
573
  expand=True,
574
  fillcolor=(0, 0, 0, 0),
575
  )
576
- return rotated
 
 
 
 
 
 
 
 
 
577
 
578
 
579
  # ---------------------------------------------------------------------------
 
547
  old FaceBox coordinates analytically is more error-prone than just
548
  re-detecting on the already-cheap YuNet pass.
549
 
550
+ Always returns RGB (never RGBA) — this runs on `bounded`, which is
551
+ RGB going into segment_alpha()'s Normalize transform; that transform
552
+ is hard-coded to 3 channels (see _seg_transform) and raises a shape
553
+ RuntimeError on 4-channel input. The rotation itself is done in RGBA
554
+ internally so PIL can fill the corners exposed by expand=True with a
555
+ real transparent value instead of smearing edge pixels (BICUBIC
556
+ without an alpha channel would otherwise blend rotated content
557
+ against whatever garbage sits outside the original frame) — that
558
+ RGBA intermediate is then flattened onto a neutral gray backing
559
+ before return, so the corners become plain pixels the segmentation
560
+ model can process like any other background, not transparency it has
561
+ never seen and has no defined behavior for.
562
+
563
  BICUBIC resample, matching every other resize/rotate op in this file
564
  that ends up in a printed deliverable (see load_and_bound's docstring
565
+ for why NEAREST is never used here).
 
 
 
 
566
  """
567
  if abs(angle_deg) < 0.5:
568
  return image # sub-half-degree tilt isn't worth a resample pass
 
582
  expand=True,
583
  fillcolor=(0, 0, 0, 0),
584
  )
585
+
586
+ # Flatten onto a neutral 50%-gray RGB canvas — not white/black, so the
587
+ # exposed-corner triangles don't accidentally read as a "clean white
588
+ # background" region to segment_alpha's foreground/background
589
+ # separation (a pure white corner touching a light shirt could bias
590
+ # the matte). Gray is a safe, low-signal fill any segmentation model
591
+ # treats as unremarkable background.
592
+ backing = Image.new("RGB", rotated.size, (128, 128, 128))
593
+ backing.paste(rotated, mask=rotated.split()[3]) # alpha channel as mask
594
+ return backing
595
 
596
 
597
  # ---------------------------------------------------------------------------