Skip to content

Request: Allow choosing the classification resize method (including non-antialiased bilinear) #936

Closed

Description

@ManuelZ

Hi,

Classification models resize with a hardcoded method, for MobileNetV4 it's bicubic interpolation through PIL, so when downscaling, the resize is Pillow's antialiased resampling. That's not so easy to reproduce outside Python, matching it exactly means reproducing Pillow's fixed-point resampling (libImaging/Resample.c).

  • TFLite only has RESIZE_BILINEAR and RESIZE_NEAREST_NEIGHBOR (both without antialiasing).
  • ONNX Resize supports antialias=1, but onnx2tf 2.6.9 drops it when converting to TFLite.
  • OpenCV's INTER_CUBIC uses a different coefficient and doesn't antialias.
  • Pillow's BILINEAR is also antialiased, so it still doesn't match RESIZE_BILINEAR.

Deployments on mobile, web or embedded would need to either carry a custom port of Pillow's resize or pass the model slightly different pixels than it was trained on.

Request

A setting that controls the resize used for training, validation, predict() and export metadata, and that's saved in the checkpoint. It could include an option matching common runtime ops, e.g. resizing on tensors with antialias=False, so training uses the same resize as the deployed model.

Thanks!

Activity

  1. EHxuban11 commented on Oct 17, 2026

    @EHxuban11
    Contributor

    Hello @ManuelZ , thank you for your detailed request!

    There was a bug with the interpolation setting and it's now fixed. I added the new value "bilinear_no_antialias" for a resize without antialiasing.

    You can use it like this:

    model = LibreMobileNetV4(size="s")
    model.interpolation = "bilinear_no_antialias"
    model.train(data="/path/to/imagefolder")

    All of this is in dev and here is the merged PR #942 . It will ship in the next version (v1.7.0) Let me know if this works for you.

    Thank you again!!!!

  2. added
    awaiting responseFix or answer given; waiting for the reporter to confirm
    and removed on Oct 21, 2026
  3. ManuelZ commented on Oct 25, 2026

    @ManuelZ
    Author

    Hi @EHxuban11, thank you very much! Sorry for the late reply.

    I ran a small resize test, these are the results:

    1. libreyolo
       pil_to_tensor        torch.uint8
       F.resize output      torch.uint8   (float32 inside, rounded back to the input dtype)
       final array          uint8
    2. cv2 uint8
       input                uint8
       output               uint8
    3. cv2 float32
       input                float32
       output               float32
    
    Whole image, absolute difference in grey levels (0-255):
      cv2 uint8  vs  libreyolo               max 1.0000   mean 0.0963   values not identical   9.63%
      cv2 float32  vs  libreyolo             max 0.5038   mean 0.1857   values not identical  74.56%
    

    So, at most 1 grey level of difference between how LibreYOLO resizes images and how a simple external resizing would look like. I don't know if this would have an impact at all, I guess not. I think the difference comes due to the rounding happening within torchvision's tensor resize.


    A small think I noticed that could mislead someone:

    class ResizeNoAntialias(transforms.Resize):
        """:class:`transforms.Resize` with bilinear and no antialiasing (#936)."""
    
        def __init__(self, size):
            super().__init__(size, interpolation=InterpolationMode.BILINEAR)  # THIS
    
        def forward(self, img):
            return _resize_no_antialias(img, self.size)
    

    sets self.interpolation and self.antialias in ResizeNoAntialias with the following values:

    self.interpolation = InterpolationMode.BILINEAR
    self.antialias = True  # notice this, it's using the default value of transforms.Resize
    

    Not a problem, since your overriden forward doesn't use self.antialias, but printing an instance of ResizeNoAntialias would show those attributes, potentially making someone think that ResizeNoAntialias is using antialiasing.

    I think it looks great, thank you!

  4. EHxuban11 commented on Oct 25, 2026

    @EHxuban11
    Contributor

    Thanks for testing @ManuelZ , I fixed the misleading antialis = True in #956

    And regarding the grey level difference it's rounding errors, it's fine.

    Best regards!

  5. removed
    awaiting responseFix or answer given; waiting for the reporter to confirm
    on Oct 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions