| @@ -17,8 +17,10 @@ | |||
| #include "nnacl/fp32/resize_fp32.h" | |||
| #include "nnacl/common_func.h" | |||
| #include "nnacl/errorcode.h" | |||
| int PrepareResizeBilinear(const int *input_shape, const int *output_shape, bool align_corners, int *y_bottoms, | |||
| int *y_tops, int *x_lefts, int *x_rights, float *y_bottom_weights, float *x_left_weights) { | |||
| int PrepareResizeBilinear(const int *input_shape, const int *output_shape, CalculateOriginalCoordinate calculate, | |||
| int *y_bottoms, int *y_tops, int *x_lefts, int *x_rights, float *y_bottom_weights, | |||
| float *x_left_weights) { | |||
| if (input_shape == NULL || output_shape == NULL || y_bottoms == NULL || y_tops == NULL || x_lefts == NULL || | |||
| x_rights == NULL || y_bottom_weights == NULL || x_left_weights == NULL) { | |||
| return NNACL_NULL_PTR; | |||
| @@ -29,18 +31,10 @@ int PrepareResizeBilinear(const int *input_shape, const int *output_shape, bool | |||
| int new_height = output_shape[1]; | |||
| int new_width = output_shape[2]; | |||
| float height_scale = (float)(in_h) / new_height; | |||
| float width_scale = (float)(in_w) / new_width; | |||
| if (align_corners && new_height > 1) { | |||
| height_scale = (float)(in_h - 1) / (new_height - 1); | |||
| } | |||
| if (align_corners && new_width > 1) { | |||
| width_scale = (float)(in_w - 1) / (new_width - 1); | |||
| } | |||
| int h, w; | |||
| for (h = 0; h < new_height; h++) { | |||
| float actual_y = (float)h * height_scale; | |||
| float actual_y = calculate(h, in_h, new_height); | |||
| int y_bottom = (int)(floor(actual_y)); | |||
| int y_top = y_bottom + 1 < in_h ? (y_bottom + 1) : (in_h - 1); | |||
| float y_top_weight = actual_y - (float)(y_bottom); | |||
| @@ -51,7 +45,7 @@ int PrepareResizeBilinear(const int *input_shape, const int *output_shape, bool | |||
| y_bottom_weights[h] = y_bottom_weight; | |||
| } | |||
| for (w = 0; w < new_width; w++) { | |||
| float actual_x = (float)(w)*width_scale; | |||
| float actual_x = calculate(w, in_w, new_width); | |||
| int x_left = (int)(floor(actual_x)); | |||
| int x_right = x_left + 1 < in_w ? (x_left + 1) : (in_w - 1); | |||
| float x_right_weight = actual_x - (float)(x_left); | |||
| @@ -64,96 +58,6 @@ int PrepareResizeBilinear(const int *input_shape, const int *output_shape, bool | |||
| return NNACL_OK; | |||
| } | |||
| int ResizeBilinear(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| const int *y_bottoms, const int *y_tops, const int *x_lefts, const int *x_rights, | |||
| const float *y_bottom_weights, const float *x_left_weights, const int n_h_begin, const int n_h_end) { | |||
| if (input_data == NULL || output_data == NULL || input_shape == NULL || output_shape == NULL || y_bottoms == NULL || | |||
| y_tops == NULL || x_lefts == NULL || x_rights == NULL || y_bottom_weights == NULL || x_left_weights == NULL) { | |||
| return NNACL_NULL_PTR; | |||
| } | |||
| int in_w = input_shape[2]; | |||
| int in_c = input_shape[3]; | |||
| int new_height = output_shape[1]; | |||
| int new_width = output_shape[2]; | |||
| int n_h, n, h, w, c; | |||
| n = n_h_begin / new_height; | |||
| h = n_h_begin % new_height; | |||
| int n_h_stride = new_width * in_c; | |||
| int out_offset = n_h_begin * n_h_stride; | |||
| for (n_h = n_h_begin; n_h < n_h_end; n_h++, h++) { | |||
| if (h == new_height) { | |||
| h = 0; | |||
| n++; | |||
| } | |||
| int y_bottom = y_bottoms[h]; | |||
| int y_top = y_tops[h]; | |||
| float y_bottom_weight = y_bottom_weights[h]; | |||
| const float y_top_weight = 1.0f - y_bottom_weight; | |||
| for (w = 0; w < new_width; w++) { | |||
| int x_left = x_lefts[w]; | |||
| int x_right = x_rights[w]; | |||
| float x_left_weight = x_left_weights[w]; | |||
| const float x_right_weight = 1.0f - x_left_weight; | |||
| float top_left_weight = y_top_weight * x_left_weight; | |||
| float top_right_weight = y_top_weight * x_right_weight; | |||
| float bottom_left_weight = y_bottom_weight * x_left_weight; | |||
| float bottom_right_weight = y_bottom_weight * x_right_weight; | |||
| c = 0; | |||
| int in_bottom_left_offset = offset(input_shape, n, y_bottom, x_left, c); | |||
| int in_bottom_right_offset = in_bottom_left_offset + (x_right - x_left) * in_c; | |||
| int in_top_left_offset = in_bottom_left_offset + (y_top - y_bottom) * in_w * in_c; | |||
| int in_top_right_offset = in_bottom_right_offset + (y_top - y_bottom) * in_w * in_c; | |||
| #ifdef ENABLE_NEON | |||
| float32x4_t top_left_w = vdupq_n_f32(top_left_weight); | |||
| float32x4_t top_right_w = vdupq_n_f32(top_right_weight); | |||
| float32x4_t bottom_left_w = vdupq_n_f32(bottom_left_weight); | |||
| float32x4_t bottom_right_w = vdupq_n_f32(bottom_right_weight); | |||
| for (; c <= in_c - 4; c += 4) { | |||
| float32x4_t bottom_left = vld1q_f32(input_data + in_bottom_left_offset + c); | |||
| float32x4_t bottom_right = vld1q_f32(input_data + in_bottom_right_offset + c); | |||
| float32x4_t top_left = vld1q_f32(input_data + in_top_left_offset + c); | |||
| float32x4_t top_right = vld1q_f32(input_data + in_top_right_offset + c); | |||
| float32x4_t interp_value = vdupq_n_f32(0.0); | |||
| float32x4_t tmp = vmulq_f32(bottom_left, bottom_left_w); | |||
| interp_value = vaddq_f32(interp_value, tmp); | |||
| tmp = vmulq_f32(bottom_right, bottom_right_w); | |||
| interp_value = vaddq_f32(interp_value, tmp); | |||
| tmp = vmulq_f32(top_left, top_left_w); | |||
| interp_value = vaddq_f32(interp_value, tmp); | |||
| tmp = vmulq_f32(top_right, top_right_w); | |||
| interp_value = vaddq_f32(interp_value, tmp); | |||
| vst1q_f32(output_data + out_offset, interp_value); | |||
| out_offset += 4; | |||
| } | |||
| #endif | |||
| for (; c < in_c; c++) { | |||
| float bottom_left = input_data[in_bottom_left_offset + c]; | |||
| float bottom_right = input_data[in_bottom_right_offset + c]; | |||
| float top_left = input_data[in_top_left_offset + c]; | |||
| float top_right = input_data[in_top_right_offset + c]; | |||
| float interp_value = bottom_left * bottom_left_weight + bottom_right * bottom_right_weight + | |||
| top_left * top_left_weight + top_right * top_right_weight; | |||
| output_data[out_offset] = interp_value; | |||
| out_offset++; | |||
| } | |||
| } | |||
| } | |||
| return NNACL_OK; | |||
| } | |||
| int InterpRow(const float *src_line, float *linear_output, int new_width, const float *x_left_weights, | |||
| const int *x_lefts, const int *x_rights, int in_c) { | |||
| int w; | |||
| @@ -207,10 +111,10 @@ int InterpCol(const float *bottom_line, const float *top_line, float *output, in | |||
| return 0; | |||
| } | |||
| int ResizeBilinear2(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| const int *y_bottoms, const int *y_tops, const int *x_lefts, const int *x_rights, | |||
| const float *y_bottom_weights, const float *x_left_weights, float *line0, float *line1, | |||
| const int n_h_begin, const int n_h_end) { | |||
| int ResizeBilinear(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| const int *y_bottoms, const int *y_tops, const int *x_lefts, const int *x_rights, | |||
| const float *y_bottom_weights, const float *x_left_weights, float *line0, float *line1, | |||
| const int n_h_begin, const int n_h_end) { | |||
| if (input_data == NULL || output_data == NULL || input_shape == NULL || output_shape == NULL || y_bottoms == NULL || | |||
| y_tops == NULL || x_lefts == NULL || x_rights == NULL || y_bottom_weights == NULL || x_left_weights == NULL) { | |||
| return NNACL_NULL_PTR; | |||
| @@ -278,36 +182,29 @@ int ResizeBilinear2(const float *input_data, float *output_data, const int *inpu | |||
| return NNACL_OK; | |||
| } | |||
| int CalcNearestNeighbor(const int out_position, const int in_size, const float scale, const bool align_corners) { | |||
| int actual_v; | |||
| if (align_corners) { | |||
| actual_v = (int)(round((float)out_position * scale)); | |||
| } else { | |||
| actual_v = (int)(floor((float)out_position * scale)); | |||
| } | |||
| int input_position = actual_v < in_size ? actual_v : in_size - 1; | |||
| return input_position; | |||
| } | |||
| int ResizeNearestNeighbor(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| bool align_corners, int tid, int thread_num) { | |||
| CalculateOriginalCoordinate calculate, int coordinate_transform_mode, int tid, | |||
| int thread_num) { | |||
| int batch, y, x, c; | |||
| c = input_shape[3]; | |||
| float height_scale = (float)(input_shape[1]) / (float)(output_shape[1]); | |||
| float width_scale = (float)(input_shape[2]) / (float)(output_shape[2]); | |||
| if (align_corners && output_shape[1] > 1) { | |||
| height_scale = (float)(input_shape[1] - 1) / (output_shape[1] - 1); | |||
| } | |||
| if (align_corners && output_shape[2] > 1) { | |||
| width_scale = (float)(input_shape[2] - 1) / (output_shape[2] - 1); | |||
| } | |||
| bool align_corners = coordinate_transform_mode == 1; | |||
| for (batch = 0; batch < output_shape[0]; batch++) { | |||
| for (y = tid; y < output_shape[1]; y += thread_num) { | |||
| int input_y = CalcNearestNeighbor(y, input_shape[1], height_scale, align_corners); | |||
| float actual_y = calculate(y, input_shape[1], output_shape[1]); | |||
| int input_y; | |||
| if (align_corners) { | |||
| input_y = (int)(round(actual_y)); | |||
| } else { | |||
| input_y = (int)(floor(actual_y)); | |||
| } | |||
| for (x = 0; x < output_shape[2]; x++) { | |||
| int input_x = CalcNearestNeighbor(x, input_shape[2], width_scale, align_corners); | |||
| float actual_x = calculate(x, input_shape[2], output_shape[2]); | |||
| int input_x; | |||
| if (align_corners) { | |||
| input_x = (int)(round(actual_x)); | |||
| } else { | |||
| input_x = (int)(floor(actual_x)); | |||
| } | |||
| int in_offset = offset(input_shape, batch, input_y, input_x, 0); | |||
| int out_offset = offset(output_shape, batch, y, x, 0); | |||
| memcpy(output_data + out_offset, input_data + in_offset, c * sizeof(float)); | |||
| @@ -317,3 +214,19 @@ int ResizeNearestNeighbor(const float *input_data, float *output_data, const int | |||
| return NNACL_OK; | |||
| } | |||
| float CalculateAsymmetric(int x_resized, int length_original, int length_resized) { | |||
| float scale = (float)(length_resized) / length_original; | |||
| return (float)(x_resized) / scale; | |||
| } | |||
| float CalculateAlignCorners(int x_resized, int length_original, int length_resized) { | |||
| float scale = (float)(length_resized - 1) / (length_original - 1); | |||
| return (float)(x_resized) / scale; | |||
| } | |||
| float CalculateHalfPixel(int x_resized, int length_original, int length_resized) { | |||
| float scale = (float)(length_resized) / length_original; | |||
| float actual = (float)(x_resized + 0.5) / scale - 0.5; | |||
| return actual > 0 ? actual : 0; | |||
| } | |||
| @@ -25,21 +25,27 @@ | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| typedef float (*CalculateOriginalCoordinate)(int x_resized, int length_original, int length_resized); | |||
| int PrepareResizeBilinear(const int *input_shape, const int *output_shape, bool align_corners, int *y_bottoms, | |||
| int *y_tops, int *x_lefts, int *x_rights, float *y_bottom_weights, float *x_left_weights); | |||
| int PrepareResizeBilinear(const int *input_shape, const int *output_shape, CalculateOriginalCoordinate calculate, | |||
| int *y_bottoms, int *y_tops, int *x_lefts, int *x_rights, float *y_bottom_weights, | |||
| float *x_left_weights); | |||
| int ResizeBilinear(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| const int *y_bottoms, const int *y_tops, const int *x_lefts, const int *x_rights, | |||
| const float *y_bottom_weights, const float *x_left_weights, const int n_h_begin, const int n_h_end); | |||
| int ResizeBilinear2(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| const int *y_bottoms, const int *y_tops, const int *x_lefts, const int *x_rights, | |||
| const float *y_bottom_weights, const float *x_left_weights, float *line0, float *line1, | |||
| const int n_h_begin, const int n_h_end); | |||
| const float *y_bottom_weights, const float *x_left_weights, float *line0, float *line1, | |||
| const int n_h_begin, const int n_h_end); | |||
| int ResizeNearestNeighbor(const float *input_data, float *output_data, const int *input_shape, const int *output_shape, | |||
| bool align_corners, int tid, int thread_num); | |||
| CalculateOriginalCoordinate calculate, int coordinate_transform_mode, int tid, | |||
| int thread_num); | |||
| float CalculateAsymmetric(int x_resized, int length_original, int length_resized); | |||
| float CalculateAlignCorners(int x_resized, int length_original, int length_resized); | |||
| float CalculateHalfPixel(int x_resized, int length_original, int length_resized); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| @@ -23,7 +23,7 @@ typedef struct ResizeParameter { | |||
| int method_; | |||
| int64_t new_height_; | |||
| int64_t new_width_; | |||
| bool align_corners_; | |||
| int coordinate_transform_mode_; | |||
| bool preserve_aspect_ratio_; | |||
| } ResizeParameter; | |||
| #endif // MINDSPORE_LITE_NNACL_RESIZE_PARAMETER_H_ | |||
| @@ -24,14 +24,10 @@ enum ResizeMethod: byte { | |||
| } | |||
| enum CoordinateTransformMode: byte { | |||
| COMMON = 0, | |||
| HALF_PIXEL = 1, | |||
| PYTORCH_HALF_PIXEL = 2, | |||
| TF_HALF_PIXEL = 3, | |||
| TF_CROP_AND_RESIZE = 4, | |||
| ALIGN_CORNERS = 5, | |||
| ASYMMETRIC = 6, | |||
| ALIGN_CORNERS_WITH_HALF_PIEXL = 7 | |||
| ASYMMETRIC = 0, | |||
| ALIGN_CORNERS = 1, | |||
| HALF_PIXEL = 2, | |||
| CROP_AND_RESIZE = 3 | |||
| } | |||
| enum NearestMode : byte { | |||
| @@ -34,7 +34,7 @@ OpParameter *PopulateResizeParameter(const mindspore::lite::PrimitiveC *primitiv | |||
| resize_param->method_ = static_cast<int>(param->GetMethod()); | |||
| resize_param->new_height_ = param->GetNewHeight(); | |||
| resize_param->new_width_ = param->GetNewWidth(); | |||
| resize_param->align_corners_ = param->GetAlignCorners(); | |||
| resize_param->coordinate_transform_mode_ = param->GetCoordinateTransformMode(); | |||
| resize_param->preserve_aspect_ratio_ = param->GetPreserveAspectRatio(); | |||
| return reinterpret_cast<OpParameter *>(resize_param); | |||
| } | |||
| @@ -27,14 +27,17 @@ int Resize::GetFormat() const { return this->primitive_->value.AsResize()->forma | |||
| int Resize::GetMethod() const { return this->primitive_->value.AsResize()->method; } | |||
| int64_t Resize::GetNewHeight() const { return this->primitive_->value.AsResize()->newHeight; } | |||
| int64_t Resize::GetNewWidth() const { return this->primitive_->value.AsResize()->newWidth; } | |||
| bool Resize::GetAlignCorners() const { return this->primitive_->value.AsResize()->alignCorners; } | |||
| bool Resize::GetPreserveAspectRatio() const { return this->primitive_->value.AsResize()->preserveAspectRatio; } | |||
| int Resize::GetCoordinateTransformMode() const { return this->primitive_->value.AsResize()->coordinateTransformMode; } | |||
| void Resize::SetFormat(int format) { this->primitive_->value.AsResize()->format = (schema::Format)format; } | |||
| void Resize::SetMethod(int method) { this->primitive_->value.AsResize()->method = (schema::ResizeMethod)method; } | |||
| void Resize::SetNewHeight(int64_t new_height) { this->primitive_->value.AsResize()->newHeight = new_height; } | |||
| void Resize::SetNewWidth(int64_t new_width) { this->primitive_->value.AsResize()->newWidth = new_width; } | |||
| void Resize::SetAlignCorners(bool align_corners) { this->primitive_->value.AsResize()->alignCorners = align_corners; } | |||
| void Resize::SetCoordinateTransformMode(int coordinate_transform_mode) { | |||
| this->primitive_->value.AsResize()->coordinateTransformMode = | |||
| static_cast<schema::CoordinateTransformMode>(coordinate_transform_mode); | |||
| } | |||
| void Resize::SetPreserveAspectRatio(bool preserve_aspect_ratio) { | |||
| this->primitive_->value.AsResize()->preserveAspectRatio = preserve_aspect_ratio; | |||
| } | |||
| @@ -71,7 +74,9 @@ int Resize::UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inp | |||
| attr->newHeight = targetSize.at(0); | |||
| attr->newWidth = targetSize.at(1); | |||
| attr->alignCorners = GetValue<bool>(prim.GetAttr("align_corners")); | |||
| if (attr->alignCorners) { | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ALIGN_CORNERS; | |||
| } | |||
| this->primitive_->value.value = attr; | |||
| if (this->primitive_->value.value == nullptr) { | |||
| if (attr != nullptr) { | |||
| @@ -89,7 +94,9 @@ int Resize::GetFormat() const { return this->primitive_->value_as_Resize()->form | |||
| int Resize::GetMethod() const { return this->primitive_->value_as_Resize()->method(); } | |||
| int64_t Resize::GetNewHeight() const { return this->primitive_->value_as_Resize()->newHeight(); } | |||
| int64_t Resize::GetNewWidth() const { return this->primitive_->value_as_Resize()->newWidth(); } | |||
| bool Resize::GetAlignCorners() const { return this->primitive_->value_as_Resize()->alignCorners(); } | |||
| int Resize::GetCoordinateTransformMode() const { | |||
| return this->primitive_->value_as_Resize()->coordinateTransformMode(); | |||
| } | |||
| bool Resize::GetPreserveAspectRatio() const { return this->primitive_->value_as_Resize()->preserveAspectRatio(); } | |||
| int Resize::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) { | |||
| MS_ASSERT(nullptr != primitive); | |||
| @@ -99,8 +106,10 @@ int Resize::UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers: | |||
| MS_LOG(ERROR) << "value_as_Resize return nullptr"; | |||
| return RET_ERROR; | |||
| } | |||
| auto val_offset = schema::CreateResize(*fbb, attr->format(), attr->method(), attr->newHeight(), attr->newWidth(), | |||
| attr->alignCorners(), attr->preserveAspectRatio()); | |||
| auto val_offset = | |||
| schema::CreateResize(*fbb, attr->format(), attr->method(), attr->newHeight(), attr->newWidth(), | |||
| attr->alignCorners(), attr->preserveAspectRatio(), attr->coordinateTransformMode(), | |||
| attr->cubicCoeff(), attr->excludeOutside(), attr->extrapolationValue(), attr->nearestMode()); | |||
| auto prim_offset = schema::CreatePrimitive(*fbb, schema::PrimitiveType_Resize, val_offset.o); | |||
| fbb->Finish(prim_offset); | |||
| return RET_OK; | |||
| @@ -153,12 +162,12 @@ int Resize::InferShape(std::vector<lite::Tensor *> inputs_, std::vector<lite::Te | |||
| } | |||
| switch (shape_tensor->format()) { | |||
| case schema::Format_NCHW: | |||
| output_shape.push_back(data[2] * input->Height()); | |||
| output_shape.push_back(data[3] * input->Width()); | |||
| output_shape.push_back(data[2]); | |||
| output_shape.push_back(data[3]); | |||
| break; | |||
| case schema::Format_NHWC: | |||
| output_shape.push_back(data[1] * input->Height()); | |||
| output_shape.push_back(data[2] * input->Width()); | |||
| output_shape.push_back(data[1]); | |||
| output_shape.push_back(data[2]); | |||
| break; | |||
| default: | |||
| MS_LOG(INFO) << "Resize don't support tensor format."; | |||
| @@ -36,8 +36,8 @@ class Resize : public PrimitiveC { | |||
| void SetMethod(int method); | |||
| void SetNewHeight(int64_t new_height); | |||
| void SetNewWidth(int64_t new_width); | |||
| void SetAlignCorners(bool align_corners); | |||
| void SetPreserveAspectRatio(bool preserve_aspect_ratio); | |||
| void SetCoordinateTransformMode(int coordinate_transform_mode); | |||
| int UnPackAttr(const Primitive &prim, const std::vector<AnfNodePtr> &inputs); | |||
| #else | |||
| int UnPackToFlatBuilder(const schema::Primitive *primitive, flatbuffers::FlatBufferBuilder *fbb) override; | |||
| @@ -47,8 +47,8 @@ class Resize : public PrimitiveC { | |||
| int GetMethod() const; | |||
| int64_t GetNewHeight() const; | |||
| int64_t GetNewWidth() const; | |||
| bool GetAlignCorners() const; | |||
| bool GetPreserveAspectRatio() const; | |||
| int GetCoordinateTransformMode() const; | |||
| }; | |||
| } // namespace lite | |||
| } // namespace mindspore | |||
| @@ -42,7 +42,7 @@ int Shape::InferShape(std::vector<Tensor *> inputs_, std::vector<Tensor *> outpu | |||
| auto in_tensor = inputs_.front(); | |||
| auto out_tensor = outputs_.front(); | |||
| out_tensor->set_data_type(kNumberTypeInt32); | |||
| out_tensor->set_format(schema::Format::Format_NHWC); | |||
| out_tensor->set_format(in_tensor->format()); | |||
| if (!infer_flag()) { | |||
| return RET_INFER_INVALID; | |||
| } | |||
| @@ -75,9 +75,9 @@ int ResizeBaseCPUKernel::CheckParameters() { | |||
| const_shape_ = true; | |||
| } | |||
| } | |||
| align_corners_ = parameter->align_corners_; | |||
| preserve_aspect_ratio = parameter->preserve_aspect_ratio_; | |||
| if (preserve_aspect_ratio) { | |||
| coordinate_transform_mode_ = parameter->coordinate_transform_mode_; | |||
| preserve_aspect_ratio_ = parameter->preserve_aspect_ratio_; | |||
| if (preserve_aspect_ratio_) { | |||
| MS_LOG(ERROR) << "Resize currently not support preserve_aspect_ratio true"; | |||
| return RET_ERROR; | |||
| } | |||
| @@ -40,8 +40,8 @@ class ResizeBaseCPUKernel : public LiteKernel { | |||
| int method_ = 0; | |||
| int64_t new_height_ = 0; | |||
| int64_t new_width_ = 0; | |||
| bool align_corners_ = false; | |||
| bool preserve_aspect_ratio = false; | |||
| int coordinate_transform_mode_; | |||
| bool preserve_aspect_ratio_ = false; | |||
| bool const_shape_ = false; | |||
| private: | |||
| @@ -30,6 +30,21 @@ using mindspore::schema::PrimitiveType_Resize; | |||
| namespace mindspore::kernel { | |||
| int ResizeCPUKernel::Init() { | |||
| auto ret = ResizeBaseCPUKernel::Init(); | |||
| switch (coordinate_transform_mode_) { | |||
| case schema::CoordinateTransformMode_ASYMMETRIC: | |||
| calculate_ = CalculateAsymmetric; | |||
| break; | |||
| case schema::CoordinateTransformMode_ALIGN_CORNERS: | |||
| calculate_ = CalculateAlignCorners; | |||
| break; | |||
| case schema::CoordinateTransformMode_HALF_PIXEL: | |||
| calculate_ = CalculateHalfPixel; | |||
| break; | |||
| default: | |||
| MS_LOG(ERROR) << "Do not support coordinate transform mode. Mode is" | |||
| << schema::EnumNameCoordinateTransformMode( | |||
| static_cast<schema::CoordinateTransformMode>(coordinate_transform_mode_)); | |||
| } | |||
| if (ret != RET_OK) { | |||
| return ret; | |||
| } | |||
| @@ -55,8 +70,8 @@ int ResizeCPUKernel::ReSize() { | |||
| auto input = in_tensors_.at(0); | |||
| auto input_shape = input->shape(); | |||
| ret = PrepareResizeBilinear(input_shape.data(), out_tensors_.at(0)->shape().data(), align_corners_, y_bottoms_, | |||
| y_tops_, x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_); | |||
| ret = PrepareResizeBilinear(input_shape.data(), out_tensors_.at(0)->shape().data(), calculate_, y_bottoms_, y_tops_, | |||
| x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_); | |||
| if (ret != RET_OK) { | |||
| FreeTmpBuffer(); | |||
| } | |||
| @@ -163,7 +178,6 @@ int ResizeCPUKernel::RunImpl(int task_id) { | |||
| if (context_ == nullptr) { | |||
| return RET_NULL_PTR; | |||
| } | |||
| int ret = 0; | |||
| switch (method_) { | |||
| case static_cast<int>(schema::ResizeMethod_LINEAR): { | |||
| @@ -176,9 +190,10 @@ int ResizeCPUKernel::RunImpl(int task_id) { | |||
| int c = in_tensors_.at(0)->shape().at(3); | |||
| float *line0 = line_buffer_ + new_width_ * c * 2 * task_id; | |||
| float *line1 = line0 + new_width_ * c; | |||
| ret = ResizeBilinear2(input_data, output_data, input_shape.data(), out_tensors_.at(0)->shape().data(), y_bottoms_, | |||
| y_tops_, x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_, line0, line1, n_h_begin, | |||
| n_h_end); | |||
| ret = ResizeBilinear(input_data, output_data, input_shape.data(), out_tensors_.at(0)->shape().data(), y_bottoms_, | |||
| y_tops_, x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_, line0, line1, n_h_begin, | |||
| n_h_end); | |||
| break; | |||
| } | |||
| @@ -195,7 +210,7 @@ int ResizeCPUKernel::RunImpl(int task_id) { | |||
| } | |||
| } | |||
| ret = ResizeNearestNeighbor(input_data, output_data, input_shape.data(), out_tensors_[0]->shape().data(), | |||
| align_corners_, task_id, context_->thread_num_); | |||
| calculate_, coordinate_transform_mode_, task_id, context_->thread_num_); | |||
| break; | |||
| } | |||
| case schema::ResizeMethod_UNKNOW: | |||
| @@ -51,6 +51,7 @@ class ResizeCPUKernel : public ResizeBaseCPUKernel { | |||
| float *y_bottom_weights_ = nullptr; | |||
| float *x_left_weights_ = nullptr; | |||
| float *line_buffer_ = nullptr; | |||
| CalculateOriginalCoordinate calculate_ = nullptr; | |||
| }; | |||
| } // namespace mindspore::kernel | |||
| @@ -61,8 +61,8 @@ int UpsampleCPUKernel::ReSize() { | |||
| auto output = out_tensors().at(0); | |||
| MS_ASSERT(output); | |||
| auto output_shape = output->shape(); | |||
| ret = PrepareResizeBilinear(input_shape.data(), output_shape.data(), align_corners_, y_bottoms_, y_tops_, x_lefts_, | |||
| x_rights_, y_bottom_weights_, x_left_weights_); | |||
| ret = PrepareResizeBilinear(input_shape.data(), output_shape.data(), CalculateAsymmetric, y_bottoms_, y_tops_, | |||
| x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_); | |||
| if (ret != RET_OK) { | |||
| FreeTmpBuffer(); | |||
| } | |||
| @@ -104,16 +104,14 @@ int UpsampleCPUKernel::RunImpl(int task_id) { | |||
| int c = in_tensors_.at(0)->shape().at(3); | |||
| float *line0 = line_buffer_ + new_width_ * c * 2 * task_id; | |||
| float *line1 = line0 + new_width_ * c; | |||
| ret = | |||
| ResizeBilinear2(input_data, output_data, input_shape.data(), out_tensor->shape().data(), y_bottoms_, y_tops_, | |||
| x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_, line0, line1, n_h_begin, n_h_end); | |||
| ret = ResizeBilinear(input_data, output_data, input_shape.data(), out_tensor->shape().data(), y_bottoms_, y_tops_, | |||
| x_lefts_, x_rights_, y_bottom_weights_, x_left_weights_, line0, line1, n_h_begin, n_h_end); | |||
| break; | |||
| } | |||
| case static_cast<int>(schema::ResizeMethod_NEAREST): { | |||
| align_corners_ = false; | |||
| ret = ResizeNearestNeighbor(input_data, output_data, input_shape.data(), out_tensor->shape().data(), | |||
| align_corners_, task_id, context_->thread_num_); | |||
| CalculateAsymmetric, coordinate_transform_mode_, task_id, context_->thread_num_); | |||
| break; | |||
| } | |||
| default: { | |||
| @@ -138,10 +138,11 @@ int ResizeInt8CPUKernel::CalRatio() { | |||
| auto out_height = out_tensor->Height(); | |||
| resize_quant_arg_.ratio_x_ = ((1 << 10) * in_width + out_width / 2) / out_width; | |||
| resize_quant_arg_.ratio_y_ = ((1 << 10) * in_height + out_height / 2) / out_height; | |||
| if (align_corners_ && out_width > 1) { | |||
| bool align_corners = coordinate_transform_mode_ == 1; | |||
| if (align_corners && out_width > 1) { | |||
| resize_quant_arg_.ratio_x_ = ((1 << 10) * (in_width - 1) + (out_width - 1) / 2) / (out_width - 1); | |||
| } | |||
| if (align_corners_ && out_height > 1) { | |||
| if (align_corners && out_height > 1) { | |||
| resize_quant_arg_.ratio_y_ = ((1 << 10) * (in_height - 1) + (out_height - 1) / 2) / (out_height - 1); | |||
| } | |||
| return RET_OK; | |||
| @@ -207,10 +208,11 @@ int ResizeInt8CPUKernel::CalFloatRatio() { | |||
| auto out_height = out_tensor->Height(); | |||
| resize_float_quant_arg_.ratio_x_ = static_cast<float>(in_width) / out_width; | |||
| resize_float_quant_arg_.ratio_y_ = static_cast<float>(in_height) / out_height; | |||
| if (align_corners_ && out_width > 1) { | |||
| bool align_corners = coordinate_transform_mode_ == 1; | |||
| if (align_corners && out_width > 1) { | |||
| resize_float_quant_arg_.ratio_x_ = static_cast<float>(in_width - 1) / (out_width - 1); | |||
| } | |||
| if (align_corners_ && out_height > 1) { | |||
| if (align_corners && out_height > 1) { | |||
| resize_float_quant_arg_.ratio_y_ = static_cast<float>(in_height - 1) / (out_height - 1); | |||
| } | |||
| return RET_OK; | |||
| @@ -335,14 +337,15 @@ int ResizeInt8CPUKernel::RunImpl(int task_id) { | |||
| case static_cast<int>(schema::ResizeMethod_NEAREST): { | |||
| bool same_zp = quant_in_->zp_ == quant_out_->zp_; | |||
| bool same_scale = abs(quant_out_->scale_ - quant_in_->scale_) < 1e-6; | |||
| bool align_corners = coordinate_transform_mode_ == 1; | |||
| if (same_zp && same_scale) { | |||
| ret = | |||
| ResizeNearestNeighborInt8Simple(input_data, output_data, input_shape.data(), out_tensors_[0]->shape().data(), | |||
| align_corners_, task_id, context_->thread_num_); | |||
| align_corners, task_id, context_->thread_num_); | |||
| } else { | |||
| ret = | |||
| ResizeNearestNeighborInt8(input_data, output_data, input_shape.data(), out_tensors_[0]->shape().data(), | |||
| align_corners_, multiplier_, quant_in_, quant_out_, task_id, context_->thread_num_); | |||
| align_corners, multiplier_, quant_in_, quant_out_, task_id, context_->thread_num_); | |||
| } | |||
| break; | |||
| } | |||
| @@ -50,7 +50,7 @@ int ResizeNPUKernel::SetNPUInputs(const std::vector<lite::Tensor *> &inputs, con | |||
| MS_LOG(ERROR) << " op is nullptr."; | |||
| return RET_ERROR; | |||
| } | |||
| op->set_attr_align_corners(resize_parameter_->align_corners_); | |||
| op->set_attr_align_corners(resize_parameter_->coordinate_transform_mode_ == 1); | |||
| op->set_input_x(*npu_inputs[0]); | |||
| op->set_input_size(*out_size); | |||
| op->set_attr_half_pixel_centers(resize_parameter_->preserve_aspect_ratio_); | |||
| @@ -61,7 +61,7 @@ int ResizeNPUKernel::SetNPUInputs(const std::vector<lite::Tensor *> &inputs, con | |||
| MS_LOG(ERROR) << " op is nullptr."; | |||
| return RET_ERROR; | |||
| } | |||
| op->set_attr_align_corners(resize_parameter_->align_corners_); | |||
| op->set_attr_align_corners(resize_parameter_->coordinate_transform_mode_ == 1); | |||
| op->set_input_x(*npu_inputs[0]); | |||
| op->set_input_size(*out_size); | |||
| op_ = op; | |||
| @@ -53,7 +53,7 @@ int ResizeOpenCLKernel::CheckSpecs() { | |||
| int ResizeOpenCLKernel::Prepare() { | |||
| auto resize_param = reinterpret_cast<ResizeParameter *>(op_parameter_); | |||
| alignCorner = resize_param->align_corners_; | |||
| alignCorner = resize_param->coordinate_transform_mode_ == 1; | |||
| preserveAspectRatio = resize_param->preserve_aspect_ratio_; | |||
| auto in_shape = in_tensors_[0]->shape(); | |||
| auto out_shape = out_tensors_[0]->shape(); | |||
| @@ -71,7 +71,9 @@ void TestResizeBilinearInt8::Prepare(const std::vector<int> &in_shape, const std | |||
| param_.method_ = static_cast<int>(schema::ResizeMethod_LINEAR); | |||
| param_.new_width_ = out_shape[2]; | |||
| param_.new_height_ = out_shape[1]; | |||
| param_.align_corners_ = align_corners; | |||
| if (align_corners) { | |||
| param_.coordinate_transform_mode_ = 1; | |||
| } | |||
| creator_ = lite::KernelRegistry::GetInstance()->GetCreator(desc_); | |||
| @@ -66,7 +66,9 @@ void TestResizeNearestNeighborInt8::Prepare(const std::vector<int> &in_shape, co | |||
| param_.method_ = static_cast<int>(schema::ResizeMethod_NEAREST); | |||
| param_.new_width_ = out_shape[2]; | |||
| param_.new_height_ = out_shape[1]; | |||
| param_.align_corners_ = align_corners; | |||
| if (align_corners) { | |||
| param_.coordinate_transform_mode_ = 1; | |||
| } | |||
| creator_ = lite::KernelRegistry::GetInstance()->GetCreator(desc_); | |||
| @@ -26,7 +26,9 @@ OpParameter *CreateParameter(schema::ResizeMethod method, int new_height, int ne | |||
| auto *param = test::CreateParameter<ResizeParameter>(schema::PrimitiveType_Resize); | |||
| param->new_height_ = new_height; | |||
| param->new_width_ = new_width; | |||
| param->align_corners_ = align_corners; | |||
| if (align_corners) { | |||
| param->coordinate_transform_mode_ = 1; | |||
| } | |||
| param->method_ = method; | |||
| param->preserve_aspect_ratio_ = false; | |||
| return reinterpret_cast<OpParameter *>(param); | |||
| @@ -45,8 +45,8 @@ PrimitiveC *CaffeInterpParser::ParseLitePrimitive(const caffe::LayerParameter &p | |||
| } | |||
| attr->newWidth = width; | |||
| } | |||
| attr->alignCorners = true; | |||
| attr->method = schema::ResizeMethod_LINEAR; | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ALIGN_CORNERS; | |||
| auto primitive = std::make_unique<schema::PrimitiveT>(); | |||
| primitive->value.type = schema::PrimitiveType_Resize; | |||
| primitive->value.value = attr.release(); | |||
| @@ -36,17 +36,19 @@ lite::PrimitiveC *OnnxResizeParser::ParseLitePrimitive(const onnx::GraphProto &o | |||
| for (const auto &onnx_node_attr : onnx_node.attribute()) { | |||
| const auto &attribute_name = onnx_node_attr.name(); | |||
| if (attribute_name == "coordinate_transformation_mode") { | |||
| attr->coordinateTransformMode = [&]() { | |||
| std::map<std::string, schema::CoordinateTransformMode> transform_map = { | |||
| {"half_pixel", schema::CoordinateTransformMode_HALF_PIXEL}, | |||
| {"pytorch_half_pixel", schema::CoordinateTransformMode_PYTORCH_HALF_PIXEL}, | |||
| {"align_corners", schema::CoordinateTransformMode_ALIGN_CORNERS}, | |||
| {"asymmetric", schema::CoordinateTransformMode_ASYMMETRIC}, | |||
| {"tf_half_pixel_for_nn", schema::CoordinateTransformMode_TF_HALF_PIXEL}, | |||
| {"tf_crop_and_resize", schema::CoordinateTransformMode_TF_CROP_AND_RESIZE}, | |||
| }; | |||
| return transform_map[onnx_node_attr.s()]; | |||
| }(); | |||
| std::map<std::string, schema::CoordinateTransformMode> transform_map = { | |||
| {"half_pixel", schema::CoordinateTransformMode_HALF_PIXEL}, | |||
| {"pytorch_half_pixel", schema::CoordinateTransformMode_HALF_PIXEL}, | |||
| {"align_corners", schema::CoordinateTransformMode_ALIGN_CORNERS}, | |||
| {"asymmetric", schema::CoordinateTransformMode_ASYMMETRIC}, | |||
| {"tf_crop_and_resize", schema::CoordinateTransformMode_CROP_AND_RESIZE}, | |||
| }; | |||
| if (transform_map.find(onnx_node_attr.s()) != transform_map.end()) { | |||
| attr->coordinateTransformMode = transform_map[onnx_node_attr.s()]; | |||
| } else { | |||
| MS_LOG(ERROR) << "Unsupport coordinate transform mode: " << attribute_name; | |||
| return nullptr; | |||
| } | |||
| } else if (attribute_name == "cubic_coeff_a") { | |||
| attr->cubicCoeff = onnx_node_attr.f(); | |||
| } else if (attribute_name == "exclude_outside") { | |||
| @@ -39,6 +39,7 @@ lite::PrimitiveC *OnnxUpsampleParser::ParseLitePrimitive(const onnx::GraphProto | |||
| attr->method = onnx_node_attr.s() == "nearest" ? schema::ResizeMethod_NEAREST : schema::ResizeMethod_LINEAR; | |||
| } | |||
| } | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ASYMMETRIC; | |||
| auto primitive = std::make_unique<schema::PrimitiveT>(); | |||
| if (primitive == nullptr) { | |||
| MS_LOG(ERROR) << "new primitive failed"; | |||
| @@ -47,7 +47,11 @@ STATUS TFResizeParser::Parse(const tensorflow::NodeDef &tf_op, | |||
| MS_LOG(ERROR) << "The align_corners attr should be specified"; | |||
| return RET_ERROR; | |||
| } | |||
| attr->alignCorners = attr_value.b(); | |||
| if (attr_value.b()) { | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ALIGN_CORNERS; | |||
| } else { | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ASYMMETRIC; | |||
| } | |||
| if (tf_op.op() == "ResizeBilinear") { | |||
| attr->method = schema::ResizeMethod_LINEAR; | |||
| } else if (tf_op.op() == "ResizeNearestNeighbor") { | |||
| @@ -36,7 +36,7 @@ PrimitiveC *TfliteResizeParser::ParseLitePrimitive(const std::unique_ptr<tflite: | |||
| MS_LOG(ERROR) << "new op failed"; | |||
| return nullptr; | |||
| } | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_COMMON; | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ASYMMETRIC; | |||
| auto tflite_op_type = (tflite_model->operator_codes[tflite_op->opcode_index])->builtin_code; | |||
| if (tflite_op_type == tflite::BuiltinOperator_RESIZE_BILINEAR) { | |||
| MS_LOG(DEBUG) << "parse TfliteResizeBilinearParser"; | |||
| @@ -46,13 +46,11 @@ PrimitiveC *TfliteResizeParser::ParseLitePrimitive(const std::unique_ptr<tflite: | |||
| return nullptr; | |||
| } | |||
| if (tfliteAttr->align_corners) { | |||
| attr->alignCorners = tfliteAttr->align_corners; | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ALIGN_CORNERS; | |||
| } | |||
| if (tfliteAttr->half_pixel_centers) { | |||
| attr->coordinateTransformMode = (attr->coordinateTransformMode == schema::CoordinateTransformMode_COMMON | |||
| ? schema::CoordinateTransformMode_TF_HALF_PIXEL | |||
| : schema::CoordinateTransformMode_ALIGN_CORNERS_WITH_HALF_PIEXL); | |||
| MS_LOG(ERROR) << "Does not support half pixel centers"; | |||
| return nullptr; | |||
| } | |||
| attr->method = schema::ResizeMethod_LINEAR; | |||
| } else if (tflite_op_type == tflite::BuiltinOperator_RESIZE_NEAREST_NEIGHBOR) { | |||
| @@ -63,13 +61,11 @@ PrimitiveC *TfliteResizeParser::ParseLitePrimitive(const std::unique_ptr<tflite: | |||
| return nullptr; | |||
| } | |||
| if (tfliteAttr->align_corners) { | |||
| attr->alignCorners = tfliteAttr->align_corners; | |||
| attr->coordinateTransformMode = schema::CoordinateTransformMode_ALIGN_CORNERS; | |||
| } | |||
| if (tfliteAttr->half_pixel_centers) { | |||
| attr->coordinateTransformMode = (attr->coordinateTransformMode == schema::CoordinateTransformMode_COMMON | |||
| ? schema::CoordinateTransformMode_TF_HALF_PIXEL | |||
| : schema::CoordinateTransformMode_ALIGN_CORNERS_WITH_HALF_PIEXL); | |||
| MS_LOG(ERROR) << "Does not support half pixel centers"; | |||
| return nullptr; | |||
| } | |||
| attr->method = schema::ResizeMethod_NEAREST; | |||
| attr->nearestMode = schema::NearestMode_NORMAL; | |||
| @@ -326,12 +326,18 @@ STATUS OnnxInputAdjustOpPass::AdjustResize(const CNodePtr &cnode) { | |||
| return lite::RET_ERROR; | |||
| } | |||
| auto attr = reinterpret_cast<schema::ResizeT *>(value); | |||
| if (cnode->inputs().size() > 3 && | |||
| attr->coordinateTransformMode == schema::CoordinateTransformMode_TF_CROP_AND_RESIZE) { | |||
| if (cnode->inputs().size() > 3 && attr->coordinateTransformMode == schema::CoordinateTransformMode_CROP_AND_RESIZE) { | |||
| auto new_resize_inputs = cnode->inputs(); | |||
| new_resize_inputs.erase(new_resize_inputs.begin() + 1); | |||
| cnode->set_inputs(new_resize_inputs); | |||
| } | |||
| if (cnode->inputs().size() > 3 && attr->coordinateTransformMode == schema::CoordinateTransformMode_HALF_PIXEL) { | |||
| std::vector<AnfNodePtr> new_resize_inputs; | |||
| new_resize_inputs.push_back(cnode->inputs()[0]); | |||
| new_resize_inputs.push_back(cnode->inputs()[1]); | |||
| new_resize_inputs.push_back(cnode->inputs()[4]); | |||
| cnode->set_inputs(new_resize_inputs); | |||
| } | |||
| return lite::RET_OK; | |||
| } | |||
| @@ -588,6 +594,8 @@ bool OnnxInputAdjustOpPass::Run(const FuncGraphPtr &func_graph) { | |||
| status = AdjustCast(cnode); | |||
| } else if (type == schema::PrimitiveType_Transpose) { | |||
| status = ReplaceTransposeWithGraphInput(func_graph, cnode); | |||
| } else if (type == schema::PrimitiveType_Resize) { | |||
| status = AdjustResize(cnode); | |||
| } | |||
| if (status != lite::RET_OK && status != lite::RET_NO_CHANGE) { | |||
| MS_LOG(ERROR) << "adjust input pass is failed."; | |||