From 62fc6ed5a88862e9ba44ff01b05711dd60bb2aa5 Mon Sep 17 00:00:00 2001 From: liqun Fu Date: Mon, 1 May 2023 10:49:17 -0700 Subject: [PATCH] [Feature Request] Support Resize opset 19 (#15633) --- docs/OperatorKernels.md | 3 +- .../providers/cpu/cpu_execution_provider.cc | 34 +++++++++------ .../core/providers/cpu/tensor/resize.cc | 41 +++++++++++++++--- .../core/providers/cpu/tensor/upsamplebase.h | 15 ++++++- .../providers/cpu/tensor/resize_op_test.cc | 43 ++++++++++++++++++- 5 files changed, 114 insertions(+), 22 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 114ab09b5a..8427dfaef4 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -295,7 +295,8 @@ Do not modify directly.* |||13|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[5, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[1, 4]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Resize|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T1**
*in* roi:**T2**
*in* scales:**tensor(float)**
*in* sizes:**tensor(int64)**
*out* Y:**T1**|18+|**T1** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| +|Resize|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T1**
*in* roi:**T2**
*in* scales:**tensor(float)**
*in* sizes:**tensor(int64)**
*out* Y:**T1**|19+|**T1** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| +|||18|**T1** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| |||[13, 17]|**T1** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| |||[11, 12]|**T1** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| |||10|**T** = tensor(float), tensor(int32), tensor(int8), tensor(uint8)| diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index 8e1b412dd2..96f2590624 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -840,10 +840,10 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 17, double, LayerNormalization); // Opset 18 -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, float, Resize); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, int32_t, Resize); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, int8_t, Resize); -class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, uint8_t, Resize); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, 18, float, Resize); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, 18, int32_t, Resize); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, 18, int8_t, Resize); +class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, 18, uint8_t, Resize); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, float, ReduceL1); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, int32_t, ReduceL1); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, int64_t, ReduceL1); @@ -922,6 +922,11 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, Op class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 18, OptionalGetElement); #endif +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 19, float, Resize); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 19, int32_t, Resize); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 19, int8_t, Resize); +class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 19, uint8_t, Resize); + // !!PLEASE READ BELOW!! Following that, add new entries above this comment /* *** IMPORTANT! *** @@ -2175,15 +2180,14 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { LayerNormalization)>, // Opset 18 - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - BuildKernelCreateInfo, - + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, #endif + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, + BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { diff --git a/onnxruntime/core/providers/cpu/tensor/resize.cc b/onnxruntime/core/providers/cpu/tensor/resize.cc index fbe8076f4f..d092bfbd97 100644 --- a/onnxruntime/core/providers/cpu/tensor/resize.cc +++ b/onnxruntime/core/providers/cpu/tensor/resize.cc @@ -93,32 +93,63 @@ ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), Resize); -ONNX_CPU_OPERATOR_TYPED_KERNEL( +ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( Resize, 18, + 18, + float, + KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Resize); + +ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( + Resize, + 18, + 18, + int32_t, + KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Resize); + +ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( + Resize, + 18, + 18, + int8_t, + KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Resize); + +ONNX_CPU_OPERATOR_VERSIONED_TYPED_KERNEL( + Resize, + 18, + 18, + uint8_t, + KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), + Resize); + +ONNX_CPU_OPERATOR_TYPED_KERNEL( + Resize, + 19, float, KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), Resize); ONNX_CPU_OPERATOR_TYPED_KERNEL( Resize, - 18, + 19, int32_t, KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), Resize); ONNX_CPU_OPERATOR_TYPED_KERNEL( Resize, - 18, + 19, int8_t, KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), Resize); ONNX_CPU_OPERATOR_TYPED_KERNEL( Resize, - 18, + 19, uint8_t, KernelDefBuilder().TypeConstraint("T1", DataTypeImpl::GetTensorType()), Resize); - } // namespace onnxruntime diff --git a/onnxruntime/core/providers/cpu/tensor/upsamplebase.h b/onnxruntime/core/providers/cpu/tensor/upsamplebase.h index 72948ae263..c13c9d42dd 100644 --- a/onnxruntime/core/providers/cpu/tensor/upsamplebase.h +++ b/onnxruntime/core/providers/cpu/tensor/upsamplebase.h @@ -41,7 +41,7 @@ enum ResizeCoordinateTransformationMode { TF_HALF_PIXEL_FOR_NN = 3, ALIGN_CORNERS = 4, TF_CROP_AND_RESIZE = 5, - CoordinateTransformationModeCount = 6, + HALF_PIXEL_SYMMETRIC = 6, }; enum ResizeNearestMode { @@ -50,7 +50,6 @@ enum ResizeNearestMode { ROUND_PREFER_CEIL = 2, FLOOR = 3, CEIL = 4, - NearestModeCount = 5, }; enum class AspectRatioPolicy { @@ -237,6 +236,9 @@ class UpsampleBase { if (coordinate_transform_mode_name == "half_pixel") { return HALF_PIXEL; } + if (coordinate_transform_mode_name == "half_pixel_symmetric") { + return HALF_PIXEL_SYMMETRIC; + } ORT_THROW("coordinate_transform_mode:[" + coordinate_transform_mode_name + "] is not supportted!"); } @@ -267,6 +269,15 @@ class UpsampleBase { : 0.5 * (roi_start + roi_end) * (length_original - 1); return static_cast(orig); }; + case HALF_PIXEL_SYMMETRIC: + return [](float x_resized, float x_scale, float length_resized, float length_original, float, float) { + float output_width = x_scale * length_original; + float adjustment = length_resized / output_width; + float center = length_original / 2; + float offset = center * (1 - adjustment); + auto orig = offset + (x_resized + 0.5) / x_scale - 0.5; + return static_cast(orig); + }; default: // "half_pixel" return [](float x_resized, float x_scale, float, float, float, float) { return ((x_resized + 0.5f) / x_scale) - 0.5f; diff --git a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc index 25d1acbbd6..832a8a744c 100644 --- a/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc +++ b/onnxruntime/test/providers/cpu/tensor/resize_op_test.cc @@ -1772,6 +1772,48 @@ TEST(ResizeOpTest, ResizeOpTypeCheck_Ver18) { ResizeOpTypeCheck_Ver_11_13_18(18); } +TEST(ResizeOpTest, ResizeOpHalfPixelSymmetricDownSample_ver19) { + OpTester test("Resize", 19); + test.AddAttribute("mode", "linear"); + test.AddAttribute("coordinate_transformation_mode", "half_pixel_symmetric"); + + constexpr int64_t N = 1, C = 1, H = 1, W = 4; + std::vector X = {1.0f, 2.0f, 3.0f, 4.0f}; + test.AddInput("X", {N, C, H, W}, X); + std::vector roi{}; + test.AddInput("roi", {0}, roi); + std::vector scales{1.0f, 1.0f, 1.0f, 0.6f}; + test.AddInput("scales", {4}, scales); + + std::vector Y = {1.666667f, 3.333333f}; + + test.AddOutput("Y", {N, C, static_cast(H * scales[2]), static_cast(W * scales[3])}, Y); + test.Run(); +} + +TEST(ResizeOpTest, ResizeOpHalfPixelSymmetricUpSample_ver19) { + OpTester test("Resize", 19); + test.AddAttribute("mode", "linear"); + test.AddAttribute("coordinate_transformation_mode", "half_pixel_symmetric"); + + constexpr int64_t N = 1, C = 1, H = 2, W = 2; + std::vector X = {1.0f, 2.0f, 3.0f, 4.0f}; + + test.AddInput("X", {N, C, H, W}, X); + std::vector roi{}; + test.AddInput("roi", {0}, roi); + std::vector scales{1.0f, 1.0f, 2.3f, 2.94f}; + test.AddInput("scales", {4}, scales); + + std::vector Y = {1.0f, 1.159864f, 1.5f, 1.840136f, 2.0f, + 1.565217f, 1.725081f, 2.065217f, 2.405353f, 2.565217f, + 2.434782f, 2.594647f, 2.934783f, 3.274919f, 3.434783f, + 3.0f, 3.159864f, 3.5f, 3.840136f, 4.0f}; + + test.AddOutput("Y", {N, C, static_cast(H * scales[2]), static_cast(W * scales[3])}, Y); + test.Run(); +} + /* * Most of TestCase against Anti-aliasing will have the attribute of "exclude_outside" as 1. * It's as Pillow 's Resize is corresponding to ONNX op with exclude_outside equaling 1. @@ -2186,6 +2228,5 @@ TEST(ResizeOpTest, Antialias_Use_Extrapolation) { }, {4, 4, 4}, X, {3, 3, 3}, Y); } - } // namespace test } // namespace onnxruntime