Merge pull request !7266 from MahdiRahmaniHanzaki/c-apitags/v1.1.0
| @@ -31,6 +31,7 @@ | |||||
| #include "minddata/dataset/kernels/image/random_affine_op.h" | #include "minddata/dataset/kernels/image/random_affine_op.h" | ||||
| #include "minddata/dataset/kernels/image/random_color_op.h" | #include "minddata/dataset/kernels/image/random_color_op.h" | ||||
| #include "minddata/dataset/kernels/image/random_color_adjust_op.h" | #include "minddata/dataset/kernels/image/random_color_adjust_op.h" | ||||
| #include "minddata/dataset/kernels/image/random_crop_and_resize_op.h" | |||||
| #include "minddata/dataset/kernels/image/random_crop_op.h" | #include "minddata/dataset/kernels/image/random_crop_op.h" | ||||
| #include "minddata/dataset/kernels/image/random_crop_decode_resize_op.h" | #include "minddata/dataset/kernels/image/random_crop_decode_resize_op.h" | ||||
| #include "minddata/dataset/kernels/image/random_horizontal_flip_op.h" | #include "minddata/dataset/kernels/image/random_horizontal_flip_op.h" | ||||
| @@ -236,6 +237,18 @@ std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint | |||||
| return op; | return op; | ||||
| } | } | ||||
| // Function to create RandomResizedCropOperation. | |||||
| std::shared_ptr<RandomResizedCropOperation> RandomResizedCrop(std::vector<int32_t> size, std::vector<float> scale, | |||||
| std::vector<float> ratio, InterpolationMode interpolation, | |||||
| int32_t max_attempts) { | |||||
| auto op = std::make_shared<RandomResizedCropOperation>(size, scale, ratio, interpolation, max_attempts); | |||||
| // Input validation | |||||
| if (!op->ValidateParams()) { | |||||
| return nullptr; | |||||
| } | |||||
| return op; | |||||
| } | |||||
| // Function to create RandomRotationOperation. | // Function to create RandomRotationOperation. | ||||
| std::shared_ptr<RandomRotationOperation> RandomRotation(std::vector<float> degrees, InterpolationMode resample, | std::shared_ptr<RandomRotationOperation> RandomRotation(std::vector<float> degrees, InterpolationMode resample, | ||||
| bool expand, std::vector<float> center, | bool expand, std::vector<float> center, | ||||
| @@ -909,6 +922,43 @@ std::shared_ptr<TensorOp> RandomPosterizeOperation::Build() { | |||||
| return tensor_op; | return tensor_op; | ||||
| } | } | ||||
| // RandomResizedCropOperation | |||||
| RandomResizedCropOperation::RandomResizedCropOperation(std::vector<int32_t> size, std::vector<float> scale, | |||||
| std::vector<float> ratio, InterpolationMode interpolation, | |||||
| int32_t max_attempts) | |||||
| : size_(size), scale_(scale), ratio_(ratio), interpolation_(interpolation), max_attempts_(max_attempts) {} | |||||
| bool RandomResizedCropOperation::ValidateParams() { | |||||
| if (size_.size() != 2 && size_.size() != 1) { | |||||
| MS_LOG(ERROR) << "RandomResizedCrop: size variable must have a length of 1 or 2 but it has a length of: " | |||||
| << size_.size(); | |||||
| return false; | |||||
| } | |||||
| if (size_[0] < 0 || (size_.size() == 2 && size_[1] < 0)) { | |||||
| MS_LOG(ERROR) << "RandomResizedCrop: size variable must only contain positive integers. However, it is: " << size_; | |||||
| return false; | |||||
| } | |||||
| if (scale_.size() != 2 || scale_[1] < scale_[0]) { | |||||
| MS_LOG(ERROR) | |||||
| << "RandomResizedCrop: scale variable must have a size of two in the format of (min, max). However, it is: " | |||||
| << scale_; | |||||
| return false; | |||||
| } | |||||
| if (ratio_.size() != 2 || ratio_[1] < ratio_[0]) { | |||||
| MS_LOG(ERROR) << "RandomResizedCrop: ratio variable must be in the format of (min, max). However , it is: " | |||||
| << ratio_; | |||||
| return false; | |||||
| } | |||||
| return true; | |||||
| } | |||||
| std::shared_ptr<TensorOp> RandomResizedCropOperation::Build() { | |||||
| int32_t height = size_[0], width = size_[0]; | |||||
| if (size_.size() == 2) width = size_[1]; | |||||
| std::shared_ptr<RandomCropAndResizeOp> tensor_op = std::make_shared<RandomCropAndResizeOp>( | |||||
| height, width, scale_[0], scale_[1], ratio_[0], ratio_[1], interpolation_, max_attempts_); | |||||
| return tensor_op; | |||||
| } | |||||
| // Function to create RandomRotationOperation. | // Function to create RandomRotationOperation. | ||||
| RandomRotationOperation::RandomRotationOperation(std::vector<float> degrees, InterpolationMode interpolation_mode, | RandomRotationOperation::RandomRotationOperation(std::vector<float> degrees, InterpolationMode interpolation_mode, | ||||
| bool expand, std::vector<float> center, | bool expand, std::vector<float> center, | ||||
| @@ -46,6 +46,7 @@ class RandomCropOperation; | |||||
| class RandomCropDecodeResizeOperation; | class RandomCropDecodeResizeOperation; | ||||
| class RandomHorizontalFlipOperation; | class RandomHorizontalFlipOperation; | ||||
| class RandomPosterizeOperation; | class RandomPosterizeOperation; | ||||
| class RandomResizedCropOperation; | |||||
| class RandomRotationOperation; | class RandomRotationOperation; | ||||
| class RandomSharpnessOperation; | class RandomSharpnessOperation; | ||||
| class RandomSolarizeOperation; | class RandomSolarizeOperation; | ||||
| @@ -227,6 +228,23 @@ std::shared_ptr<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob = | |||||
| /// \return Shared pointer to the current TensorOperation. | /// \return Shared pointer to the current TensorOperation. | ||||
| std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint8_t> &bit_range = {4, 8}); | std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint8_t> &bit_range = {4, 8}); | ||||
| /// \brief Function to create a RandomResizedCrop TensorOperation. | |||||
| /// \notes Crop the input image to a random size and aspect ratio. | |||||
| /// \param[in] size A vector representing the output size of the cropped image. | |||||
| /// If size is a single value, a square crop of size (size, size) is returned. | |||||
| /// If size has 2 values, it should be (height, width). | |||||
| /// \param[in] scale Range [min, max) of respective size of the original | |||||
| /// size to be cropped (default=(0.08, 1.0)) | |||||
| /// \param[in] ratio Range [min, max) of aspect ratio to be cropped | |||||
| /// (default=(3. / 4., 4. / 3.)). | |||||
| /// \param[in] interpolation Image interpolation mode (default=InterpolationMode::kLinear) | |||||
| /// \param[in] max_attempts The maximum number of attempts to propose a valid | |||||
| /// crop_area (default=10). If exceeded, fall back to use center_crop instead. | |||||
| /// \return Shared pointer to the current TensorOperation. | |||||
| std::shared_ptr<RandomResizedCropOperation> RandomResizedCrop( | |||||
| std::vector<int32_t> size, std::vector<float> scale = {0.08, 1.0}, std::vector<float> ratio = {3. / 4., 4. / 3.}, | |||||
| InterpolationMode interpolation = InterpolationMode::kLinear, int32_t max_attempts = 10); | |||||
| /// \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 | ||||
| /// \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 | ||||
| @@ -553,6 +571,27 @@ class RandomPosterizeOperation : public TensorOperation { | |||||
| std::vector<uint8_t> bit_range_; | std::vector<uint8_t> bit_range_; | ||||
| }; | }; | ||||
| class RandomResizedCropOperation : public TensorOperation { | |||||
| public: | |||||
| explicit RandomResizedCropOperation(std::vector<int32_t> size, std::vector<float> scale = {0.08, 1.0}, | |||||
| std::vector<float> ratio = {3. / 4., 4. / 3.}, | |||||
| InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, | |||||
| int32_t max_attempts = 10); | |||||
| ~RandomResizedCropOperation() = default; | |||||
| std::shared_ptr<TensorOp> Build() override; | |||||
| bool ValidateParams() override; | |||||
| private: | |||||
| std::vector<int32_t> size_; | |||||
| std::vector<float> scale_; | |||||
| std::vector<float> ratio_; | |||||
| InterpolationMode interpolation_; | |||||
| int32_t max_attempts_; | |||||
| }; | |||||
| class RandomRotationOperation : public TensorOperation { | class RandomRotationOperation : public TensorOperation { | ||||
| public: | public: | ||||
| RandomRotationOperation(std::vector<float> degrees, InterpolationMode interpolation_mode, bool expand, | RandomRotationOperation(std::vector<float> degrees, InterpolationMode interpolation_mode, bool expand, | ||||
| @@ -228,6 +228,133 @@ TEST_F(MindDataTestPipeline, TestCutMixBatchFail3) { | |||||
| EXPECT_EQ(cutmix_batch_op, nullptr); | EXPECT_EQ(cutmix_batch_op, nullptr); | ||||
| } | } | ||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropSuccess1) { | |||||
| // Testing RandomResizedCrop with default values | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5}); | |||||
| EXPECT_NE(random_resized_crop, nullptr); | |||||
| // Create a Map operation on ds | |||||
| ds = ds->Map({random_resized_crop}, {"image"}); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create an iterator over the result of the above dataset | |||||
| // This will trigger the creation of the Execution Tree and launch it. | |||||
| std::shared_ptr<Iterator> iter = ds->CreateIterator(); | |||||
| EXPECT_NE(iter, nullptr); | |||||
| // Iterate the dataset and get each row | |||||
| std::unordered_map<std::string, std::shared_ptr<Tensor>> row; | |||||
| iter->GetNextRow(&row); | |||||
| uint64_t i = 0; | |||||
| while (row.size() != 0) { | |||||
| i++; | |||||
| auto image = row["image"]; | |||||
| MS_LOG(INFO) << "Tensor image shape: " << image->shape(); | |||||
| EXPECT_EQ(image->shape()[0] == 5 && image->shape()[1] == 5, true); | |||||
| iter->GetNextRow(&row); | |||||
| } | |||||
| EXPECT_EQ(i, 10); | |||||
| // Manually terminate the pipeline | |||||
| iter->Stop(); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropSuccess2) { | |||||
| // Testing RandomResizedCrop with non-default values | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = | |||||
| vision::RandomResizedCrop({5, 10}, {0.25, 0.75}, {0.5, 1.25}, mindspore::dataset::InterpolationMode::kArea, 20); | |||||
| EXPECT_NE(random_resized_crop, nullptr); | |||||
| // Create a Map operation on ds | |||||
| ds = ds->Map({random_resized_crop}, {"image"}); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create an iterator over the result of the above dataset | |||||
| // This will trigger the creation of the Execution Tree and launch it. | |||||
| std::shared_ptr<Iterator> iter = ds->CreateIterator(); | |||||
| EXPECT_NE(iter, nullptr); | |||||
| // Iterate the dataset and get each row | |||||
| std::unordered_map<std::string, std::shared_ptr<Tensor>> row; | |||||
| iter->GetNextRow(&row); | |||||
| uint64_t i = 0; | |||||
| while (row.size() != 0) { | |||||
| i++; | |||||
| auto image = row["image"]; | |||||
| MS_LOG(INFO) << "Tensor image shape: " << image->shape(); | |||||
| EXPECT_EQ(image->shape()[0] == 5 && image->shape()[1] == 10, true); | |||||
| iter->GetNextRow(&row); | |||||
| } | |||||
| EXPECT_EQ(i, 10); | |||||
| // Manually terminate the pipeline | |||||
| iter->Stop(); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropFail1) { | |||||
| // This should fail because size has negative value | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5, -10}); | |||||
| EXPECT_EQ(random_resized_crop, nullptr); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropFail2) { | |||||
| // This should fail because scale isn't in {min, max} format | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5, 10}, {4, 3}); | |||||
| EXPECT_EQ(random_resized_crop, nullptr); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropFail3) { | |||||
| // This should fail because ratio isn't in {min, max} format | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5, 10}, {4, 5}, {7, 6}); | |||||
| EXPECT_EQ(random_resized_crop, nullptr); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestRandomResizedCropFail4) { | |||||
| // This should fail because scale has a size of more than 2 | |||||
| // Create a Cifar10 Dataset | |||||
| std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; | |||||
| std::shared_ptr<Dataset> ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); | |||||
| EXPECT_NE(ds, nullptr); | |||||
| // Create objects for the tensor ops | |||||
| std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5, 10, 20}, {4, 5}, {7, 6}); | |||||
| EXPECT_EQ(random_resized_crop, nullptr); | |||||
| } | |||||
| TEST_F(MindDataTestPipeline, TestCutOut) { | TEST_F(MindDataTestPipeline, TestCutOut) { | ||||
| // Create an ImageFolder Dataset | // Create an ImageFolder Dataset | ||||
| std::string folder_path = datasets_root_path_ + "/testPK/data/"; | std::string folder_path = datasets_root_path_ + "/testPK/data/"; | ||||
| @@ -1303,8 +1430,8 @@ TEST_F(MindDataTestPipeline, TestCenterCropFail) { | |||||
| TEST_F(MindDataTestPipeline, TestNormalizeFail) { | TEST_F(MindDataTestPipeline, TestNormalizeFail) { | ||||
| MS_LOG(INFO) << "Doing MindDataTestPipeline-TestNormalize with invalid params."; | MS_LOG(INFO) << "Doing MindDataTestPipeline-TestNormalize with invalid params."; | ||||
| // mean value 0.0 | // mean value 0.0 | ||||
| std::shared_ptr<TensorOperation> normalize = mindspore::dataset::api::vision::Normalize({0.0, 115.0, 100.0}, | |||||
| {70.0, 68.0, 71.0}); | |||||
| std::shared_ptr<TensorOperation> normalize = | |||||
| mindspore::dataset::api::vision::Normalize({0.0, 115.0, 100.0}, {70.0, 68.0, 71.0}); | |||||
| EXPECT_EQ(normalize, nullptr); | EXPECT_EQ(normalize, nullptr); | ||||
| // std value at 0.0 | // std value at 0.0 | ||||
| normalize = mindspore::dataset::api::vision::Normalize({121.0, 115.0, 100.0}, {0.0, 68.0, 71.0}); | normalize = mindspore::dataset::api::vision::Normalize({121.0, 115.0, 100.0}, {0.0, 68.0, 71.0}); | ||||