Merge pull request !5189 from islam_amin/fixed_translate_affinetags/v1.0.0
| @@ -131,7 +131,7 @@ PYBIND_REGISTER(RandomResizeWithBBoxOp, 1, ([](const py::module *m) { | |||||
| PYBIND_REGISTER(RandomPosterizeOp, 1, ([](const py::module *m) { | PYBIND_REGISTER(RandomPosterizeOp, 1, ([](const py::module *m) { | ||||
| (void)py::class_<RandomPosterizeOp, TensorOp, std::shared_ptr<RandomPosterizeOp>>(*m, | (void)py::class_<RandomPosterizeOp, TensorOp, std::shared_ptr<RandomPosterizeOp>>(*m, | ||||
| "RandomPosterizeOp") | "RandomPosterizeOp") | ||||
| .def(py::init<uint8_t, uint8_t>()); | |||||
| .def(py::init<std::vector<uint8_t>>()); | |||||
| })); | })); | ||||
| PYBIND_REGISTER(UniformAugOp, 1, ([](const py::module *m) { | PYBIND_REGISTER(UniformAugOp, 1, ([](const py::module *m) { | ||||
| @@ -219,8 +219,8 @@ std::shared_ptr<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob) | |||||
| } | } | ||||
| // Function to create RandomPosterizeOperation. | // Function to create RandomPosterizeOperation. | ||||
| std::shared_ptr<RandomPosterizeOperation> RandomPosterize(uint8_t min_bit, uint8_t max_bit) { | |||||
| auto op = std::make_shared<RandomPosterizeOperation>(min_bit, max_bit); | |||||
| std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint8_t> &bit_range) { | |||||
| auto op = std::make_shared<RandomPosterizeOperation>(bit_range); | |||||
| // Input validation | // Input validation | ||||
| if (!op->ValidateParams()) { | if (!op->ValidateParams()) { | ||||
| return nullptr; | return nullptr; | ||||
| @@ -383,7 +383,7 @@ CutMixBatchOperation::CutMixBatchOperation(ImageBatchFormat image_batch_format, | |||||
| bool CutMixBatchOperation::ValidateParams() { | bool CutMixBatchOperation::ValidateParams() { | ||||
| if (alpha_ <= 0) { | if (alpha_ <= 0) { | ||||
| MS_LOG(ERROR) << "CutMixBatch: alpha cannot be negative."; | |||||
| MS_LOG(ERROR) << "CutMixBatch: alpha must be a positive floating value however it is: " << alpha_; | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (prob_ < 0 || prob_ > 1) { | if (prob_ < 0 || prob_ > 1) { | ||||
| @@ -616,7 +616,7 @@ RandomAffineOperation::RandomAffineOperation(const std::vector<float_t> °rees | |||||
| bool RandomAffineOperation::ValidateParams() { | bool RandomAffineOperation::ValidateParams() { | ||||
| // Degrees | // Degrees | ||||
| if (degrees_.size() != 2) { | if (degrees_.size() != 2) { | ||||
| MS_LOG(ERROR) << "RandomAffine: degrees vector has incorrect size: degrees.size() = " << degrees_.size(); | |||||
| MS_LOG(ERROR) << "RandomAffine: degrees expecting size 2, got: degrees.size() = " << degrees_.size(); | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (degrees_[0] > degrees_[1]) { | if (degrees_[0] > degrees_[1]) { | ||||
| @@ -625,16 +625,43 @@ bool RandomAffineOperation::ValidateParams() { | |||||
| return false; | return false; | ||||
| } | } | ||||
| // Translate | // Translate | ||||
| if (translate_range_.size() != 2) { | |||||
| MS_LOG(ERROR) << "RandomAffine: translate_range vector has incorrect size: translate_range.size() = " | |||||
| if (translate_range_.size() != 2 && translate_range_.size() != 4) { | |||||
| MS_LOG(ERROR) << "RandomAffine: translate_range expecting size 2 or 4, got: translate_range.size() = " | |||||
| << translate_range_.size(); | << translate_range_.size(); | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (translate_range_[0] > translate_range_[1]) { | if (translate_range_[0] > translate_range_[1]) { | ||||
| MS_LOG(ERROR) << "RandomAffine: minimum of translate range is greater than maximum: min = " << translate_range_[0] | |||||
| << ", max = " << translate_range_[1]; | |||||
| MS_LOG(ERROR) << "RandomAffine: minimum of translate range on x is greater than maximum: min = " | |||||
| << translate_range_[0] << ", max = " << translate_range_[1]; | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (translate_range_[0] < -1 || translate_range_[0] > 1) { | |||||
| MS_LOG(ERROR) << "RandomAffine: minimum of translate range on x is out of range of [-1, 1], value = " | |||||
| << translate_range_[0]; | |||||
| return false; | |||||
| } | |||||
| if (translate_range_[1] < -1 || translate_range_[1] > 1) { | |||||
| MS_LOG(ERROR) << "RandomAffine: maximum of translate range on x is out of range of [-1, 1], value = " | |||||
| << translate_range_[1]; | |||||
| return false; | |||||
| } | |||||
| if (translate_range_.size() == 4) { | |||||
| if (translate_range_[2] > translate_range_[3]) { | |||||
| MS_LOG(ERROR) << "RandomAffine: minimum of translate range on y is greater than maximum: min = " | |||||
| << translate_range_[2] << ", max = " << translate_range_[3]; | |||||
| return false; | |||||
| } | |||||
| if (translate_range_[2] < -1 || translate_range_[2] > 1) { | |||||
| MS_LOG(ERROR) << "RandomAffine: minimum of translate range on y is out of range of [-1, 1], value = " | |||||
| << translate_range_[2]; | |||||
| return false; | |||||
| } | |||||
| if (translate_range_[3] < -1 || translate_range_[3] > 1) { | |||||
| MS_LOG(ERROR) << "RandomAffine: maximum of translate range on y is out of range of [-1, 1], value = " | |||||
| << translate_range_[3]; | |||||
| return false; | |||||
| } | |||||
| } | |||||
| // Scale | // Scale | ||||
| if (scale_range_.size() != 2) { | if (scale_range_.size() != 2) { | ||||
| MS_LOG(ERROR) << "RandomAffine: scale_range vector has incorrect size: scale_range.size() = " | MS_LOG(ERROR) << "RandomAffine: scale_range vector has incorrect size: scale_range.size() = " | ||||
| @@ -647,8 +674,8 @@ bool RandomAffineOperation::ValidateParams() { | |||||
| return false; | return false; | ||||
| } | } | ||||
| // Shear | // Shear | ||||
| if (shear_ranges_.size() != 4) { | |||||
| MS_LOG(ERROR) << "RandomAffine: shear_ranges vector has incorrect size: shear_ranges.size() = " | |||||
| if (shear_ranges_.size() != 2 && shear_ranges_.size() != 4) { | |||||
| MS_LOG(ERROR) << "RandomAffine: shear_ranges expecting size 2 or 4, got: shear_ranges.size() = " | |||||
| << shear_ranges_.size(); | << shear_ranges_.size(); | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -657,7 +684,7 @@ bool RandomAffineOperation::ValidateParams() { | |||||
| << shear_ranges_[0] << ", max = " << shear_ranges_[1]; | << shear_ranges_[0] << ", max = " << shear_ranges_[1]; | ||||
| return false; | return false; | ||||
| } | } | ||||
| if (shear_ranges_[2] > shear_ranges_[3]) { | |||||
| if (shear_ranges_.size() == 4 && shear_ranges_[2] > shear_ranges_[3]) { | |||||
| MS_LOG(ERROR) << "RandomAffine: minimum of vertical shear range is greater than maximum: min = " << shear_ranges_[2] | MS_LOG(ERROR) << "RandomAffine: minimum of vertical shear range is greater than maximum: min = " << shear_ranges_[2] | ||||
| << ", max = " << scale_range_[3]; | << ", max = " << scale_range_[3]; | ||||
| return false; | return false; | ||||
| @@ -671,6 +698,12 @@ bool RandomAffineOperation::ValidateParams() { | |||||
| } | } | ||||
| std::shared_ptr<TensorOp> RandomAffineOperation::Build() { | std::shared_ptr<TensorOp> RandomAffineOperation::Build() { | ||||
| if (shear_ranges_.size() == 2) { | |||||
| shear_ranges_.resize(4); | |||||
| } | |||||
| if (translate_range_.size() == 2) { | |||||
| translate_range_.resize(4); | |||||
| } | |||||
| auto tensor_op = std::make_shared<RandomAffineOp>(degrees_, translate_range_, scale_range_, shear_ranges_, | auto tensor_op = std::make_shared<RandomAffineOp>(degrees_, translate_range_, scale_range_, shear_ranges_, | ||||
| interpolation_, fill_value_); | interpolation_, fill_value_); | ||||
| return tensor_op; | return tensor_op; | ||||
| @@ -737,27 +770,31 @@ std::shared_ptr<TensorOp> RandomHorizontalFlipOperation::Build() { | |||||
| } | } | ||||
| // RandomPosterizeOperation | // RandomPosterizeOperation | ||||
| RandomPosterizeOperation::RandomPosterizeOperation(uint8_t min_bit, uint8_t max_bit) | |||||
| : min_bit_(min_bit), max_bit_(max_bit) {} | |||||
| RandomPosterizeOperation::RandomPosterizeOperation(const std::vector<uint8_t> &bit_range) : bit_range_(bit_range) {} | |||||
| bool RandomPosterizeOperation::ValidateParams() { | bool RandomPosterizeOperation::ValidateParams() { | ||||
| if (min_bit_ < 1 || min_bit_ > 8) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: min_bit value is out of range [1-8]: " << min_bit_; | |||||
| if (bit_range_.size() != 2) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: bit_range needs to be of size 2 but is of size: " << bit_range_.size(); | |||||
| return false; | |||||
| } | |||||
| if (bit_range_[0] < 1 || bit_range_[0] > 8) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: min_bit value is out of range [1-8]: " << bit_range_[0]; | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (max_bit_ < 1 || max_bit_ > 8) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: max_bit value is out of range [1-8]: " << max_bit_; | |||||
| if (bit_range_[1] < 1 || bit_range_[1] > 8) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: max_bit value is out of range [1-8]: " << bit_range_[1]; | |||||
| return false; | return false; | ||||
| } | } | ||||
| if (max_bit_ < min_bit_) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: max_bit value is less than min_bit: max =" << max_bit_ << ", min = " << min_bit_; | |||||
| if (bit_range_[1] < bit_range_[0]) { | |||||
| MS_LOG(ERROR) << "RandomPosterize: max_bit value is less than min_bit: max =" << bit_range_[1] | |||||
| << ", min = " << bit_range_[0]; | |||||
| return false; | return false; | ||||
| } | } | ||||
| return true; | return true; | ||||
| } | } | ||||
| std::shared_ptr<TensorOp> RandomPosterizeOperation::Build() { | std::shared_ptr<TensorOp> RandomPosterizeOperation::Build() { | ||||
| std::shared_ptr<RandomPosterizeOp> tensor_op = std::make_shared<RandomPosterizeOp>(min_bit_, max_bit_); | |||||
| std::shared_ptr<RandomPosterizeOp> tensor_op = std::make_shared<RandomPosterizeOp>(bit_range_); | |||||
| return tensor_op; | return tensor_op; | ||||
| } | } | ||||
| @@ -161,16 +161,21 @@ std::shared_ptr<PadOperation> Pad(std::vector<int32_t> padding, std::vector<uint | |||||
| /// \brief Function to create a RandomAffine TensorOperation. | /// \brief Function to create a RandomAffine TensorOperation. | ||||
| /// \notes Applies a Random Affine transformation on input image in RGB or Greyscale mode. | /// \notes Applies a Random Affine transformation on input image in RGB or Greyscale mode. | ||||
| /// \param[in] degrees A float vector size 2, representing the starting and ending degree | /// \param[in] degrees A float vector size 2, representing the starting and ending degree | ||||
| /// \param[in] translate_range A float vector size 2, representing percentages of translation on x and y axes. | |||||
| /// \param[in] translate_range A float vector size 2 or 4, representing percentages of translation on x and y axes. | |||||
| /// if size is 2, (min_dx, max_dx, 0, 0) | |||||
| /// if size is 4, (min_dx, max_dx, min_dy, max_dy) | |||||
| /// all values are in range [-1, 1] | |||||
| /// \param[in] scale_range A float vector size 2, representing the starting and ending scales in the range. | /// \param[in] scale_range A float vector size 2, representing the starting and ending scales in the range. | ||||
| /// \param[in] shear_ranges A float vector size 4, representing the starting and ending shear degrees vertically and | |||||
| /// horizontally. | |||||
| /// \param[in] shear_ranges A float vector size 2 or 4, representing the starting and ending shear degrees vertically | |||||
| /// and horizontally. | |||||
| /// if size is 2, (min_shear_x, max_shear_x, 0, 0) | |||||
| /// if size is 4, (min_shear_x, max_shear_x, min_shear_y, max_shear_y) | |||||
| /// \param[in] interpolation An enum for the mode of interpolation | /// \param[in] interpolation An enum for the mode of interpolation | ||||
| /// \param[in] fill_value A uint8_t vector size 3, representing the pixel intensity of the borders, it is used to | /// \param[in] fill_value A uint8_t vector size 3, representing the pixel intensity of the borders, it is used to | ||||
| /// fill R, G, B channels respectively. | /// fill R, G, B channels respectively. | ||||
| /// \return Shared pointer to the current TensorOperation. | /// \return Shared pointer to the current TensorOperation. | ||||
| std::shared_ptr<RandomAffineOperation> RandomAffine( | std::shared_ptr<RandomAffineOperation> RandomAffine( | ||||
| const std::vector<float_t> °rees, const std::vector<float_t> &translate_range = {0.0, 0.0}, | |||||
| const std::vector<float_t> °rees, const std::vector<float_t> &translate_range = {0.0, 0.0, 0.0, 0.0}, | |||||
| const std::vector<float_t> &scale_range = {1.0, 1.0}, const std::vector<float_t> &shear_ranges = {0.0, 0.0, 0.0, 0.0}, | const std::vector<float_t> &scale_range = {1.0, 1.0}, const std::vector<float_t> &shear_ranges = {0.0, 0.0, 0.0, 0.0}, | ||||
| InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, | InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, | ||||
| const std::vector<uint8_t> &fill_value = {0, 0, 0}); | const std::vector<uint8_t> &fill_value = {0, 0, 0}); | ||||
| @@ -223,10 +228,9 @@ std::shared_ptr<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob = | |||||
| /// \brief Function to create a RandomPosterize TensorOperation. | /// \brief Function to create a RandomPosterize TensorOperation. | ||||
| /// \notes Tensor operation to perform random posterize. | /// \notes Tensor operation to perform random posterize. | ||||
| /// \param[in] min_bit - uint8_t representing the minimum bit in range. (Default=8) | |||||
| /// \param[in] max_bit - uint8_t representing the maximum bit in range. (Default=8) | |||||
| /// \param[in] bit_range - uint8_t vector representing the minimum and maximum bit in range. (Default={4, 8}) | |||||
| /// \return Shared pointer to the current TensorOperation. | /// \return Shared pointer to the current TensorOperation. | ||||
| std::shared_ptr<RandomPosterizeOperation> RandomPosterize(uint8_t min_bit = 8, uint8_t max_bit = 8); | |||||
| std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint8_t> &bit_range = {4, 8}); | |||||
| /// \brief Function to create a RandomRotation TensorOp | /// \brief Function to create a RandomRotation TensorOp | ||||
| /// \notes Rotates the image according to parameters | /// \notes Rotates the image according to parameters | ||||
| @@ -530,7 +534,7 @@ class RandomHorizontalFlipOperation : public TensorOperation { | |||||
| class RandomPosterizeOperation : public TensorOperation { | class RandomPosterizeOperation : public TensorOperation { | ||||
| public: | public: | ||||
| explicit RandomPosterizeOperation(uint8_t min_bit = 8, uint8_t max_bit = 8); | |||||
| explicit RandomPosterizeOperation(const std::vector<uint8_t> &bit_range = {4, 8}); | |||||
| ~RandomPosterizeOperation() = default; | ~RandomPosterizeOperation() = default; | ||||
| @@ -539,8 +543,7 @@ class RandomPosterizeOperation : public TensorOperation { | |||||
| bool ValidateParams() override; | bool ValidateParams() override; | ||||
| private: | private: | ||||
| uint8_t min_bit_; | |||||
| uint8_t max_bit_; | |||||
| std::vector<uint8_t> bit_range_; | |||||
| }; | }; | ||||
| class RandomRotationOperation : public TensorOperation { | class RandomRotationOperation : public TensorOperation { | ||||
| @@ -27,7 +27,7 @@ namespace mindspore { | |||||
| namespace dataset { | namespace dataset { | ||||
| const std::vector<float_t> RandomAffineOp::kDegreesRange = {0.0, 0.0}; | const std::vector<float_t> RandomAffineOp::kDegreesRange = {0.0, 0.0}; | ||||
| const std::vector<float_t> RandomAffineOp::kTranslationPercentages = {0.0, 0.0}; | |||||
| const std::vector<float_t> RandomAffineOp::kTranslationPercentages = {0.0, 0.0, 0.0, 0.0}; | |||||
| const std::vector<float_t> RandomAffineOp::kScaleRange = {1.0, 1.0}; | const std::vector<float_t> RandomAffineOp::kScaleRange = {1.0, 1.0}; | ||||
| const std::vector<float_t> RandomAffineOp::kShearRanges = {0.0, 0.0, 0.0, 0.0}; | const std::vector<float_t> RandomAffineOp::kShearRanges = {0.0, 0.0, 0.0, 0.0}; | ||||
| const InterpolationMode RandomAffineOp::kDefInterpolation = InterpolationMode::kNearestNeighbour; | const InterpolationMode RandomAffineOp::kDefInterpolation = InterpolationMode::kNearestNeighbour; | ||||
| @@ -50,14 +50,16 @@ Status RandomAffineOp::Compute(const std::shared_ptr<Tensor> &input, std::shared | |||||
| IO_CHECK(input, output); | IO_CHECK(input, output); | ||||
| dsize_t height = input->shape()[0]; | dsize_t height = input->shape()[0]; | ||||
| dsize_t width = input->shape()[1]; | dsize_t width = input->shape()[1]; | ||||
| float_t max_dx = translate_range_[0] * height; | |||||
| float_t max_dy = translate_range_[1] * width; | |||||
| float_t min_dx = translate_range_[0] * width; | |||||
| float_t max_dx = translate_range_[1] * width; | |||||
| float_t min_dy = translate_range_[2] * height; | |||||
| float_t max_dy = translate_range_[3] * height; | |||||
| float_t degrees = 0.0; | float_t degrees = 0.0; | ||||
| RETURN_IF_NOT_OK(GenerateRealNumber(degrees_range_[0], degrees_range_[1], &rnd_, °rees)); | RETURN_IF_NOT_OK(GenerateRealNumber(degrees_range_[0], degrees_range_[1], &rnd_, °rees)); | ||||
| float_t translation_x = 0.0; | float_t translation_x = 0.0; | ||||
| RETURN_IF_NOT_OK(GenerateRealNumber(-1 * max_dx, max_dx, &rnd_, &translation_x)); | |||||
| RETURN_IF_NOT_OK(GenerateRealNumber(min_dx, max_dx, &rnd_, &translation_x)); | |||||
| float_t translation_y = 0.0; | float_t translation_y = 0.0; | ||||
| RETURN_IF_NOT_OK(GenerateRealNumber(-1 * max_dy, max_dy, &rnd_, &translation_y)); | |||||
| RETURN_IF_NOT_OK(GenerateRealNumber(min_dy, max_dy, &rnd_, &translation_y)); | |||||
| float_t scale = 1.0; | float_t scale = 1.0; | ||||
| RETURN_IF_NOT_OK(GenerateRealNumber(scale_range_[0], scale_range_[1], &rnd_, &scale)); | RETURN_IF_NOT_OK(GenerateRealNumber(scale_range_[0], scale_range_[1], &rnd_, &scale)); | ||||
| float_t shear_x = 0.0; | float_t shear_x = 0.0; | ||||
| @@ -24,16 +24,16 @@ | |||||
| namespace mindspore { | namespace mindspore { | ||||
| namespace dataset { | namespace dataset { | ||||
| const uint8_t RandomPosterizeOp::kMinBit = 8; | |||||
| const uint8_t RandomPosterizeOp::kMaxBit = 8; | |||||
| const std::vector<uint8_t> RandomPosterizeOp::kBitRange = {4, 8}; | |||||
| RandomPosterizeOp::RandomPosterizeOp(uint8_t min_bit, uint8_t max_bit) | |||||
| : PosterizeOp(min_bit), min_bit_(min_bit), max_bit_(max_bit) { | |||||
| RandomPosterizeOp::RandomPosterizeOp(const std::vector<uint8_t> &bit_range) | |||||
| : PosterizeOp(bit_range[0]), bit_range_(bit_range) { | |||||
| rnd_.seed(GetSeed()); | rnd_.seed(GetSeed()); | ||||
| } | } | ||||
| Status RandomPosterizeOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) { | Status RandomPosterizeOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) { | ||||
| bit_ = (min_bit_ == max_bit_) ? min_bit_ : std::uniform_int_distribution<uint8_t>(min_bit_, max_bit_)(rnd_); | |||||
| bit_ = (bit_range_[0] == bit_range_[1]) ? bit_range_[0] | |||||
| : std::uniform_int_distribution<uint8_t>(bit_range_[0], bit_range_[1])(rnd_); | |||||
| return PosterizeOp::Compute(input, output); | return PosterizeOp::Compute(input, output); | ||||
| } | } | ||||
| } // namespace dataset | } // namespace dataset | ||||
| @@ -28,13 +28,11 @@ namespace dataset { | |||||
| class RandomPosterizeOp : public PosterizeOp { | class RandomPosterizeOp : public PosterizeOp { | ||||
| public: | public: | ||||
| /// Default values | /// Default values | ||||
| static const uint8_t kMinBit; | |||||
| static const uint8_t kMaxBit; | |||||
| static const std::vector<uint8_t> kBitRange; | |||||
| /// \brief Constructor | /// \brief Constructor | ||||
| /// \param[in] min_bit: Minimum bit in range | |||||
| /// \param[in] max_bit: Maximum bit in range | |||||
| explicit RandomPosterizeOp(uint8_t min_bit = kMinBit, uint8_t max_bit = kMaxBit); | |||||
| /// \param[in] bit_range: Minimum and maximum bits in range | |||||
| explicit RandomPosterizeOp(const std::vector<uint8_t> &bit_range = kBitRange); | |||||
| ~RandomPosterizeOp() override = default; | ~RandomPosterizeOp() override = default; | ||||
| @@ -45,8 +43,7 @@ class RandomPosterizeOp : public PosterizeOp { | |||||
| /// Member variables | /// Member variables | ||||
| private: | private: | ||||
| std::string kRandomPosterizeOp = "RandomPosterizeOp"; | std::string kRandomPosterizeOp = "RandomPosterizeOp"; | ||||
| uint8_t min_bit_; | |||||
| uint8_t max_bit_; | |||||
| std::vector<uint8_t> bit_range_; | |||||
| std::mt19937 rnd_; | std::mt19937 rnd_; | ||||
| }; | }; | ||||
| } // namespace dataset | } // namespace dataset | ||||
| @@ -64,6 +64,7 @@ DE_C_BORDER_TYPE = {Border.CONSTANT: cde.BorderType.DE_BORDER_CONSTANT, | |||||
| DE_C_IMAGE_BATCH_FORMAT = {ImageBatchFormat.NHWC: cde.ImageBatchFormat.DE_IMAGE_BATCH_FORMAT_NHWC, | DE_C_IMAGE_BATCH_FORMAT = {ImageBatchFormat.NHWC: cde.ImageBatchFormat.DE_IMAGE_BATCH_FORMAT_NHWC, | ||||
| ImageBatchFormat.NCHW: cde.ImageBatchFormat.DE_IMAGE_BATCH_FORMAT_NCHW} | ImageBatchFormat.NCHW: cde.ImageBatchFormat.DE_IMAGE_BATCH_FORMAT_NCHW} | ||||
| def parse_padding(padding): | def parse_padding(padding): | ||||
| if isinstance(padding, numbers.Number): | if isinstance(padding, numbers.Number): | ||||
| padding = [padding] * 4 | padding = [padding] * 4 | ||||
| @@ -237,11 +238,16 @@ class RandomAffine(cde.RandomAffineOp): | |||||
| degrees (int or float or sequence): Range of the rotation degrees. | degrees (int or float or sequence): Range of the rotation degrees. | ||||
| If degrees is a number, the range will be (-degrees, degrees). | If degrees is a number, the range will be (-degrees, degrees). | ||||
| If degrees is a sequence, it should be (min, max). | If degrees is a sequence, it should be (min, max). | ||||
| translate (sequence, optional): Sequence (tx, ty) of maximum translation in | |||||
| translate (sequence, optional): Sequence (tx_min, tx_max, ty_min, ty_max) of minimum/maximum translation in | |||||
| x(horizontal) and y(vertical) directions (default=None). | x(horizontal) and y(vertical) directions (default=None). | ||||
| The horizontal and vertical shift is selected randomly from the range: | The horizontal and vertical shift is selected randomly from the range: | ||||
| (-tx*width, tx*width) and (-ty*height, ty*height), respectively. | |||||
| If None, no translations gets applied. | |||||
| (tx_min*width, tx_max*width) and (ty_min*height, ty_max*height), respectively. | |||||
| If a tuple or list of size 2, then a translate parallel to the x axis in the range of | |||||
| (translate[0], translate[1]) is applied. | |||||
| If a tuple of list of size 4, then a translate parallel to x axis in the range of | |||||
| (translate[0], translate[1]) and a translate parallel to y axis in the range of | |||||
| (translate[2], translate[3]) are applied. | |||||
| If None, no translation is applied. | |||||
| scale (sequence, optional): Scaling factor interval (default=None, original scale is used). | scale (sequence, optional): Scaling factor interval (default=None, original scale is used). | ||||
| shear (int or float or sequence, optional): Range of shear factor (default=None). | shear (int or float or sequence, optional): Range of shear factor (default=None). | ||||
| If a number 'shear', then a shear parallel to the x axis in the range of (-shear, +shear) is applied. | If a number 'shear', then a shear parallel to the x axis in the range of (-shear, +shear) is applied. | ||||
| @@ -266,18 +272,18 @@ class RandomAffine(cde.RandomAffineOp): | |||||
| Raises: | Raises: | ||||
| ValueError: If degrees is negative. | ValueError: If degrees is negative. | ||||
| ValueError: If translation value is not between 0 and 1. | |||||
| ValueError: If translation value is not between -1 and 1. | |||||
| ValueError: If scale is not positive. | ValueError: If scale is not positive. | ||||
| ValueError: If shear is a number but is not positive. | ValueError: If shear is a number but is not positive. | ||||
| TypeError: If degrees is not a number or a list or a tuple. | TypeError: If degrees is not a number or a list or a tuple. | ||||
| If degrees is a list or tuple, its length is not 2. | If degrees is a list or tuple, its length is not 2. | ||||
| TypeError: If translate is specified but is not list or a tuple of length 2. | |||||
| TypeError: If translate is specified but is not list or a tuple of length 2 or 4. | |||||
| TypeError: If scale is not a list or tuple of length 2.'' | TypeError: If scale is not a list or tuple of length 2.'' | ||||
| TypeError: If shear is not a list or tuple of length 2 or 4. | TypeError: If shear is not a list or tuple of length 2 or 4. | ||||
| TypeError: If fill_value is not a single integer or a 3-tuple. | TypeError: If fill_value is not a single integer or a 3-tuple. | ||||
| Examples: | Examples: | ||||
| >>> c_transform.RandomAffine(degrees=15, translate=(0.1, 0.1), scale=(0.9, 1.1)) | |||||
| >>> c_transform.RandomAffine(degrees=15, translate=(-0.1, 0.1, 0, 0), scale=(0.9, 1.1)) | |||||
| """ | """ | ||||
| @check_random_affine | @check_random_affine | ||||
| @@ -300,7 +306,7 @@ class RandomAffine(cde.RandomAffineOp): | |||||
| # translation | # translation | ||||
| if translate is None: | if translate is None: | ||||
| translate = (0.0, 0.0) | |||||
| translate = (0.0, 0.0, 0.0, 0.0) | |||||
| # scale | # scale | ||||
| if scale is None: | if scale is None: | ||||
| @@ -467,7 +473,7 @@ class RandomPosterize(cde.RandomPosterizeOp): | |||||
| bits values should always be in range of [1,8], and include at | bits values should always be in range of [1,8], and include at | ||||
| least one integer values in the given range. It should be in | least one integer values in the given range. It should be in | ||||
| (min, max) or integer format. If min=max, then it is a single fixed | (min, max) or integer format. If min=max, then it is a single fixed | ||||
| magnitude operation (default=8). | |||||
| magnitude operation (default=[4,8]). | |||||
| """ | """ | ||||
| @check_posterize | @check_posterize | ||||
| @@ -475,7 +481,7 @@ class RandomPosterize(cde.RandomPosterizeOp): | |||||
| self.bits = bits | self.bits = bits | ||||
| if isinstance(bits, int): | if isinstance(bits, int): | ||||
| bits = (bits, bits) | bits = (bits, bits) | ||||
| super().__init__(bits[0], bits[1]) | |||||
| super().__init__(bits) | |||||
| class RandomVerticalFlip(cde.RandomVerticalFlipOp): | class RandomVerticalFlip(cde.RandomVerticalFlipOp): | ||||
| @@ -523,10 +523,10 @@ def check_random_affine(method): | |||||
| if translate is not None: | if translate is not None: | ||||
| type_check(translate, (list, tuple), "translate") | type_check(translate, (list, tuple), "translate") | ||||
| type_check_list(translate, (int, float), "translate") | type_check_list(translate, (int, float), "translate") | ||||
| if len(translate) != 2: | |||||
| raise TypeError("translate should be a list or tuple of length 2.") | |||||
| if len(translate) != 2 and len(translate) != 4: | |||||
| raise TypeError("translate should be a list or tuple of length 2 or 4.") | |||||
| for i, t in enumerate(translate): | for i, t in enumerate(translate): | ||||
| check_value(t, [0.0, 1.0], "translate at {0}".format(i)) | |||||
| check_value(t, [-1.0, 1.0], "translate at {0}".format(i)) | |||||
| if scale is not None: | if scale is not None: | ||||
| type_check(scale, (tuple, list), "scale") | type_check(scale, (tuple, list), "scale") | ||||
| @@ -620,10 +620,10 @@ TEST_F(MindDataTestPipeline, TestRandomAffineFail) { | |||||
| std::shared_ptr<TensorOperation> affine = vision::RandomAffine({0.0, 0.0}, {}); | std::shared_ptr<TensorOperation> affine = vision::RandomAffine({0.0, 0.0}, {}); | ||||
| EXPECT_EQ(affine, nullptr); | EXPECT_EQ(affine, nullptr); | ||||
| // Invalid number of values for translate | // Invalid number of values for translate | ||||
| affine = vision::RandomAffine({0.0, 0.0}, {1, 1, 1, 1}); | |||||
| affine = vision::RandomAffine({0.0, 0.0}, {1, 1, 1, 1, 1}); | |||||
| EXPECT_EQ(affine, nullptr); | EXPECT_EQ(affine, nullptr); | ||||
| // Invalid number of values for shear | // Invalid number of values for shear | ||||
| affine = vision::RandomAffine({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0, 10.0}); | |||||
| affine = vision::RandomAffine({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0}); | |||||
| EXPECT_EQ(affine, nullptr); | EXPECT_EQ(affine, nullptr); | ||||
| } | } | ||||
| @@ -642,7 +642,7 @@ TEST_F(MindDataTestPipeline, TestRandomAffineSuccess1) { | |||||
| // Create objects for the tensor ops | // Create objects for the tensor ops | ||||
| std::shared_ptr<TensorOperation> affine = | std::shared_ptr<TensorOperation> affine = | ||||
| vision::RandomAffine({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0, 10.0, 20.0, 20.0}); | |||||
| vision::RandomAffine({30.0, 30.0}, {-1.0, 1.0, -1.0, 1.0}, {2.0, 2.0}, {10.0, 10.0, 20.0, 20.0}); | |||||
| EXPECT_NE(affine, nullptr); | EXPECT_NE(affine, nullptr); | ||||
| // Create a Map operation on ds | // Create a Map operation on ds | ||||
| @@ -844,13 +844,16 @@ TEST_F(MindDataTestPipeline, TestRandomPosterizeFail) { | |||||
| // Create objects for the tensor ops | // Create objects for the tensor ops | ||||
| // Invalid max > 8 | // Invalid max > 8 | ||||
| std::shared_ptr<TensorOperation> posterize = vision::RandomPosterize(1, 9); | |||||
| std::shared_ptr<TensorOperation> posterize = vision::RandomPosterize({1, 9}); | |||||
| EXPECT_EQ(posterize, nullptr); | EXPECT_EQ(posterize, nullptr); | ||||
| // Invalid min < 1 | // Invalid min < 1 | ||||
| posterize = vision::RandomPosterize(0, 8); | |||||
| posterize = vision::RandomPosterize({0, 8}); | |||||
| EXPECT_EQ(posterize, nullptr); | EXPECT_EQ(posterize, nullptr); | ||||
| // min > max | // min > max | ||||
| posterize = vision::RandomPosterize(8, 1); | |||||
| posterize = vision::RandomPosterize({8, 1}); | |||||
| EXPECT_EQ(posterize, nullptr); | |||||
| // empty | |||||
| posterize = vision::RandomPosterize({}); | |||||
| EXPECT_EQ(posterize, nullptr); | EXPECT_EQ(posterize, nullptr); | ||||
| } | } | ||||
| @@ -869,7 +872,7 @@ TEST_F(MindDataTestPipeline, TestRandomPosterizeSuccess1) { | |||||
| // Create objects for the tensor ops | // Create objects for the tensor ops | ||||
| std::shared_ptr<TensorOperation> posterize = | std::shared_ptr<TensorOperation> posterize = | ||||
| vision::RandomPosterize(1, 4); | |||||
| vision::RandomPosterize({1, 4}); | |||||
| EXPECT_NE(posterize, nullptr); | EXPECT_NE(posterize, nullptr); | ||||
| // Create a Map operation on ds | // Create a Map operation on ds | ||||
| @@ -33,8 +33,9 @@ TEST_F(MindDataTestRandomAffineOp, TestOp1) { | |||||
| MS_LOG(INFO) << "Doing testRandomAffineOp."; | MS_LOG(INFO) << "Doing testRandomAffineOp."; | ||||
| std::shared_ptr<Tensor> output_tensor; | std::shared_ptr<Tensor> output_tensor; | ||||
| std::unique_ptr<RandomAffineOp> op(new RandomAffineOp({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0, 10.0, 20.0, 20.0}, | |||||
| InterpolationMode::kNearestNeighbour, {255, 0, 0})); | |||||
| std::unique_ptr<RandomAffineOp> op(new RandomAffineOp({30.0, 30.0}, {0.0, 0.0, 0.0, 0.0}, {2.0, 2.0}, | |||||
| {10.0, 10.0, 20.0, 20.0}, InterpolationMode::kNearestNeighbour, | |||||
| {255, 0, 0})); | |||||
| EXPECT_TRUE(op->OneToOne()); | EXPECT_TRUE(op->OneToOne()); | ||||
| Status s = op->Compute(input_tensor_, &output_tensor); | Status s = op->Compute(input_tensor_, &output_tensor); | ||||
| EXPECT_TRUE(s.IsOk()); | EXPECT_TRUE(s.IsOk()); | ||||
| @@ -33,7 +33,7 @@ TEST_F(MindDataTestRandomPosterizeOp, TestOp1) { | |||||
| MS_LOG(INFO) << "Doing testRandomPosterize."; | MS_LOG(INFO) << "Doing testRandomPosterize."; | ||||
| std::shared_ptr<Tensor> output_tensor; | std::shared_ptr<Tensor> output_tensor; | ||||
| std::unique_ptr<RandomPosterizeOp> op(new RandomPosterizeOp(1, 1)); | |||||
| std::unique_ptr<RandomPosterizeOp> op(new RandomPosterizeOp({1, 1})); | |||||
| EXPECT_TRUE(op->OneToOne()); | EXPECT_TRUE(op->OneToOne()); | ||||
| Status s = op->Compute(input_tensor_, &output_tensor); | Status s = op->Compute(input_tensor_, &output_tensor); | ||||
| EXPECT_TRUE(s.IsOk()); | EXPECT_TRUE(s.IsOk()); | ||||
| @@ -75,7 +75,7 @@ def test_random_affine_op_c(plot=False): | |||||
| # define map operations | # define map operations | ||||
| transforms1 = [ | transforms1 = [ | ||||
| c_vision.Decode(), | c_vision.Decode(), | ||||
| c_vision.RandomAffine(degrees=15, translate=(0.1, 0.1), scale=(0.9, 1.1)) | |||||
| c_vision.RandomAffine(degrees=0, translate=(0.5, 0.5, 0, 0)) | |||||
| ] | ] | ||||
| transforms2 = [ | transforms2 = [ | ||||
| @@ -139,7 +139,7 @@ def test_random_affine_c_md5(): | |||||
| # define map operations | # define map operations | ||||
| transforms = [ | transforms = [ | ||||
| c_vision.Decode(), | c_vision.Decode(), | ||||
| c_vision.RandomAffine(degrees=(-5, 15), translate=(0.1, 0.3), | |||||
| c_vision.RandomAffine(degrees=(-5, 15), translate=(-0.1, 0.1, -0.3, 0.3), | |||||
| scale=(0.9, 1.1), shear=(-10, 10, -5, 5)) | scale=(0.9, 1.1), shear=(-10, 10, -5, 5)) | ||||
| ] | ] | ||||
| @@ -156,9 +156,35 @@ def test_random_affine_c_md5(): | |||||
| ds.config.set_num_parallel_workers((original_num_parallel_workers)) | ds.config.set_num_parallel_workers((original_num_parallel_workers)) | ||||
| def test_random_affine_default_c_md5(): | |||||
| """ | |||||
| Test RandomAffine C Op (default params) with md5 comparison | |||||
| """ | |||||
| logger.info("test_random_affine_default_c_md5") | |||||
| original_seed = config_get_set_seed(1) | |||||
| original_num_parallel_workers = config_get_set_num_parallel_workers(1) | |||||
| # define map operations | |||||
| transforms = [ | |||||
| c_vision.Decode(), | |||||
| c_vision.RandomAffine(degrees=0) | |||||
| ] | |||||
| # Generate dataset | |||||
| data = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False) | |||||
| data = data.map(input_columns=["image"], operations=transforms) | |||||
| # check results with md5 comparison | |||||
| filename = "random_affine_01_default_c_result.npz" | |||||
| save_and_check_md5(data, filename, generate_golden=GENERATE_GOLDEN) | |||||
| # Restore configuration | |||||
| ds.config.set_seed(original_seed) | |||||
| ds.config.set_num_parallel_workers((original_num_parallel_workers)) | |||||
| def test_random_affine_py_exception_non_pil_images(): | def test_random_affine_py_exception_non_pil_images(): | ||||
| """ | """ | ||||
| Test RandomAffine: input img is ndarray and not PIL, expected to raise TypeError | |||||
| Test RandomAffine: input img is ndarray and not PIL, expected to raise RuntimeError | |||||
| """ | """ | ||||
| logger.info("test_random_affine_exception_negative_degrees") | logger.info("test_random_affine_exception_negative_degrees") | ||||
| dataset = ds.MnistDataset(MNIST_DATA_DIR, num_parallel_workers=3) | dataset = ds.MnistDataset(MNIST_DATA_DIR, num_parallel_workers=3) | ||||
| @@ -188,14 +214,20 @@ def test_random_affine_exception_negative_degrees(): | |||||
| def test_random_affine_exception_translation_range(): | def test_random_affine_exception_translation_range(): | ||||
| """ | """ | ||||
| Test RandomAffine: translation value is not in [0, 1], expected to raise ValueError | |||||
| Test RandomAffine: translation value is not in [-1, 1], expected to raise ValueError | |||||
| """ | """ | ||||
| logger.info("test_random_affine_exception_translation_range") | logger.info("test_random_affine_exception_translation_range") | ||||
| try: | try: | ||||
| _ = py_vision.RandomAffine(degrees=15, translate=(0.1, 1.5)) | |||||
| _ = c_vision.RandomAffine(degrees=15, translate=(0.1, 1.5)) | |||||
| except ValueError as e: | |||||
| logger.info("Got an exception in DE: {}".format(str(e))) | |||||
| assert str(e) == "Input translate at 1 is not within the required interval of (-1.0 to 1.0)." | |||||
| logger.info("test_random_affine_exception_translation_range") | |||||
| try: | |||||
| _ = c_vision.RandomAffine(degrees=15, translate=(-2, 1.5)) | |||||
| except ValueError as e: | except ValueError as e: | ||||
| logger.info("Got an exception in DE: {}".format(str(e))) | logger.info("Got an exception in DE: {}".format(str(e))) | ||||
| assert str(e) == "Input translate at 1 is not within the required interval of (0.0 to 1.0)." | |||||
| assert str(e) == "Input translate at 0 is not within the required interval of (-1.0 to 1.0)." | |||||
| def test_random_affine_exception_scale_value(): | def test_random_affine_exception_scale_value(): | ||||
| @@ -308,6 +340,7 @@ if __name__ == "__main__": | |||||
| test_random_affine_op_c(plot=True) | test_random_affine_op_c(plot=True) | ||||
| test_random_affine_md5() | test_random_affine_md5() | ||||
| test_random_affine_c_md5() | test_random_affine_c_md5() | ||||
| test_random_affine_default_c_md5() | |||||
| test_random_affine_py_exception_non_pil_images() | test_random_affine_py_exception_non_pil_images() | ||||
| test_random_affine_exception_negative_degrees() | test_random_affine_exception_negative_degrees() | ||||
| test_random_affine_exception_translation_range() | test_random_affine_exception_translation_range() | ||||
| @@ -114,6 +114,47 @@ def test_random_posterize_op_fixed_point_c(plot=False, run_golden=True): | |||||
| visualize_list(image_original, image_posterize) | visualize_list(image_original, image_posterize) | ||||
| def test_random_posterize_default_c_md5(plot=False, run_golden=True): | |||||
| """ | |||||
| Test RandomPosterize C Op (default params) with md5 comparison | |||||
| """ | |||||
| logger.info("test_random_posterize_default_c_md5") | |||||
| original_seed = config_get_set_seed(5) | |||||
| original_num_parallel_workers = config_get_set_num_parallel_workers(1) | |||||
| # define map operations | |||||
| transforms1 = [ | |||||
| c_vision.Decode(), | |||||
| c_vision.RandomPosterize() | |||||
| ] | |||||
| # First dataset | |||||
| data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False) | |||||
| data1 = data1.map(input_columns=["image"], operations=transforms1) | |||||
| # Second dataset | |||||
| data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False) | |||||
| data2 = data2.map(input_columns=["image"], operations=[c_vision.Decode()]) | |||||
| image_posterize = [] | |||||
| image_original = [] | |||||
| for item1, item2 in zip(data1.create_dict_iterator(), data2.create_dict_iterator()): | |||||
| image1 = item1["image"] | |||||
| image2 = item2["image"] | |||||
| image_posterize.append(image1) | |||||
| image_original.append(image2) | |||||
| if run_golden: | |||||
| # check results with md5 comparison | |||||
| filename = "random_posterize_01_default_result_c.npz" | |||||
| save_and_check_md5(data1, filename, generate_golden=GENERATE_GOLDEN) | |||||
| if plot: | |||||
| visualize_list(image_original, image_posterize) | |||||
| # Restore configuration | |||||
| ds.config.set_seed(original_seed) | |||||
| ds.config.set_num_parallel_workers(original_num_parallel_workers) | |||||
| def test_random_posterize_exception_bit(): | def test_random_posterize_exception_bit(): | ||||
| """ | """ | ||||
| Test RandomPosterize: out of range input bits and invalid type | Test RandomPosterize: out of range input bits and invalid type | ||||
| @@ -150,6 +191,7 @@ def test_random_posterize_exception_bit(): | |||||
| logger.info("Got an exception in DE: {}".format(str(e))) | logger.info("Got an exception in DE: {}".format(str(e))) | ||||
| assert str(e) == "Size of bits should be a single integer or a list/tuple (min, max) of length 2." | assert str(e) == "Size of bits should be a single integer or a list/tuple (min, max) of length 2." | ||||
| def test_rescale_with_random_posterize(): | def test_rescale_with_random_posterize(): | ||||
| """ | """ | ||||
| Test RandomPosterize: only support CV_8S/CV_8U | Test RandomPosterize: only support CV_8S/CV_8U | ||||
| @@ -171,8 +213,10 @@ def test_rescale_with_random_posterize(): | |||||
| logger.info("Got an exception in DE: {}".format(str(e))) | logger.info("Got an exception in DE: {}".format(str(e))) | ||||
| assert "Input image data type can not be float" in str(e) | assert "Input image data type can not be float" in str(e) | ||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||
| test_random_posterize_op_c(plot=False, run_golden=False) | test_random_posterize_op_c(plot=False, run_golden=False) | ||||
| test_random_posterize_op_fixed_point_c(plot=False) | test_random_posterize_op_fixed_point_c(plot=False) | ||||
| test_random_posterize_default_c_md5(plot=False) | |||||
| test_random_posterize_exception_bit() | test_random_posterize_exception_bit() | ||||
| test_rescale_with_random_posterize() | test_rescale_with_random_posterize() | ||||