RandomResizedCrop C API

pull/7266/head
Mahdi 4 years ago
parent a75665ce49
commit c8333accfc

@ -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"
@ -235,6 +236,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,
@ -898,6 +911,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;
@ -226,6 +227,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
@ -545,6 +563,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}, std::shared_ptr<TensorOperation> normalize =
{70.0, 68.0, 71.0}); 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});

Loading…
Cancel
Save