Spaces:
Sleeping
Sleeping
Update engine.py
Browse files
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).
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
# ---------------------------------------------------------------------------
|