diff --git a/mindspore/ccsrc/minddata/dataset/include/dataset/vision.h b/mindspore/ccsrc/minddata/dataset/include/dataset/vision.h index ddcbca95cc6..0af4b98efbf 100644 --- a/mindspore/ccsrc/minddata/dataset/include/dataset/vision.h +++ b/mindspore/ccsrc/minddata/dataset/include/dataset/vision.h @@ -642,13 +642,13 @@ class RandomRotation final : public TensorTransform { /// - InterpolationMode::kArea, Interpolation method is pixel area interpolation. /// - InterpolationMode::kCubicPil, Interpolation method is bicubic interpolation like implemented in pillow. /// \param[in] expand A boolean representing whether the image is expanded after rotation. - /// \param[in] center A float vector of size 2, representing the x and y center of rotation. + /// \param[in] center A float vector of size 2 or empty, representing the x and y center of rotation + /// or the center of the image. /// \param[in] fill_value A vector representing the value to fill the area outside the transform /// in the output image. If 1 value is provided, it is used for all RGB channels. /// If 3 values are provided, it is used to fill R, G, B channels respectively. RandomRotation(std::vector degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour, - bool expand = false, std::vector center = {-1, -1}, - std::vector fill_value = {0, 0, 0}); + bool expand = false, std::vector center = {}, std::vector fill_value = {0, 0, 0}); /// \brief Destructor. ~RandomRotation() = default; diff --git a/mindspore/ccsrc/minddata/dataset/include/dataset/vision_lite.h b/mindspore/ccsrc/minddata/dataset/include/dataset/vision_lite.h index 4b38d981f62..ff8e26bc397 100644 --- a/mindspore/ccsrc/minddata/dataset/include/dataset/vision_lite.h +++ b/mindspore/ccsrc/minddata/dataset/include/dataset/vision_lite.h @@ -323,12 +323,13 @@ class Rotate final : public TensorTransform { /// - InterpolationMode::kArea, Interpolation method is pixel area interpolation. /// - InterpolationMode::kCubicPil, Interpolation method is bicubic interpolation like implemented in pillow. /// \param[in] expand A boolean representing whether the image is expanded after rotation. - /// \param[in] center A float vector of size 2, representing the x and y center of rotation. + /// \param[in] center A float vector of size 2 or empty, representing the x and y center of rotation + /// or the center of the image. /// \param[in] fill_value A vector representing the value to fill the area outside the transform /// in the output image. If 1 value is provided, it is used for all RGB channels. /// If 3 values are provided, it is used to fill R, G, B channels respectively. Rotate(float degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour, bool expand = false, - std::vector center = {-1, -1}, std::vector fill_value = {0, 0, 0}); + std::vector center = {}, std::vector fill_value = {0, 0, 0}); /// \brief Destructor. ~Rotate() = default; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc index 22c835126f7..39d4e562272 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc @@ -627,8 +627,9 @@ Status CropAndResize(const std::shared_ptr &input, std::shared_ptr &input, std::shared_ptr *output, float fx, float fy, float degree, - InterpolationMode interpolation, bool expand, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b) { +Status Rotate(const std::shared_ptr &input, std::shared_ptr *output, std::vector center, + float degree, InterpolationMode interpolation, bool expand, uint8_t fill_r, uint8_t fill_g, + uint8_t fill_b) { try { std::shared_ptr input_cv = CVTensor::AsCVTensor(input); if (!input_cv->mat().data) { @@ -642,12 +643,14 @@ Status Rotate(const std::shared_ptr &input, std::shared_ptr *out if (input_img.cols > (MAX_INT_PRECISION * 2) || input_img.rows > (MAX_INT_PRECISION * 2)) { RETURN_STATUS_UNEXPECTED("Rotate: image is too large and center is not precise."); } - // default to center of image - if (fx == -1) { + float fx = 0, fy = 0; + if (center.empty()) { + // default to center of image fx = (input_img.cols - 1) / 2.0; - } - if (fy == -1) { fy = (input_img.rows - 1) / 2.0; + } else { + fx = center[0]; + fy = center[1]; } cv::Mat output_img; cv::Scalar fill_color = cv::Scalar(fill_b, fill_g, fill_r); diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h index 380d260912a..a26671db498 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h @@ -183,13 +183,12 @@ Status CropAndResize(const std::shared_ptr &input, std::shared_ptr or and any OpenCv compatible type, see CVTensor. -/// \param fx: rotation center x coordinate -/// \param fy: rotation center y coordinate +/// \param center: rotation center /// \param degree: degree to rotate /// \param expand: if reshape is necessary /// \param output: rotated image of same input type. -Status Rotate(const std::shared_ptr &input, std::shared_ptr *output, float fx, float fy, float degree, - InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, bool expand = false, +Status Rotate(const std::shared_ptr &input, std::shared_ptr *output, std::vector center, + float degree, InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, bool expand = false, uint8_t fill_r = 0, uint8_t fill_g = 0, uint8_t fill_b = 0); /// \brief Returns Normalized image diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.cc index 079523ba0e1..1747259a802 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.cc @@ -24,8 +24,7 @@ namespace mindspore { namespace dataset { -const float RandomRotationOp::kDefCenterX = -1; -const float RandomRotationOp::kDefCenterY = -1; +const std::vector RandomRotationOp::kDefCenter = {}; const InterpolationMode RandomRotationOp::kDefInterpolation = InterpolationMode::kNearestNeighbour; const bool RandomRotationOp::kDefExpand = false; const uint8_t RandomRotationOp::kDefFillR = 0; @@ -34,11 +33,10 @@ const uint8_t RandomRotationOp::kDefFillB = 0; // constructor RandomRotationOp::RandomRotationOp(float start_degree, float end_degree, InterpolationMode resample, bool expand, - float center_x, float center_y, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b) + std::vector center, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b) : degree_start_(start_degree), degree_end_(end_degree), - center_x_(center_x), - center_y_(center_y), + center_(center), interpolation_(resample), expand_(expand), fill_r_(fill_r), @@ -60,8 +58,9 @@ Status RandomRotationOp::Compute(const std::shared_ptr &input, std::shar float mid = (degree_end_ + degree_start_) / 2; float degree = mid + random_double * degree_range; - return Rotate(input, output, center_x_, center_y_, degree, interpolation_, expand_, fill_r_, fill_g_, fill_b_); + return Rotate(input, output, center_, degree, interpolation_, expand_, fill_r_, fill_g_, fill_b_); } + Status RandomRotationOp::OutputShape(const std::vector &inputs, std::vector &outputs) { RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); outputs.clear(); diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.h index 3616e8c2ad2..c017440cebd 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/random_rotation_op.h @@ -31,8 +31,7 @@ namespace dataset { class RandomRotationOp : public TensorOp { public: // Default values, also used by python_bindings.cc - static const float kDefCenterX; - static const float kDefCenterY; + static const std::vector kDefCenter; static const InterpolationMode kDefInterpolation; static const bool kDefExpand; static const uint8_t kDefFillR; @@ -44,8 +43,7 @@ class RandomRotationOp : public TensorOp { // @param endDegree ending range for random degree // @param interpolation DE interpolation mode for rotation // @param expand option for the output image shape to change - // @param center_x coordinate for center of image rotation - // @param center_y coordinate for center of image rotation + // @param center coordinate for center of image rotation // @param fill_r R value for the color to pad with // @param fill_g G value for the color to pad with // @param fill_b B value for the color to pad with @@ -53,8 +51,8 @@ class RandomRotationOp : public TensorOp { // @details the output shape, if changed, will contain the entire rotated image // @note maybe using unsigned long int isn't the best here according to our coding rules RandomRotationOp(float start_degree, float end_degree, InterpolationMode resample = kDefInterpolation, - bool expand = kDefExpand, float center_x = kDefCenterX, float center_y = kDefCenterY, - uint8_t fill_r = kDefFillR, uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB); + bool expand = kDefExpand, std::vector center = kDefCenter, uint8_t fill_r = kDefFillR, + uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB); ~RandomRotationOp() override = default; @@ -63,6 +61,7 @@ class RandomRotationOp : public TensorOp { // and transforms its data using openCV, the output memory is manipulated to contain the result // @return Status The status code returned Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; std::string Name() const override { return kRandomRotationOp; } @@ -70,8 +69,7 @@ class RandomRotationOp : public TensorOp { private: float degree_start_; float degree_end_; - float center_x_; - float center_y_; + std::vector center_; InterpolationMode interpolation_; bool expand_; uint8_t fill_r_; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.cc index 5011932af55..d04824c7fdc 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.cc @@ -24,8 +24,7 @@ namespace mindspore { namespace dataset { -const float RotateOp::kDefCenterX = -1; -const float RotateOp::kDefCenterY = -1; +const std::vector RotateOp::kDefCenter = {}; const InterpolationMode RotateOp::kDefInterpolation = InterpolationMode::kNearestNeighbour; const bool RotateOp::kDefExpand = false; const uint8_t RotateOp::kDefFillR = 0; @@ -34,11 +33,10 @@ const uint8_t RotateOp::kDefFillB = 0; RotateOp::RotateOp(int angle_id) : angle_id_(angle_id) {} -RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, float center_x, float center_y, - uint8_t fill_r, uint8_t fill_g, uint8_t fill_b) +RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, std::vector center, uint8_t fill_r, + uint8_t fill_g, uint8_t fill_b) : degrees_(degrees), - center_x_(center_x), - center_y_(center_y), + center_(center), interpolation_(resample), expand_(expand), fill_r_(fill_r), @@ -48,7 +46,7 @@ RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, float Status RotateOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { IO_CHECK(input, output); #ifndef ENABLE_ANDROID - return Rotate(input, output, center_x_, center_y_, degrees_, interpolation_, expand_, fill_r_, fill_g_, fill_b_); + return Rotate(input, output, center_, degrees_, interpolation_, expand_, fill_r_, fill_g_, fill_b_); #else return Rotate(input, output, angle_id_); #endif diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.h index 0b0b6e9b32a..12093bd27ba 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rotate_op.h @@ -30,8 +30,7 @@ namespace dataset { class RotateOp : public TensorOp { public: // Default values, also used by python_bindings.cc - static const float kDefCenterX; - static const float kDefCenterY; + static const std::vector kDefCenter; static const InterpolationMode kDefInterpolation; static const bool kDefExpand; static const uint8_t kDefFillR; @@ -42,8 +41,8 @@ class RotateOp : public TensorOp { explicit RotateOp(int angle_id); explicit RotateOp(float degrees, InterpolationMode resample = kDefInterpolation, bool expand = kDefExpand, - float center_x = kDefCenterX, float center_y = kDefCenterY, uint8_t fill_r = kDefFillR, - uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB); + std::vector center = kDefCenter, uint8_t fill_r = kDefFillR, uint8_t fill_g = kDefFillG, + uint8_t fill_b = kDefFillB); ~RotateOp() override = default; @@ -61,8 +60,7 @@ class RotateOp : public TensorOp { private: float degrees_; - float center_x_; - float center_y_; + std::vector center_; InterpolationMode interpolation_; bool expand_; uint8_t fill_r_; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/random_rotation_ir.cc b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/random_rotation_ir.cc index ececfe31e51..cd3ca25465f 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/random_rotation_ir.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/random_rotation_ir.cc @@ -64,9 +64,9 @@ Status RandomRotationOperation::ValidateParams() { RETURN_STATUS_SYNTAX_ERROR(err_msg); } // center - if (center_.empty() || center_.size() != 2) { + if (center_.size() != 0 && center_.size() != 2) { std::string err_msg = - "RandomRotation: center must be a vector of two values, got: " + std::to_string(center_.size()); + "RandomRotation: center must be a vector of two values or empty, got: " + std::to_string(center_.size()); MS_LOG(ERROR) << err_msg; RETURN_STATUS_SYNTAX_ERROR(err_msg); } @@ -97,7 +97,7 @@ std::shared_ptr RandomRotationOperation::Build() { } std::shared_ptr tensor_op = std::make_shared( - start_degree, end_degree, interpolation_mode_, expand_, center_[0], center_[1], fill_r, fill_g, fill_b); + start_degree, end_degree, interpolation_mode_, expand_, center_, fill_r, fill_g, fill_b); return tensor_op; } diff --git a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/rotate_ir.cc b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/rotate_ir.cc index e46e9668817..3bdac701786 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/rotate_ir.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/ir/vision/rotate_ir.cc @@ -37,8 +37,9 @@ std::string RotateOperation::Name() const { return kRotateOperation; } Status RotateOperation::ValidateParams() { #ifndef ENABLE_ANDROID // center - if (center_.empty() || center_.size() != 2) { - std::string err_msg = "Rotate: center must be a vector of two values, got: " + std::to_string(center_.size()); + if (center_.size() != 0 && center_.size() != 2) { + std::string err_msg = + "Rotate: center must be a vector of two values or empty, got: " + std::to_string(center_.size()); MS_LOG(ERROR) << err_msg; RETURN_STATUS_SYNTAX_ERROR(err_msg); } @@ -62,7 +63,7 @@ std::shared_ptr RotateOperation::Build() { } std::shared_ptr tensor_op = - std::make_shared(degrees_, interpolation_mode_, expand_, center_[0], center_[1], fill_r, fill_g, fill_b); + std::make_shared(degrees_, interpolation_mode_, expand_, center_, fill_r, fill_g, fill_b); return tensor_op; #else return rotate_op_; diff --git a/mindspore/dataset/vision/c_transforms.py b/mindspore/dataset/vision/c_transforms.py index 586b590d0e3..0292061abfa 100644 --- a/mindspore/dataset/vision/c_transforms.py +++ b/mindspore/dataset/vision/c_transforms.py @@ -90,6 +90,7 @@ DE_C_INTER_MODE = {Inter.NEAREST: cde.InterpolationMode.DE_INTER_NEAREST_NEIGHBO DE_C_SLICE_MODE = {SliceMode.PAD: cde.SliceMode.DE_SLICE_PAD, SliceMode.DROP: cde.SliceMode.DE_SLICE_DROP} + def parse_padding(padding): """ Parses and prepares the padding tuple""" if isinstance(padding, numbers.Number): @@ -1214,7 +1215,7 @@ class RandomRotation(ImageTensorOperation): if degrees[0] > degrees[1]: degrees[1] += 360 if center is None: - center = (-1, -1) + center = () if isinstance(fill_value, int): fill_value = tuple([fill_value] * 3) self.degrees = degrees @@ -1525,7 +1526,7 @@ class Rotate(ImageTensorOperation): if isinstance(degrees, (int, float)): degrees = degrees % 360 if center is None: - center = (-1, -1) + center = () if isinstance(fill_value, int): fill_value = tuple([fill_value] * 3) self.degrees = degrees @@ -1576,6 +1577,7 @@ class SlicePatches(ImageTensorOperation): return cde.SlicePatchesOperation(self.num_height, self.num_width, DE_C_SLICE_MODE[self.slice_mode], self.fill_value) + class SoftDvppDecodeRandomCropResizeJpeg(ImageTensorOperation): """ A combination of `Crop`, `Decode` and `Resize` using the simulation algorithm of Ascend series chip DVPP module. diff --git a/mindspore/dataset/vision/validators.py b/mindspore/dataset/vision/validators.py index 50b54890f1f..baecbabce73 100644 --- a/mindspore/dataset/vision/validators.py +++ b/mindspore/dataset/vision/validators.py @@ -20,8 +20,9 @@ import numpy as np from mindspore._c_dataengine import TensorOp, TensorOperation from mindspore.dataset.core.validator_helpers import check_value, check_uint8, FLOAT_MAX_INTEGER, check_pos_float32, \ - check_float32, check_2tuple, check_range, check_positive, INT32_MAX, parse_user_args, type_check, type_check_list, \ - check_c_tensor_op, UINT8_MAX, check_value_normalize_std, check_value_cutoff, check_value_ratio, check_odd + check_float32, check_2tuple, check_range, check_positive, INT32_MAX, INT32_MIN, parse_user_args, type_check, \ + type_check_list, check_c_tensor_op, UINT8_MAX, check_value_normalize_std, check_value_cutoff, check_value_ratio, \ + check_odd from .utils import Inter, Border, ImageBatchFormat, SliceMode @@ -427,7 +428,7 @@ def check_resample_expand_center_fill_value_params(resample, expand, center, fil check_2tuple(center, "center") for value in center: type_check(value, (int, float), "center") - check_value(value, [-1, INT32_MAX], "center") + check_value(value, [INT32_MIN, INT32_MAX], "center") check_fill_value(fill_value) @@ -528,6 +529,7 @@ def check_slice_patches(method): return new_method + def check_random_perspective(method): """Wrapper method to check the parameters of random perspective.""" diff --git a/tests/ut/cpp/dataset/random_rotation_op_test.cc b/tests/ut/cpp/dataset/random_rotation_op_test.cc index a3ad6a3f33a..e2243e01972 100644 --- a/tests/ut/cpp/dataset/random_rotation_op_test.cc +++ b/tests/ut/cpp/dataset/random_rotation_op_test.cc @@ -35,11 +35,10 @@ TEST_F(MindDataTestRandomRotationOp, TestOp) { float sDegree = -180; float eDegree = 180; // use compute center to use for rotation - float xCenter = -1; - float yCenter = -1; + std::vector center = {}; bool expand = false; std::unique_ptr op( - new RandomRotationOp(sDegree, eDegree, InterpolationMode::kLinear, expand, xCenter, yCenter)); + new RandomRotationOp(sDegree, eDegree, InterpolationMode::kLinear, expand, center)); EXPECT_TRUE(op->OneToOne()); Status s = op->Compute(input_tensor_, &output_tensor); EXPECT_TRUE(s.IsOk()); diff --git a/tests/ut/cpp/dataset/to_float16_op_test.cc b/tests/ut/cpp/dataset/to_float16_op_test.cc index a6de5177c5a..14ce72dbaf3 100644 --- a/tests/ut/cpp/dataset/to_float16_op_test.cc +++ b/tests/ut/cpp/dataset/to_float16_op_test.cc @@ -36,11 +36,10 @@ TEST_F(MindDataTestToFloat16Op, TestOp) { float s_degree = -180; float e_degree = 180; // use compute center to use for rotation - float x_center = -1; - float y_center = -1; + std::vector center = {}; bool expand = false; std::unique_ptr op( - new RandomRotationOp(s_degree, e_degree, InterpolationMode::kLinear, expand, x_center, y_center)); + new RandomRotationOp(s_degree, e_degree, InterpolationMode::kLinear, expand, center)); EXPECT_TRUE(op->OneToOne()); Status s = op->Compute(input_tensor_, &output_tensor); EXPECT_TRUE(s.IsOk());