Skip to content

Conversation

jantonguirao
Copy link
Contributor

@jantonguirao jantonguirao commented Apr 11, 2022

Signed-off-by: Joaquin Anton janton@nvidia.com

Description
This PR extends Resize with new functionality:

  • New boolean parameter antialias, which enables an antialiasing filter when downscaling with linear and cubic interpolation modes.

  • New axes argument, allowing to select a subset of dimensions that sizes, roi and scales refer to.

  • New keep_aspect_ratio_policy argument, determining how to interpret the value of sizes. Three policies supported:

    • "stretch" (default): The output is resized to the target size, disregarding the original aspect ratio
    • "not_larger" : The output is resized so that no extent is larger than the provided size, while keeping its aspect ratio
    • "not_smaller" : The output is resized so that no extent is smaller than the provided size, while keeping its aspect ratio

Motivation and Context

  • Why is this change required? What problem does it solve?
  • Some libraries apply a downscaling antialiasing (e.g. PIL) while others don't (e.g. OpenCV). Having such an option allows the user to be aligned with either. This options will be crucial to be able to port the data preprocessing pipeline from image classification models (resnet), which is currently described as a Python function using PIL resize. For more background see: https://github.com/onnx/working-groups/blob/main/preprocessing/notebooks/resize-antialias/resize-antialias.ipynb
  • Previous version of resize forces the user to provide a scale or extent for dimensions that are not meant to be resize. This makes it hard to use in some contexts, such as image resize, where the "channel" dimension should not be resized.
  • Resizing data while keeping aspect ratio is currently hard to achieve, requiring a complicated pipeline for a trivial and quite common operation. We can benefit to have such "keep aspect ratio" semantics, for example for image vision applications.

@jantonguirao jantonguirao requested review from a team as code owners April 11, 2022 07:05
@jantonguirao jantonguirao changed the title [WIP] Add Resize-16: Antialiasing filter Add Resize-16: Antialiasing filter Apr 11, 2022
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao changed the title Add Resize-16: Antialiasing filter Add Resize-117: Antialiasing filter Apr 13, 2022
@jantonguirao jantonguirao changed the title Add Resize-117: Antialiasing filter Add Resize-17: Antialiasing filter Apr 13, 2022
@gramalingam gramalingam added the topic: operator Issues related to ONNX operators label Apr 26, 2022
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao force-pushed the resize_16 branch 8 times, most recently from d119e54 to e50bcf6 Compare May 2, 2022 16:46
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao changed the title Add Resize-17: Antialiasing filter Add Resize-17: Antialiasing, axes and keep_aspect_ratio_policy May 2, 2022
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
AttributeProto::STRING,
std::string("round_prefer_floor"))
.Attr(
"extrapolation_value",
"When coordinate_transformation_mode is \"tf_crop_and_resize\" and x_original is outside the range [0, length_original - 1], this value is used as the corresponding output value. Default is 0.0f.",
AttributeProto::FLOAT,
static_cast<float>(0))
.Attr(
"antialias",
"If set to 1, \"linear\" and \"cubic\" interpolation modes will use an antialiasing filter when downscaling. "
Copy link

Choose a reason for hiding this comment

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

This wording is likely to go stale when a new interpolation method is added. We could say that it is not applicable to "nearest" interpolation method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is true. On the other hand, there is a chance that a new interpolation method is added that doesn't support antialiasing.

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Comment on lines 59 to 67
def round_half_up(x: float) -> int:
"""
Computes the nearest integer value, rounding halfway cases up
"""
fractional = x - int(x)
if fractional == 0.5:
return int(x) + 1
else:
return round(x)
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this function necessary? Unless you are going for very explicit and clear code, the same could be acheived by int(x + 0.5), maybe enclosed in a lambda.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point. I'll take your suggestion

<dt><tt>antialias</tt> : int (default is 0)</dt>
<dd>If set to 1, "linear" and "cubic" interpolation modes will use an antialiasing filter when downscaling. Antialiasing is achieved by stretching the resampling filter by a factor max(1, 1 / scale), which means that when downsampling, more input pixels contribute to an output pixel.</dd>
<dt><tt>axes</tt> : list of ints</dt>
<dd>If provided, it specifies a subset of axes that 'roi', 'scales' and 'sizes' refer to. If not provided, all axes are assumed [0, 1, ..., r-1], where r = rank(data). Non-specified dimensions are interpreted as non-resizable. Negative value means counting dimensions from the back. Accepted range is [-r, r-1], where r = rank(data). Behavior is undefined if an axis is repeated.</dd>
Copy link
Contributor

Choose a reason for hiding this comment

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

The user could be notified about a possible undefined behaviour. Maybe throwing an error (like when both scales and sizes are given in Inputs) or giving a warning would be beneficial?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've added some more error checking

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
…xel_for_nn

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao jantonguirao changed the title Add Resize-17: Antialiasing, axes and keep_aspect_ratio_policy Add Resize-18: Antialiasing, axes and keep_aspect_ratio_policy Jun 22, 2022
@yuanyao-nv
Copy link
Contributor

Should we be more precise in the ONNX spec about what antialias filter to use for various interpolation methods? For example, by giving the precise mathematical formula in cases of possible ambiguity.

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
@jantonguirao
Copy link
Contributor Author

jantonguirao commented Jun 27, 2022

Should we be more precise in the ONNX spec about what antialias filter to use for various interpolation methods? For example, by giving the precise mathematical formula in cases of possible ambiguity.

@yuanyao-nv There is this definition:

Antialiasing is achieved by stretching the resampling filter by a factor max(1, 1 / scale), which means that when downsampling, more input pixels contribute to an output pixel.

which is basically extending the neighborhood region by the inverse of the scale factor, resampling the interpolation filter weights accordingly. Do you think we should phrase it differently?

Regarding being mathematically explicit, the formulas are in resize.py (cubic_coeffs_antialias, linear_coeffs_antialias). I feel that to express it mathematically in the documentation, we would need to also express all the formulas for the different interpolation methods with all the variants, which might be hard to do concisely

@yuanyao-nv
Copy link
Contributor

Thanks for the reply @jantonguirao .
Do you know if this is the same antialias definition used in TensorFlow and PyTorch ? In the TF definition, they mention some hat/tent filter for bilinear.

@jantonguirao
Copy link
Contributor Author

jantonguirao commented Jun 29, 2022

Thanks for the reply @jantonguirao . Do you know if this is the same antialias definition used in TensorFlow and PyTorch ? In the TF definition, they mention some hat/tent filter for bilinear.

It seems to be the same filter as those two frameworks.

Regarding Tensorflow:
becomes a hat/tent filter function with radius 1 when downsampling.
Yes, this is the same filter. Also known as triangular filter.

Regarding Pytorch:
They mention being close to what PIL does. PIL applies antialiasing with the same approach as I am suggesting here. This is a triangular filter for the case of bilinear interpolation.

I made a demo comparing this proposal against OpenCV (no antialiasing) and Pillow (antialiasing): Notebook here. As you can see, the formulas I am proposing match what Pillow is doing.

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
Signed-off-by: Joaquin Anton <janton@nvidia.com>
bool hasSizesInput = (3 < ctx.getNumInputs()) && (ctx.getInputType(3) != nullptr);

if (hasScalesInput + hasSizesInput != 1) {
fail_shape_inference("Either `sizes` or `scales` must be provided, but not both of them");
Copy link
Member

Choose a reason for hiding this comment

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

FYI this line causes shape inference failures with some of ONNX Model Zoo models. Please check this issue: #4380. Thanks!

broune pushed a commit to broune/onnx that referenced this pull request May 6, 2023
…4126)

* [WIP] Add Resize-16: Antialiasing filter

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Update to version 17

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Add 'keep_aspect_ratio_policy' and 'axes'

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Add shape inference implementation

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Fix version converter

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Workaround windows build issue

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Fixes

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Code review fixes

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Apply code review suggestions

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Move new Resize to opset 18

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Correct error checking

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Adjust converter to opset 18

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Update DomainToVersionRange

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Apply clang-format

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Fix shape inference test

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Fix flake8 issue

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Delete generated test test_resize_downsample_sizes_nearest_tf_half_pixel_for_nn

Signed-off-by: Joaquin Anton <janton@nvidia.com>

* Check for repeated axes

Signed-off-by: Joaquin Anton <janton@nvidia.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic: operator Issues related to ONNX operators
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants