Skip to content

Conversation

federicopozzi33
Copy link
Contributor

@federicopozzi33 federicopozzi33 commented Aug 19, 2025

Summary by Sourcery

Add Pillow-based resize backend to geometric augmentations, centralize no-op shape checks, and extend dependency and test coverage accordingly

New Features:

  • Detect "pillow" backend via ALBUMENTATIONS_RESIZE and import if PIL is available
  • Implement resize_pil function to perform image resizing using PIL

Enhancements:

  • Return images unchanged if they already match the target size in the main resize function and remove duplicate checks from individual backends

Build:

  • Add pillow to optional-dependencies in pyproject.toml

Tests:

  • Add tests comparing Pillow and OpenCV resize outputs with xfail markers for interpolation differences

Copy link

sourcery-ai bot commented Aug 19, 2025

Reviewer's Guide

This PR adds support for Pillow as an optional image resize backend by extending environment‐based backend detection and introducing a resize_pil implementation, streamlines the resize workflow with a unified early exit for images already at target dimensions while removing redundant checks, extends tests to cover Pillow vs OpenCV consistency with appropriate xfail and skip markers, and updates pyproject.toml to declare Pillow in optional dependencies.

Entity relationship diagram for optional dependencies in pyproject.toml

erDiagram
    PROJECT ||--o{ PILLOW : "optional dependency"
    PROJECT ||--o{ PYVIPS : "optional dependency"
    PROJECT ||--o{ PYTORCH : "optional dependency"
    PROJECT {
        string name
        string version
        string[] optional-dependencies
    }
    PILLOW {
        string name
    }
    PYVIPS {
        string name
    }
    PYTORCH {
        string name
    }
Loading

Class diagram for new and updated resize functions

classDiagram
    class functional {
        +resize(img: np.ndarray, target_shape: tuple[int, int], interpolation: int) np.ndarray
        +resize_cv2(img: np.ndarray, target_shape: tuple[int, int], interpolation: int) np.ndarray
        +resize_pyvips(img: np.ndarray, target_shape: tuple[int, int], interpolation: int) np.ndarray
        +resize_pil(img: np.ndarray, target_shape: tuple[int, int], interpolation: int) np.ndarray
    }
    functional --> "uses" PIL: resize_pil
    functional --> "uses" cv2: resize_cv2
    functional --> "uses" pyvips: resize_pyvips
    functional --> "selects" resize_backend: resize
Loading

File-Level Changes

Change Details Files
Support Pillow backend for image resizing
  • Extend _get_resize_backend to return “pillow” when PIL is importable
  • Implement resize_pil converting NumPy arrays to PIL Images and back
  • Add resize_pil function definition in functional.py
albumentations/augmentations/geometric/functional.py
Optimize resize workflow by short-circuiting no-op resizes
  • Add early return in resize() when target shape matches image
  • Remove redundant shape‐equality checks from resize_cv2 and resize_pyvips
  • Update docstrings to reflect backend-specific implementations
albumentations/augmentations/geometric/functional.py
Enhance tests for Pillow backend consistency
  • Add pytest xfail for Pillow vs OpenCV interpolation differences
  • Skip tests when PIL is not installed
  • Introduce test comparing resize_cv2 and resize_pil outputs with tolerance
tests/functional/test_geometric.py
Update optional dependencies to include Pillow
  • Declare pillow under optional-dependencies in pyproject.toml
pyproject.toml

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ternaus
Copy link
Contributor

ternaus commented Aug 22, 2025

@federicopozzi33 Is it ready to be merged?

@federicopozzi33
Copy link
Contributor Author

@federicopozzi33 Is it ready to be merged?

I'll just add a test, and then it’s good to go.

@federicopozzi33 federicopozzi33 marked this pull request as ready for review August 27, 2025 18:47
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey there - I've reviewed your changes - here's some feedback:

  • Consider adding the target_shape equality early-return inside the resize_pil backend (and similarly in other direct backend functions) to ensure callers bypass unnecessary work when dimensions already match.
  • Instead of silently falling back to OpenCV when ALBUMENTATIONS_RESIZE is set to an unavailable backend, consider raising a configuration error or warning so users know their requested backend wasn't used.
  • Pillow’s interpolation enum values don’t align with OpenCV’s indices, so adding an explicit mapping or validating supported interpolation values can help avoid unexpected resize artifacts when switching backends.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Consider adding the target_shape equality early-return inside the resize_pil backend (and similarly in other direct backend functions) to ensure callers bypass unnecessary work when dimensions already match.
- Instead of silently falling back to OpenCV when ALBUMENTATIONS_RESIZE is set to an unavailable backend, consider raising a configuration error or warning so users know their requested backend wasn't used.
- Pillow’s interpolation enum values don’t align with OpenCV’s indices, so adding an explicit mapping or validating supported interpolation values can help avoid unexpected resize artifacts when switching backends.

## Individual Comments

### Comment 1
<location> `albumentations/augmentations/geometric/functional.py:354` </location>
<code_context>
+def resize_pil(
</code_context>

<issue_to_address>
Validate input image format for PIL compatibility.

Ensure the input array matches PIL's expected format, or add validation and conversion steps as needed.
</issue_to_address>

### Comment 2
<location> `albumentations/augmentations/geometric/functional.py:301` </location>
<code_context>
-
     height, width = img.shape[:2]
     target_height, target_width = target_shape
     original_dtype = img.dtype
</code_context>

<issue_to_address>
Restoring original dtype may cause issues for unsupported types.

Casting back to unsupported dtypes like int16 or float64 after resizing may corrupt data. Please restrict allowed dtypes or add a warning for unsupported types.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +354 to +363
def resize_pil(
img: np.ndarray,
target_shape: tuple[int, int],
interpolation: int,
) -> np.ndarray:
"""Resizes an image (NumPy array) using PIL's resize method.

This function resizes an input image to the target shape using the specified interpolation method.

Args:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: Validate input image format for PIL compatibility.

Ensure the input array matches PIL's expected format, or add validation and conversion steps as needed.

@@ -290,9 +296,6 @@
# At this stage, the library's installation and importability have already been verified.
import pyvips

if target_shape == img.shape[:2]:
return img

height, width = img.shape[:2]
target_height, target_width = target_shape
original_dtype = img.dtype
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Restoring original dtype may cause issues for unsupported types.

Casting back to unsupported dtypes like int16 or float64 after resizing may corrupt data. Please restrict allowed dtypes or add a warning for unsupported types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants