diff --git a/mindspore/ccsrc/minddata/dataset/api/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/api/CMakeLists.txt index d3fd8bc434..3888df6d47 100644 --- a/mindspore/ccsrc/minddata/dataset/api/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/api/CMakeLists.txt @@ -28,4 +28,5 @@ add_library(cpp-API OBJECT transforms.cc samplers.cc text.cc + vision.cc ) diff --git a/mindspore/ccsrc/minddata/dataset/api/text.cc b/mindspore/ccsrc/minddata/dataset/api/text.cc index 31247d1b7b..3df2585509 100644 --- a/mindspore/ccsrc/minddata/dataset/api/text.cc +++ b/mindspore/ccsrc/minddata/dataset/api/text.cc @@ -20,8 +20,13 @@ namespace mindspore { namespace dataset { namespace api { + +// Transform operations for text. namespace text { +// FUNCTIONS TO CREATE TEXT OPERATIONS +// (In alphabetical order) + std::shared_ptr Lookup(const std::shared_ptr &vocab, const std::string &unknown_token, const DataType &data_type) { auto op = std::make_shared(vocab, unknown_token, data_type); @@ -32,6 +37,12 @@ std::shared_ptr Lookup(const std::shared_ptr &vocab, con return op; } +/* ####################################### Validator Functions ############################################ */ + +/* ####################################### Derived TensorOperation classes ################################# */ + +// (In alphabetical order) + // LookupOperation LookupOperation::LookupOperation(const std::shared_ptr &vocab, const std::string &unknown_token, const DataType &data_type) diff --git a/mindspore/ccsrc/minddata/dataset/api/transforms.cc b/mindspore/ccsrc/minddata/dataset/api/transforms.cc index b2c2a0cd5c..afd22f380f 100644 --- a/mindspore/ccsrc/minddata/dataset/api/transforms.cc +++ b/mindspore/ccsrc/minddata/dataset/api/transforms.cc @@ -17,31 +17,8 @@ #include "minddata/dataset/include/transforms.h" #include "minddata/dataset/kernels/image/image_utils.h" -#include "minddata/dataset/kernels/image/center_crop_op.h" -#include "minddata/dataset/kernels/image/crop_op.h" -#include "minddata/dataset/kernels/image/cutmix_batch_op.h" -#include "minddata/dataset/kernels/image/cut_out_op.h" -#include "minddata/dataset/kernels/image/decode_op.h" -#include "minddata/dataset/kernels/image/hwc_to_chw_op.h" -#include "minddata/dataset/kernels/image/mixup_batch_op.h" -#include "minddata/dataset/kernels/image/normalize_op.h" +// Kernel data headers (in alphabetical order) #include "minddata/dataset/kernels/data/one_hot_op.h" -#include "minddata/dataset/kernels/image/pad_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_adjust_op.h" -#include "minddata/dataset/kernels/image/random_crop_op.h" -#include "minddata/dataset/kernels/image/random_horizontal_flip_op.h" -#include "minddata/dataset/kernels/image/random_posterize_op.h" -#include "minddata/dataset/kernels/image/random_rotation_op.h" -#include "minddata/dataset/kernels/image/random_sharpness_op.h" -#include "minddata/dataset/kernels/image/random_solarize_op.h" -#include "minddata/dataset/kernels/image/random_vertical_flip_op.h" -#include "minddata/dataset/kernels/image/resize_op.h" -#include "minddata/dataset/kernels/image/rgba_to_bgr_op.h" -#include "minddata/dataset/kernels/image/rgba_to_rgb_op.h" -#include "minddata/dataset/kernels/image/swap_red_blue_op.h" -#include "minddata/dataset/kernels/image/uniform_aug_op.h" namespace mindspore { namespace dataset { @@ -49,88 +26,11 @@ namespace api { TensorOperation::TensorOperation() {} -// Transform operations for computer vision. -namespace vision { +// Transform operations for data. +namespace transforms { -// Function to create CenterCropOperation. -std::shared_ptr CenterCrop(std::vector size) { - auto op = std::make_shared(size); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create CropOperation. -std::shared_ptr Crop(std::vector coordinates, std::vector size) { - auto op = std::make_shared(coordinates, size); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create CutMixBatchOperation. -std::shared_ptr CutMixBatch(ImageBatchFormat image_batch_format, float alpha, float prob) { - auto op = std::make_shared(image_batch_format, alpha, prob); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create CutOutOp. -std::shared_ptr CutOut(int32_t length, int32_t num_patches) { - auto op = std::make_shared(length, num_patches); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create DecodeOperation. -std::shared_ptr Decode(bool rgb) { - auto op = std::make_shared(rgb); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create HwcToChwOperation. -std::shared_ptr HWC2CHW() { - auto op = std::make_shared(); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create MixUpBatchOperation. -std::shared_ptr MixUpBatch(float alpha) { - auto op = std::make_shared(alpha); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create NormalizeOperation. -std::shared_ptr Normalize(std::vector mean, std::vector std) { - auto op = std::make_shared(mean, std); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} +// FUNCTIONS TO CREATE DATA TRANSFORM OPERATIONS +// (In alphabetical order) // Function to create OneHotOperation. std::shared_ptr OneHot(int32_t num_classes) { @@ -142,373 +42,11 @@ std::shared_ptr OneHot(int32_t num_classes) { return op; } -// Function to create PadOperation. -std::shared_ptr Pad(std::vector padding, std::vector fill_value, - BorderType padding_mode) { - auto op = std::make_shared(padding, fill_value, padding_mode); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomColorOperation. -std::shared_ptr RandomColor(float t_lb, float t_ub) { - auto op = std::make_shared(t_lb, t_ub); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -std::shared_ptr RandomColorOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(t_lb_, t_ub_); - return tensor_op; -} - -// Function to create RandomColorAdjustOperation. -std::shared_ptr RandomColorAdjust(std::vector brightness, - std::vector contrast, - std::vector saturation, std::vector hue) { - auto op = std::make_shared(brightness, contrast, saturation, hue); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomAffineOperation. -std::shared_ptr RandomAffine(const std::vector °rees, - const std::vector &translate_range, - const std::vector &scale_range, - const std::vector &shear_ranges, - InterpolationMode interpolation, - const std::vector &fill_value) { - auto op = std::make_shared(degrees, translate_range, scale_range, shear_ranges, interpolation, - fill_value); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomCropOperation. -std::shared_ptr RandomCrop(std::vector size, std::vector padding, - bool pad_if_needed, std::vector fill_value, - BorderType padding_mode) { - auto op = std::make_shared(size, padding, pad_if_needed, fill_value, padding_mode); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomHorizontalFlipOperation. -std::shared_ptr RandomHorizontalFlip(float prob) { - auto op = std::make_shared(prob); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomPosterizeOperation. -std::shared_ptr RandomPosterize(const std::vector &bit_range) { - auto op = std::make_shared(bit_range); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomRotationOperation. -std::shared_ptr RandomRotation(std::vector degrees, InterpolationMode resample, - bool expand, std::vector center, - std::vector fill_value) { - auto op = std::make_shared(degrees, resample, expand, center, fill_value); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomSolarizeOperation. -std::shared_ptr RandomSolarize(std::vector threshold) { - auto op = std::make_shared(threshold); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomSharpnessOperation. -std::shared_ptr RandomSharpness(std::vector degrees) { - auto op = std::make_shared(degrees); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RandomVerticalFlipOperation. -std::shared_ptr RandomVerticalFlip(float prob) { - auto op = std::make_shared(prob); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create ResizeOperation. -std::shared_ptr Resize(std::vector size, InterpolationMode interpolation) { - auto op = std::make_shared(size, interpolation); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RgbaToBgrOperation. -std::shared_ptr RGBA2BGR() { - auto op = std::make_shared(); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create RgbaToRgbOperation. -std::shared_ptr RGBA2RGB() { - auto op = std::make_shared(); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create SwapRedBlueOperation. -std::shared_ptr SwapRedBlue() { - auto op = std::make_shared(); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - -// Function to create UniformAugOperation. -std::shared_ptr UniformAugment(std::vector> transforms, - int32_t num_ops) { - auto op = std::make_shared(transforms, num_ops); - // Input validation - if (!op->ValidateParams()) { - return nullptr; - } - return op; -} - /* ####################################### Validator Functions ############################################ */ -bool CheckVectorPositive(const std::vector &size) { - for (int i = 0; i < size.size(); ++i) { - if (size[i] <= 0) return false; - } - return true; -} - -bool CmpFloat(const float &a, const float &b, float epsilon = 0.0000000001f) { return (std::fabs(a - b) < epsilon); } /* ####################################### Derived TensorOperation classes ################################# */ -// CenterCropOperation -CenterCropOperation::CenterCropOperation(std::vector size) : size_(size) {} - -bool CenterCropOperation::ValidateParams() { - if (size_.empty() || size_.size() > 2) { - MS_LOG(ERROR) << "CenterCrop: size vector has incorrect size."; - return false; - } - // We have to limit crop size due to library restrictions, optimized to only iterate over size_ once - for (int i = 0; i < size_.size(); ++i) { - if (size_[i] <= 0) { - MS_LOG(ERROR) << "CenterCrop: invalid size, size must be greater than 0, got: " << size_[i]; - return false; - } - if (size_[i] == INT_MAX) { - MS_LOG(ERROR) << "CenterCrop: invalid size, size too large, got: " << size_[i]; - return false; - } - } - return true; -} - -std::shared_ptr CenterCropOperation::Build() { - int32_t crop_height = size_[0]; - int32_t crop_width = 0; - - // User has specified crop_width. - if (size_.size() == 2) { - crop_width = size_[1]; - } - - std::shared_ptr tensor_op = std::make_shared(crop_height, crop_width); - return tensor_op; -} - -// CropOperation. -CropOperation::CropOperation(std::vector coordinates, std::vector size) - : coordinates_(coordinates), size_(size) {} - -bool CropOperation::ValidateParams() { - // Do some input validation. - if (coordinates_.size() != 2) { - MS_LOG(ERROR) << "Crop: coordinates must be a vector of two values"; - return false; - } - // we don't check the coordinates here because we don't have access to image dimensions - if (size_.empty() || size_.size() > 2) { - MS_LOG(ERROR) << "Crop: size must be a vector of one or two values"; - return false; - } - // We have to limit crop size due to library restrictions, optimized to only iterate over size_ once - for (int i = 0; i < size_.size(); ++i) { - if (size_[i] <= 0) { - MS_LOG(ERROR) << "Crop: invalid size, size must be greater than 0, got: " << size_[i]; - return false; - } - if (size_[i] == INT_MAX) { - MS_LOG(ERROR) << "Crop: invalid size, size too large, got: " << size_[i]; - return false; - } - } - return true; -} - -std::shared_ptr CropOperation::Build() { - int32_t x, y, height, width; - - x = coordinates_[0]; - y = coordinates_[1]; - - height = size_[0]; - width = size_[1]; - - std::shared_ptr tensor_op = std::make_shared(x, y, height, width); - return tensor_op; -} - -// CutMixBatchOperation -CutMixBatchOperation::CutMixBatchOperation(ImageBatchFormat image_batch_format, float alpha, float prob) - : image_batch_format_(image_batch_format), alpha_(alpha), prob_(prob) {} - -bool CutMixBatchOperation::ValidateParams() { - if (alpha_ <= 0) { - MS_LOG(ERROR) << "CutMixBatch: alpha must be a positive floating value however it is: " << alpha_; - return false; - } - if (prob_ < 0 || prob_ > 1) { - MS_LOG(ERROR) << "CutMixBatch: Probability has to be between 0 and 1."; - return false; - } - return true; -} - -std::shared_ptr CutMixBatchOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(image_batch_format_, alpha_, prob_); - return tensor_op; -} - -// CutOutOperation -CutOutOperation::CutOutOperation(int32_t length, int32_t num_patches) : length_(length), num_patches_(num_patches) {} - -bool CutOutOperation::ValidateParams() { - if (length_ < 0) { - MS_LOG(ERROR) << "CutOut: length cannot be negative"; - return false; - } - if (num_patches_ < 0) { - MS_LOG(ERROR) << "CutOut: number of patches cannot be negative"; - return false; - } - return true; -} - -std::shared_ptr CutOutOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(length_, length_, num_patches_, false, 0, 0, 0); - return tensor_op; -} - -// DecodeOperation -DecodeOperation::DecodeOperation(bool rgb) : rgb_(rgb) {} - -bool DecodeOperation::ValidateParams() { return true; } - -std::shared_ptr DecodeOperation::Build() { return std::make_shared(rgb_); } - -// HwcToChwOperation -bool HwcToChwOperation::ValidateParams() { return true; } - -std::shared_ptr HwcToChwOperation::Build() { return std::make_shared(); } - -// MixUpOperation -MixUpBatchOperation::MixUpBatchOperation(float alpha) : alpha_(alpha) {} - -bool MixUpBatchOperation::ValidateParams() { - if (alpha_ <= 0) { - MS_LOG(ERROR) << "MixUpBatch: alpha must be a positive floating value however it is: " << alpha_; - return false; - } - - return true; -} - -std::shared_ptr MixUpBatchOperation::Build() { return std::make_shared(alpha_); } - -// NormalizeOperation -NormalizeOperation::NormalizeOperation(std::vector mean, std::vector std) : mean_(mean), std_(std) {} - -bool NormalizeOperation::ValidateParams() { - if (mean_.size() != 3) { - MS_LOG(ERROR) << "Normalize: mean vector has incorrect size: " << mean_.size(); - return false; - } - // check mean value - for (int i = 0; i < mean_.size(); ++i) { - if (mean_[i] < 0.0f || mean_[i] > 255.0f || CmpFloat(mean_[i], 0.0f)) { - MS_LOG(ERROR) << "Normalize: mean vector has incorrect value: " << mean_[i]; - return false; - } - } - if (std_.size() != 3) { - MS_LOG(ERROR) << "Normalize: std vector has incorrect size: " << std_.size(); - return false; - } - // check std value - for (int i = 0; i < std_.size(); ++i) { - if (std_[i] < 0.0f || std_[i] > 255.0f || CmpFloat(std_[i], 0.0f)) { - MS_LOG(ERROR) << "Normalize: std vector has incorrect value: " << std_[i]; - return false; - } - } - return true; -} - -std::shared_ptr NormalizeOperation::Build() { - return std::make_shared(mean_[0], mean_[1], mean_[2], std_[0], std_[1], std_[2]); -} +// (In alphabetical order) // OneHotOperation OneHotOperation::OneHotOperation(int32_t num_classes) : num_classes_(num_classes) {} @@ -524,476 +62,7 @@ bool OneHotOperation::ValidateParams() { std::shared_ptr OneHotOperation::Build() { return std::make_shared(num_classes_); } -// PadOperation -PadOperation::PadOperation(std::vector padding, std::vector fill_value, BorderType padding_mode) - : padding_(padding), fill_value_(fill_value), padding_mode_(padding_mode) {} - -bool PadOperation::ValidateParams() { - if (padding_.empty() || padding_.size() == 3 || padding_.size() > 4) { - MS_LOG(ERROR) << "Pad: padding vector has incorrect size: padding.size()"; - return false; - } - - if (fill_value_.empty() || (fill_value_.size() != 1 && fill_value_.size() != 3)) { - MS_LOG(ERROR) << "Pad: fill_value vector has incorrect size: fill_value.size()"; - return false; - } - return true; -} - -std::shared_ptr PadOperation::Build() { - int32_t pad_top, pad_bottom, pad_left, pad_right; - switch (padding_.size()) { - case 1: - pad_left = padding_[0]; - pad_top = padding_[0]; - pad_right = padding_[0]; - pad_bottom = padding_[0]; - break; - case 2: - pad_left = padding_[0]; - pad_top = padding_[1]; - pad_right = padding_[0]; - pad_bottom = padding_[1]; - break; - default: - pad_left = padding_[0]; - pad_top = padding_[1]; - pad_right = padding_[2]; - pad_bottom = padding_[3]; - } - uint8_t fill_r, fill_g, fill_b; - - fill_r = fill_value_[0]; - fill_g = fill_value_[0]; - fill_b = fill_value_[0]; - - if (fill_value_.size() == 3) { - fill_r = fill_value_[0]; - fill_g = fill_value_[1]; - fill_b = fill_value_[2]; - } - - std::shared_ptr tensor_op = - std::make_shared(pad_top, pad_bottom, pad_left, pad_right, padding_mode_, fill_r, fill_g, fill_b); - return tensor_op; -} - -// RandomColorOperation. -RandomColorOperation::RandomColorOperation(float t_lb, float t_ub) : t_lb_(t_lb), t_ub_(t_ub) {} - -bool RandomColorOperation::ValidateParams() { - // Do some input validation. - if (t_lb_ > t_ub_) { - MS_LOG(ERROR) << "RandomColor: lower bound must be less or equal to upper bound"; - return false; - } - return true; -} - -// RandomColorAdjustOperation. -RandomColorAdjustOperation::RandomColorAdjustOperation(std::vector brightness, std::vector contrast, - std::vector saturation, std::vector hue) - : brightness_(brightness), contrast_(contrast), saturation_(saturation), hue_(hue) {} - -bool RandomColorAdjustOperation::ValidateParams() { - // Do some input validation. - if (brightness_.empty() || brightness_.size() > 2) { - MS_LOG(ERROR) << "RandomColorAdjust: brightness must be a vector of one or two values"; - return false; - } - if (contrast_.empty() || contrast_.size() > 2) { - MS_LOG(ERROR) << "RandomColorAdjust: contrast must be a vector of one or two values"; - return false; - } - if (saturation_.empty() || saturation_.size() > 2) { - MS_LOG(ERROR) << "RandomColorAdjust: saturation must be a vector of one or two values"; - return false; - } - if (hue_.empty() || hue_.size() > 2) { - MS_LOG(ERROR) << "RandomColorAdjust: hue must be a vector of one or two values"; - return false; - } - return true; -} - -std::shared_ptr RandomColorAdjustOperation::Build() { - float brightness_lb, brightness_ub, contrast_lb, contrast_ub, saturation_lb, saturation_ub, hue_lb, hue_ub; - - brightness_lb = brightness_[0]; - brightness_ub = brightness_[0]; - - if (brightness_.size() == 2) brightness_ub = brightness_[1]; - - contrast_lb = contrast_[0]; - contrast_ub = contrast_[0]; - - if (contrast_.size() == 2) contrast_ub = contrast_[1]; - - saturation_lb = saturation_[0]; - saturation_ub = saturation_[0]; - - if (saturation_.size() == 2) saturation_ub = saturation_[1]; - - hue_lb = hue_[0]; - hue_ub = hue_[0]; - - if (hue_.size() == 2) hue_ub = hue_[1]; - - std::shared_ptr tensor_op = std::make_shared( - brightness_lb, brightness_ub, contrast_lb, contrast_ub, saturation_lb, saturation_ub, hue_lb, hue_ub); - return tensor_op; -} - -// RandomAffineOperation -RandomAffineOperation::RandomAffineOperation(const std::vector °rees, - const std::vector &translate_range, - const std::vector &scale_range, - const std::vector &shear_ranges, InterpolationMode interpolation, - const std::vector &fill_value) - : degrees_(degrees), - translate_range_(translate_range), - scale_range_(scale_range), - shear_ranges_(shear_ranges), - interpolation_(interpolation), - fill_value_(fill_value) {} - -bool RandomAffineOperation::ValidateParams() { - // Degrees - if (degrees_.size() != 2) { - MS_LOG(ERROR) << "RandomAffine: degrees expecting size 2, got: degrees.size() = " << degrees_.size(); - return false; - } - if (degrees_[0] > degrees_[1]) { - MS_LOG(ERROR) << "RandomAffine: minimum of degrees range is greater than maximum: min = " << degrees_[0] - << ", max = " << degrees_[1]; - return false; - } - // Translate - 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(); - return false; - } - if (translate_range_[0] > 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; - } - 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 - if (scale_range_.size() != 2) { - MS_LOG(ERROR) << "RandomAffine: scale_range vector has incorrect size: scale_range.size() = " - << scale_range_.size(); - return false; - } - if (scale_range_[0] > scale_range_[1]) { - MS_LOG(ERROR) << "RandomAffine: minimum of scale range is greater than maximum: min = " << scale_range_[0] - << ", max = " << scale_range_[1]; - return false; - } - // Shear - 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(); - return false; - } - if (shear_ranges_[0] > shear_ranges_[1]) { - MS_LOG(ERROR) << "RandomAffine: minimum of horizontal shear range is greater than maximum: min = " - << shear_ranges_[0] << ", max = " << shear_ranges_[1]; - return false; - } - 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] - << ", max = " << scale_range_[3]; - return false; - } - // Fill Value - if (fill_value_.size() != 3) { - MS_LOG(ERROR) << "RandomAffine: fill_value vector has incorrect size: fill_value.size() = " << fill_value_.size(); - return false; - } - return true; -} - -std::shared_ptr 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(degrees_, translate_range_, scale_range_, shear_ranges_, - interpolation_, fill_value_); - return tensor_op; -} - -// RandomCropOperation -RandomCropOperation::RandomCropOperation(std::vector size, std::vector padding, bool pad_if_needed, - std::vector fill_value, BorderType padding_mode) - : size_(size), - padding_(padding), - pad_if_needed_(pad_if_needed), - fill_value_(fill_value), - padding_mode_(padding_mode) {} - -bool RandomCropOperation::ValidateParams() { - if (size_.empty() || size_.size() > 2) { - MS_LOG(ERROR) << "RandomCrop: size vector has incorrect size: " << size_.size(); - return false; - } - - if (padding_.empty() || padding_.size() != 4) { - MS_LOG(ERROR) << "RandomCrop: padding vector has incorrect size: padding.size()"; - return false; - } - - if (fill_value_.empty() || fill_value_.size() != 3) { - MS_LOG(ERROR) << "RandomCrop: fill_value vector has incorrect size: fill_value.size()"; - return false; - } - return true; -} - -std::shared_ptr RandomCropOperation::Build() { - int32_t crop_height = size_[0]; - int32_t crop_width = 0; - - int32_t pad_top = padding_[0]; - int32_t pad_bottom = padding_[1]; - int32_t pad_left = padding_[2]; - int32_t pad_right = padding_[3]; - - uint8_t fill_r = fill_value_[0]; - uint8_t fill_g = fill_value_[1]; - uint8_t fill_b = fill_value_[2]; - - // User has specified the crop_width value. - if (size_.size() == 2) { - crop_width = size_[1]; - } - - auto tensor_op = std::make_shared(crop_height, crop_width, pad_top, pad_bottom, pad_left, pad_right, - padding_mode_, pad_if_needed_, fill_r, fill_g, fill_b); - return tensor_op; -} - -// RandomHorizontalFlipOperation -RandomHorizontalFlipOperation::RandomHorizontalFlipOperation(float probability) : probability_(probability) {} - -bool RandomHorizontalFlipOperation::ValidateParams() { return true; } - -std::shared_ptr RandomHorizontalFlipOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(probability_); - return tensor_op; -} - -// RandomPosterizeOperation -RandomPosterizeOperation::RandomPosterizeOperation(const std::vector &bit_range) : bit_range_(bit_range) {} - -bool RandomPosterizeOperation::ValidateParams() { - 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; - } - 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; - } - 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 true; -} - -std::shared_ptr RandomPosterizeOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(bit_range_); - return tensor_op; -} - -// Function to create RandomRotationOperation. -RandomRotationOperation::RandomRotationOperation(std::vector degrees, InterpolationMode interpolation_mode, - bool expand, std::vector center, - std::vector fill_value) - : degrees_(degrees), - interpolation_mode_(interpolation_mode), - expand_(expand), - center_(center), - fill_value_(fill_value) {} - -bool RandomRotationOperation::ValidateParams() { - if (degrees_.empty() || degrees_.size() != 2) { - MS_LOG(ERROR) << "RandomRotation: degrees vector has incorrect size: degrees.size()"; - return false; - } - if (center_.empty() || center_.size() != 2) { - MS_LOG(ERROR) << "RandomRotation: center vector has incorrect size: center.size()"; - return false; - } - if (fill_value_.empty() || fill_value_.size() != 3) { - MS_LOG(ERROR) << "RandomRotation: fill_value vector has incorrect size: fill_value.size()"; - return false; - } - return true; -} - -std::shared_ptr RandomRotationOperation::Build() { - std::shared_ptr tensor_op = - std::make_shared(degrees_[0], degrees_[1], center_[0], center_[1], interpolation_mode_, expand_, - fill_value_[0], fill_value_[1], fill_value_[2]); - return tensor_op; -} - -// Function to create RandomSharpness. -RandomSharpnessOperation::RandomSharpnessOperation(std::vector degrees) : degrees_(degrees) {} - -bool RandomSharpnessOperation::ValidateParams() { - if (degrees_.empty() || degrees_.size() != 2) { - MS_LOG(ERROR) << "RandomSharpness: degrees vector has incorrect size: degrees.size()"; - return false; - } - return true; -} - -std::shared_ptr RandomSharpnessOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(degrees_[0], degrees_[1]); - return tensor_op; -} - -// RandomSolarizeOperation. -RandomSolarizeOperation::RandomSolarizeOperation(std::vector threshold) : threshold_(threshold) {} - -bool RandomSolarizeOperation::ValidateParams() { - if (threshold_.size() != 2) { - MS_LOG(ERROR) << "RandomSolarize: threshold vector has incorrect size: " << threshold_.size(); - return false; - } - if (threshold_.at(0) > threshold_.at(1)) { - MS_LOG(ERROR) << "RandomSolarize: threshold must be passed in a min, max format"; - return false; - } - return true; -} - -std::shared_ptr RandomSolarizeOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(threshold_); - return tensor_op; -} - -// RandomVerticalFlipOperation -RandomVerticalFlipOperation::RandomVerticalFlipOperation(float probability) : probability_(probability) {} - -bool RandomVerticalFlipOperation::ValidateParams() { return true; } - -std::shared_ptr RandomVerticalFlipOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(probability_); - return tensor_op; -} - -// ResizeOperation -ResizeOperation::ResizeOperation(std::vector size, InterpolationMode interpolation) - : size_(size), interpolation_(interpolation) {} - -bool ResizeOperation::ValidateParams() { - if (size_.empty() || size_.size() > 2) { - MS_LOG(ERROR) << "Resize: size vector has incorrect size: " << size_.size(); - return false; - } - if (!CheckVectorPositive(size_)) { - return false; - } - return true; -} - -std::shared_ptr ResizeOperation::Build() { - int32_t height = size_[0]; - int32_t width = 0; - - // User specified the width value. - if (size_.size() == 2) { - width = size_[1]; - } - - return std::make_shared(height, width, interpolation_); -} - -// RgbaToBgrOperation. -RgbaToBgrOperation::RgbaToBgrOperation() {} - -bool RgbaToBgrOperation::ValidateParams() { return true; } - -std::shared_ptr RgbaToBgrOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(); - return tensor_op; -} - -// RgbaToRgbOperation. -RgbaToRgbOperation::RgbaToRgbOperation() {} - -bool RgbaToRgbOperation::ValidateParams() { return true; } - -std::shared_ptr RgbaToRgbOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(); - return tensor_op; -} - -// SwapRedBlueOperation. -SwapRedBlueOperation::SwapRedBlueOperation() {} - -bool SwapRedBlueOperation::ValidateParams() { return true; } - -std::shared_ptr SwapRedBlueOperation::Build() { - std::shared_ptr tensor_op = std::make_shared(); - return tensor_op; -} - -// UniformAugOperation -UniformAugOperation::UniformAugOperation(std::vector> transforms, int32_t num_ops) - : transforms_(transforms), num_ops_(num_ops) {} - -bool UniformAugOperation::ValidateParams() { return true; } - -std::shared_ptr UniformAugOperation::Build() { - std::vector> tensor_ops; - (void)std::transform(transforms_.begin(), transforms_.end(), std::back_inserter(tensor_ops), - [](std::shared_ptr op) -> std::shared_ptr { return op->Build(); }); - std::shared_ptr tensor_op = std::make_shared(tensor_ops, num_ops_); - return tensor_op; -} - -} // namespace vision +} // namespace transforms } // namespace api } // namespace dataset } // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/api/vision.cc b/mindspore/ccsrc/minddata/dataset/api/vision.cc new file mode 100644 index 0000000000..7972142406 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/api/vision.cc @@ -0,0 +1,979 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "minddata/dataset/include/transforms.h" +#include "minddata/dataset/include/vision.h" +#include "minddata/dataset/kernels/image/image_utils.h" + +// Kernel image headers (in alphabetical order) +#include "minddata/dataset/kernels/image/center_crop_op.h" +#include "minddata/dataset/kernels/image/crop_op.h" +#include "minddata/dataset/kernels/image/cutmix_batch_op.h" +#include "minddata/dataset/kernels/image/cut_out_op.h" +#include "minddata/dataset/kernels/image/decode_op.h" +#include "minddata/dataset/kernels/image/hwc_to_chw_op.h" +#include "minddata/dataset/kernels/image/mixup_batch_op.h" +#include "minddata/dataset/kernels/image/normalize_op.h" +#include "minddata/dataset/kernels/image/pad_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_adjust_op.h" +#include "minddata/dataset/kernels/image/random_crop_op.h" +#include "minddata/dataset/kernels/image/random_horizontal_flip_op.h" +#include "minddata/dataset/kernels/image/random_posterize_op.h" +#include "minddata/dataset/kernels/image/random_rotation_op.h" +#include "minddata/dataset/kernels/image/random_sharpness_op.h" +#include "minddata/dataset/kernels/image/random_solarize_op.h" +#include "minddata/dataset/kernels/image/random_vertical_flip_op.h" +#include "minddata/dataset/kernels/image/resize_op.h" +#include "minddata/dataset/kernels/image/rgba_to_bgr_op.h" +#include "minddata/dataset/kernels/image/rgba_to_rgb_op.h" +#include "minddata/dataset/kernels/image/swap_red_blue_op.h" +#include "minddata/dataset/kernels/image/uniform_aug_op.h" + +namespace mindspore { +namespace dataset { +namespace api { + +// Transform operations for computer vision. +namespace vision { + +// FUNCTIONS TO CREATE VISION TRANSFORM OPERATIONS +// (In alphabetical order) + +// Function to create CenterCropOperation. +std::shared_ptr CenterCrop(std::vector size) { + auto op = std::make_shared(size); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create CropOperation. +std::shared_ptr Crop(std::vector coordinates, std::vector size) { + auto op = std::make_shared(coordinates, size); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create CutMixBatchOperation. +std::shared_ptr CutMixBatch(ImageBatchFormat image_batch_format, float alpha, float prob) { + auto op = std::make_shared(image_batch_format, alpha, prob); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create CutOutOp. +std::shared_ptr CutOut(int32_t length, int32_t num_patches) { + auto op = std::make_shared(length, num_patches); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create DecodeOperation. +std::shared_ptr Decode(bool rgb) { + auto op = std::make_shared(rgb); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create HwcToChwOperation. +std::shared_ptr HWC2CHW() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create MixUpBatchOperation. +std::shared_ptr MixUpBatch(float alpha) { + auto op = std::make_shared(alpha); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create NormalizeOperation. +std::shared_ptr Normalize(std::vector mean, std::vector std) { + auto op = std::make_shared(mean, std); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create PadOperation. +std::shared_ptr Pad(std::vector padding, std::vector fill_value, + BorderType padding_mode) { + auto op = std::make_shared(padding, fill_value, padding_mode); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomColorOperation. +std::shared_ptr RandomColor(float t_lb, float t_ub) { + auto op = std::make_shared(t_lb, t_ub); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +std::shared_ptr RandomColorOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(t_lb_, t_ub_); + return tensor_op; +} + +// Function to create RandomColorAdjustOperation. +std::shared_ptr RandomColorAdjust(std::vector brightness, + std::vector contrast, + std::vector saturation, std::vector hue) { + auto op = std::make_shared(brightness, contrast, saturation, hue); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomAffineOperation. +std::shared_ptr RandomAffine(const std::vector °rees, + const std::vector &translate_range, + const std::vector &scale_range, + const std::vector &shear_ranges, + InterpolationMode interpolation, + const std::vector &fill_value) { + auto op = std::make_shared(degrees, translate_range, scale_range, shear_ranges, interpolation, + fill_value); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomCropOperation. +std::shared_ptr RandomCrop(std::vector size, std::vector padding, + bool pad_if_needed, std::vector fill_value, + BorderType padding_mode) { + auto op = std::make_shared(size, padding, pad_if_needed, fill_value, padding_mode); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomHorizontalFlipOperation. +std::shared_ptr RandomHorizontalFlip(float prob) { + auto op = std::make_shared(prob); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomPosterizeOperation. +std::shared_ptr RandomPosterize(const std::vector &bit_range) { + auto op = std::make_shared(bit_range); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomRotationOperation. +std::shared_ptr RandomRotation(std::vector degrees, InterpolationMode resample, + bool expand, std::vector center, + std::vector fill_value) { + auto op = std::make_shared(degrees, resample, expand, center, fill_value); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomSolarizeOperation. +std::shared_ptr RandomSolarize(std::vector threshold) { + auto op = std::make_shared(threshold); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomSharpnessOperation. +std::shared_ptr RandomSharpness(std::vector degrees) { + auto op = std::make_shared(degrees); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RandomVerticalFlipOperation. +std::shared_ptr RandomVerticalFlip(float prob) { + auto op = std::make_shared(prob); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create ResizeOperation. +std::shared_ptr Resize(std::vector size, InterpolationMode interpolation) { + auto op = std::make_shared(size, interpolation); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RgbaToBgrOperation. +std::shared_ptr RGBA2BGR() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RgbaToRgbOperation. +std::shared_ptr RGBA2RGB() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create SwapRedBlueOperation. +std::shared_ptr SwapRedBlue() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create UniformAugOperation. +std::shared_ptr UniformAugment(std::vector> transforms, + int32_t num_ops) { + auto op = std::make_shared(transforms, num_ops); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +/* ####################################### Validator Functions ############################################ */ +bool CheckVectorPositive(const std::vector &size) { + for (int i = 0; i < size.size(); ++i) { + if (size[i] <= 0) return false; + } + return true; +} + +bool CmpFloat(const float &a, const float &b, float epsilon = 0.0000000001f) { return (std::fabs(a - b) < epsilon); } + +/* ####################################### Derived TensorOperation classes ################################# */ + +// (In alphabetical order) + +// CenterCropOperation +CenterCropOperation::CenterCropOperation(std::vector size) : size_(size) {} + +bool CenterCropOperation::ValidateParams() { + if (size_.empty() || size_.size() > 2) { + MS_LOG(ERROR) << "CenterCrop: size vector has incorrect size."; + return false; + } + // We have to limit crop size due to library restrictions, optimized to only iterate over size_ once + for (int i = 0; i < size_.size(); ++i) { + if (size_[i] <= 0) { + MS_LOG(ERROR) << "CenterCrop: invalid size, size must be greater than 0, got: " << size_[i]; + return false; + } + if (size_[i] == INT_MAX) { + MS_LOG(ERROR) << "CenterCrop: invalid size, size too large, got: " << size_[i]; + return false; + } + } + return true; +} + +std::shared_ptr CenterCropOperation::Build() { + int32_t crop_height = size_[0]; + int32_t crop_width = 0; + + // User has specified crop_width. + if (size_.size() == 2) { + crop_width = size_[1]; + } + + std::shared_ptr tensor_op = std::make_shared(crop_height, crop_width); + return tensor_op; +} + +// CropOperation. +CropOperation::CropOperation(std::vector coordinates, std::vector size) + : coordinates_(coordinates), size_(size) {} + +bool CropOperation::ValidateParams() { + // Do some input validation. + if (coordinates_.size() != 2) { + MS_LOG(ERROR) << "Crop: coordinates must be a vector of two values"; + return false; + } + // we don't check the coordinates here because we don't have access to image dimensions + if (size_.empty() || size_.size() > 2) { + MS_LOG(ERROR) << "Crop: size must be a vector of one or two values"; + return false; + } + // We have to limit crop size due to library restrictions, optimized to only iterate over size_ once + for (int i = 0; i < size_.size(); ++i) { + if (size_[i] <= 0) { + MS_LOG(ERROR) << "Crop: invalid size, size must be greater than 0, got: " << size_[i]; + return false; + } + if (size_[i] == INT_MAX) { + MS_LOG(ERROR) << "Crop: invalid size, size too large, got: " << size_[i]; + return false; + } + } + return true; +} + +std::shared_ptr CropOperation::Build() { + int32_t x, y, height, width; + + x = coordinates_[0]; + y = coordinates_[1]; + + height = size_[0]; + width = size_[1]; + + std::shared_ptr tensor_op = std::make_shared(x, y, height, width); + return tensor_op; +} + +// CutMixBatchOperation +CutMixBatchOperation::CutMixBatchOperation(ImageBatchFormat image_batch_format, float alpha, float prob) + : image_batch_format_(image_batch_format), alpha_(alpha), prob_(prob) {} + +bool CutMixBatchOperation::ValidateParams() { + if (alpha_ <= 0) { + MS_LOG(ERROR) << "CutMixBatch: alpha must be a positive floating value however it is: " << alpha_; + return false; + } + if (prob_ < 0 || prob_ > 1) { + MS_LOG(ERROR) << "CutMixBatch: Probability has to be between 0 and 1."; + return false; + } + return true; +} + +std::shared_ptr CutMixBatchOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(image_batch_format_, alpha_, prob_); + return tensor_op; +} + +// CutOutOperation +CutOutOperation::CutOutOperation(int32_t length, int32_t num_patches) : length_(length), num_patches_(num_patches) {} + +bool CutOutOperation::ValidateParams() { + if (length_ < 0) { + MS_LOG(ERROR) << "CutOut: length cannot be negative"; + return false; + } + if (num_patches_ < 0) { + MS_LOG(ERROR) << "CutOut: number of patches cannot be negative"; + return false; + } + return true; +} + +std::shared_ptr CutOutOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(length_, length_, num_patches_, false, 0, 0, 0); + return tensor_op; +} + +// DecodeOperation +DecodeOperation::DecodeOperation(bool rgb) : rgb_(rgb) {} + +bool DecodeOperation::ValidateParams() { return true; } + +std::shared_ptr DecodeOperation::Build() { return std::make_shared(rgb_); } + +// HwcToChwOperation +bool HwcToChwOperation::ValidateParams() { return true; } + +std::shared_ptr HwcToChwOperation::Build() { return std::make_shared(); } + +// MixUpOperation +MixUpBatchOperation::MixUpBatchOperation(float alpha) : alpha_(alpha) {} + +bool MixUpBatchOperation::ValidateParams() { + if (alpha_ <= 0) { + MS_LOG(ERROR) << "MixUpBatch: alpha must be a positive floating value however it is: " << alpha_; + return false; + } + + return true; +} + +std::shared_ptr MixUpBatchOperation::Build() { return std::make_shared(alpha_); } + +// NormalizeOperation +NormalizeOperation::NormalizeOperation(std::vector mean, std::vector std) : mean_(mean), std_(std) {} + +bool NormalizeOperation::ValidateParams() { + if (mean_.size() != 3) { + MS_LOG(ERROR) << "Normalize: mean vector has incorrect size: " << mean_.size(); + return false; + } + // check mean value + for (int i = 0; i < mean_.size(); ++i) { + if (mean_[i] < 0.0f || mean_[i] > 255.0f || CmpFloat(mean_[i], 0.0f)) { + MS_LOG(ERROR) << "Normalize: mean vector has incorrect value: " << mean_[i]; + return false; + } + } + if (std_.size() != 3) { + MS_LOG(ERROR) << "Normalize: std vector has incorrect size: " << std_.size(); + return false; + } + // check std value + for (int i = 0; i < std_.size(); ++i) { + if (std_[i] < 0.0f || std_[i] > 255.0f || CmpFloat(std_[i], 0.0f)) { + MS_LOG(ERROR) << "Normalize: std vector has incorrect value: " << std_[i]; + return false; + } + } + return true; +} + +std::shared_ptr NormalizeOperation::Build() { + return std::make_shared(mean_[0], mean_[1], mean_[2], std_[0], std_[1], std_[2]); +} + +// PadOperation +PadOperation::PadOperation(std::vector padding, std::vector fill_value, BorderType padding_mode) + : padding_(padding), fill_value_(fill_value), padding_mode_(padding_mode) {} + +bool PadOperation::ValidateParams() { + if (padding_.empty() || padding_.size() == 3 || padding_.size() > 4) { + MS_LOG(ERROR) << "Pad: padding vector has incorrect size: padding.size()"; + return false; + } + + if (fill_value_.empty() || (fill_value_.size() != 1 && fill_value_.size() != 3)) { + MS_LOG(ERROR) << "Pad: fill_value vector has incorrect size: fill_value.size()"; + return false; + } + return true; +} + +std::shared_ptr PadOperation::Build() { + int32_t pad_top, pad_bottom, pad_left, pad_right; + switch (padding_.size()) { + case 1: + pad_left = padding_[0]; + pad_top = padding_[0]; + pad_right = padding_[0]; + pad_bottom = padding_[0]; + break; + case 2: + pad_left = padding_[0]; + pad_top = padding_[1]; + pad_right = padding_[0]; + pad_bottom = padding_[1]; + break; + default: + pad_left = padding_[0]; + pad_top = padding_[1]; + pad_right = padding_[2]; + pad_bottom = padding_[3]; + } + uint8_t fill_r, fill_g, fill_b; + + fill_r = fill_value_[0]; + fill_g = fill_value_[0]; + fill_b = fill_value_[0]; + + if (fill_value_.size() == 3) { + fill_r = fill_value_[0]; + fill_g = fill_value_[1]; + fill_b = fill_value_[2]; + } + + std::shared_ptr tensor_op = + std::make_shared(pad_top, pad_bottom, pad_left, pad_right, padding_mode_, fill_r, fill_g, fill_b); + return tensor_op; +} + +// RandomColorOperation. +RandomColorOperation::RandomColorOperation(float t_lb, float t_ub) : t_lb_(t_lb), t_ub_(t_ub) {} + +bool RandomColorOperation::ValidateParams() { + // Do some input validation. + if (t_lb_ > t_ub_) { + MS_LOG(ERROR) << "RandomColor: lower bound must be less or equal to upper bound"; + return false; + } + return true; +} + +// RandomColorAdjustOperation. +RandomColorAdjustOperation::RandomColorAdjustOperation(std::vector brightness, std::vector contrast, + std::vector saturation, std::vector hue) + : brightness_(brightness), contrast_(contrast), saturation_(saturation), hue_(hue) {} + +bool RandomColorAdjustOperation::ValidateParams() { + // Do some input validation. + if (brightness_.empty() || brightness_.size() > 2) { + MS_LOG(ERROR) << "RandomColorAdjust: brightness must be a vector of one or two values"; + return false; + } + if (contrast_.empty() || contrast_.size() > 2) { + MS_LOG(ERROR) << "RandomColorAdjust: contrast must be a vector of one or two values"; + return false; + } + if (saturation_.empty() || saturation_.size() > 2) { + MS_LOG(ERROR) << "RandomColorAdjust: saturation must be a vector of one or two values"; + return false; + } + if (hue_.empty() || hue_.size() > 2) { + MS_LOG(ERROR) << "RandomColorAdjust: hue must be a vector of one or two values"; + return false; + } + return true; +} + +std::shared_ptr RandomColorAdjustOperation::Build() { + float brightness_lb, brightness_ub, contrast_lb, contrast_ub, saturation_lb, saturation_ub, hue_lb, hue_ub; + + brightness_lb = brightness_[0]; + brightness_ub = brightness_[0]; + + if (brightness_.size() == 2) brightness_ub = brightness_[1]; + + contrast_lb = contrast_[0]; + contrast_ub = contrast_[0]; + + if (contrast_.size() == 2) contrast_ub = contrast_[1]; + + saturation_lb = saturation_[0]; + saturation_ub = saturation_[0]; + + if (saturation_.size() == 2) saturation_ub = saturation_[1]; + + hue_lb = hue_[0]; + hue_ub = hue_[0]; + + if (hue_.size() == 2) hue_ub = hue_[1]; + + std::shared_ptr tensor_op = std::make_shared( + brightness_lb, brightness_ub, contrast_lb, contrast_ub, saturation_lb, saturation_ub, hue_lb, hue_ub); + return tensor_op; +} + +// RandomAffineOperation +RandomAffineOperation::RandomAffineOperation(const std::vector °rees, + const std::vector &translate_range, + const std::vector &scale_range, + const std::vector &shear_ranges, InterpolationMode interpolation, + const std::vector &fill_value) + : degrees_(degrees), + translate_range_(translate_range), + scale_range_(scale_range), + shear_ranges_(shear_ranges), + interpolation_(interpolation), + fill_value_(fill_value) {} + +bool RandomAffineOperation::ValidateParams() { + // Degrees + if (degrees_.size() != 2) { + MS_LOG(ERROR) << "RandomAffine: degrees expecting size 2, got: degrees.size() = " << degrees_.size(); + return false; + } + if (degrees_[0] > degrees_[1]) { + MS_LOG(ERROR) << "RandomAffine: minimum of degrees range is greater than maximum: min = " << degrees_[0] + << ", max = " << degrees_[1]; + return false; + } + // Translate + 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(); + return false; + } + if (translate_range_[0] > 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; + } + 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 + if (scale_range_.size() != 2) { + MS_LOG(ERROR) << "RandomAffine: scale_range vector has incorrect size: scale_range.size() = " + << scale_range_.size(); + return false; + } + if (scale_range_[0] > scale_range_[1]) { + MS_LOG(ERROR) << "RandomAffine: minimum of scale range is greater than maximum: min = " << scale_range_[0] + << ", max = " << scale_range_[1]; + return false; + } + // Shear + 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(); + return false; + } + if (shear_ranges_[0] > shear_ranges_[1]) { + MS_LOG(ERROR) << "RandomAffine: minimum of horizontal shear range is greater than maximum: min = " + << shear_ranges_[0] << ", max = " << shear_ranges_[1]; + return false; + } + 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] + << ", max = " << scale_range_[3]; + return false; + } + // Fill Value + if (fill_value_.size() != 3) { + MS_LOG(ERROR) << "RandomAffine: fill_value vector has incorrect size: fill_value.size() = " << fill_value_.size(); + return false; + } + return true; +} + +std::shared_ptr 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(degrees_, translate_range_, scale_range_, shear_ranges_, + interpolation_, fill_value_); + return tensor_op; +} + +// RandomCropOperation +RandomCropOperation::RandomCropOperation(std::vector size, std::vector padding, bool pad_if_needed, + std::vector fill_value, BorderType padding_mode) + : size_(size), + padding_(padding), + pad_if_needed_(pad_if_needed), + fill_value_(fill_value), + padding_mode_(padding_mode) {} + +bool RandomCropOperation::ValidateParams() { + if (size_.empty() || size_.size() > 2) { + MS_LOG(ERROR) << "RandomCrop: size vector has incorrect size: " << size_.size(); + return false; + } + + if (padding_.empty() || padding_.size() != 4) { + MS_LOG(ERROR) << "RandomCrop: padding vector has incorrect size: padding.size()"; + return false; + } + + if (fill_value_.empty() || fill_value_.size() != 3) { + MS_LOG(ERROR) << "RandomCrop: fill_value vector has incorrect size: fill_value.size()"; + return false; + } + return true; +} + +std::shared_ptr RandomCropOperation::Build() { + int32_t crop_height = size_[0]; + int32_t crop_width = 0; + + int32_t pad_top = padding_[0]; + int32_t pad_bottom = padding_[1]; + int32_t pad_left = padding_[2]; + int32_t pad_right = padding_[3]; + + uint8_t fill_r = fill_value_[0]; + uint8_t fill_g = fill_value_[1]; + uint8_t fill_b = fill_value_[2]; + + // User has specified the crop_width value. + if (size_.size() == 2) { + crop_width = size_[1]; + } + + auto tensor_op = std::make_shared(crop_height, crop_width, pad_top, pad_bottom, pad_left, pad_right, + padding_mode_, pad_if_needed_, fill_r, fill_g, fill_b); + return tensor_op; +} + +// RandomHorizontalFlipOperation +RandomHorizontalFlipOperation::RandomHorizontalFlipOperation(float probability) : probability_(probability) {} + +bool RandomHorizontalFlipOperation::ValidateParams() { return true; } + +std::shared_ptr RandomHorizontalFlipOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(probability_); + return tensor_op; +} + +// RandomPosterizeOperation +RandomPosterizeOperation::RandomPosterizeOperation(const std::vector &bit_range) : bit_range_(bit_range) {} + +bool RandomPosterizeOperation::ValidateParams() { + 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; + } + 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; + } + 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 true; +} + +std::shared_ptr RandomPosterizeOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(bit_range_); + return tensor_op; +} + +// Function to create RandomRotationOperation. +RandomRotationOperation::RandomRotationOperation(std::vector degrees, InterpolationMode interpolation_mode, + bool expand, std::vector center, + std::vector fill_value) + : degrees_(degrees), + interpolation_mode_(interpolation_mode), + expand_(expand), + center_(center), + fill_value_(fill_value) {} + +bool RandomRotationOperation::ValidateParams() { + if (degrees_.empty() || degrees_.size() != 2) { + MS_LOG(ERROR) << "RandomRotation: degrees vector has incorrect size: degrees.size()"; + return false; + } + if (center_.empty() || center_.size() != 2) { + MS_LOG(ERROR) << "RandomRotation: center vector has incorrect size: center.size()"; + return false; + } + if (fill_value_.empty() || fill_value_.size() != 3) { + MS_LOG(ERROR) << "RandomRotation: fill_value vector has incorrect size: fill_value.size()"; + return false; + } + return true; +} + +std::shared_ptr RandomRotationOperation::Build() { + std::shared_ptr tensor_op = + std::make_shared(degrees_[0], degrees_[1], center_[0], center_[1], interpolation_mode_, expand_, + fill_value_[0], fill_value_[1], fill_value_[2]); + return tensor_op; +} + +// Function to create RandomSharpness. +RandomSharpnessOperation::RandomSharpnessOperation(std::vector degrees) : degrees_(degrees) {} + +bool RandomSharpnessOperation::ValidateParams() { + if (degrees_.empty() || degrees_.size() != 2) { + MS_LOG(ERROR) << "RandomSharpness: degrees vector has incorrect size: degrees.size()"; + return false; + } + return true; +} + +std::shared_ptr RandomSharpnessOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(degrees_[0], degrees_[1]); + return tensor_op; +} + +// RandomSolarizeOperation. +RandomSolarizeOperation::RandomSolarizeOperation(std::vector threshold) : threshold_(threshold) {} + +bool RandomSolarizeOperation::ValidateParams() { + if (threshold_.size() != 2) { + MS_LOG(ERROR) << "RandomSolarize: threshold vector has incorrect size: " << threshold_.size(); + return false; + } + if (threshold_.at(0) > threshold_.at(1)) { + MS_LOG(ERROR) << "RandomSolarize: threshold must be passed in a min, max format"; + return false; + } + return true; +} + +std::shared_ptr RandomSolarizeOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(threshold_); + return tensor_op; +} + +// RandomVerticalFlipOperation +RandomVerticalFlipOperation::RandomVerticalFlipOperation(float probability) : probability_(probability) {} + +bool RandomVerticalFlipOperation::ValidateParams() { return true; } + +std::shared_ptr RandomVerticalFlipOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(probability_); + return tensor_op; +} + +// ResizeOperation +ResizeOperation::ResizeOperation(std::vector size, InterpolationMode interpolation) + : size_(size), interpolation_(interpolation) {} + +bool ResizeOperation::ValidateParams() { + if (size_.empty() || size_.size() > 2) { + MS_LOG(ERROR) << "Resize: size vector has incorrect size: " << size_.size(); + return false; + } + if (!CheckVectorPositive(size_)) { + return false; + } + return true; +} + +std::shared_ptr ResizeOperation::Build() { + int32_t height = size_[0]; + int32_t width = 0; + + // User specified the width value. + if (size_.size() == 2) { + width = size_[1]; + } + + return std::make_shared(height, width, interpolation_); +} + +// RgbaToBgrOperation. +RgbaToBgrOperation::RgbaToBgrOperation() {} + +bool RgbaToBgrOperation::ValidateParams() { return true; } + +std::shared_ptr RgbaToBgrOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + +// RgbaToRgbOperation. +RgbaToRgbOperation::RgbaToRgbOperation() {} + +bool RgbaToRgbOperation::ValidateParams() { return true; } + +std::shared_ptr RgbaToRgbOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + +// SwapRedBlueOperation. +SwapRedBlueOperation::SwapRedBlueOperation() {} + +bool SwapRedBlueOperation::ValidateParams() { return true; } + +std::shared_ptr SwapRedBlueOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + +// UniformAugOperation +UniformAugOperation::UniformAugOperation(std::vector> transforms, int32_t num_ops) + : transforms_(transforms), num_ops_(num_ops) {} + +bool UniformAugOperation::ValidateParams() { return true; } + +std::shared_ptr UniformAugOperation::Build() { + std::vector> tensor_ops; + (void)std::transform(transforms_.begin(), transforms_.end(), std::back_inserter(tensor_ops), + [](std::shared_ptr op) -> std::shared_ptr { return op->Build(); }); + std::shared_ptr tensor_op = std::make_shared(tensor_ops, num_ops_); + return tensor_op; +} + +} // namespace vision +} // namespace api +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/include/text.h b/mindspore/ccsrc/minddata/dataset/include/text.h index 3b9caddafe..e865f827da 100644 --- a/mindspore/ccsrc/minddata/dataset/include/text.h +++ b/mindspore/ccsrc/minddata/dataset/include/text.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_API_TEXT_H_ -#define MINDSPORE_CCSRC_MINDDATA_DATASET_API_TEXT_H_ +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TEXT_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TEXT_H_ #include #include @@ -68,4 +68,4 @@ class LookupOperation : public TensorOperation { } // namespace api } // namespace dataset } // namespace mindspore -#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_API_TEXT_H_ +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TEXT_H_ diff --git a/mindspore/ccsrc/minddata/dataset/include/transforms.h b/mindspore/ccsrc/minddata/dataset/include/transforms.h index 322794cbff..925a40148e 100644 --- a/mindspore/ccsrc/minddata/dataset/include/transforms.h +++ b/mindspore/ccsrc/minddata/dataset/include/transforms.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_API_TRANSFORMS_H_ -#define MINDSPORE_CCSRC_MINDDATA_DATASET_API_TRANSFORMS_H_ +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TRANSFORMS_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TRANSFORMS_H_ #include #include @@ -43,92 +43,11 @@ class TensorOperation : public std::enable_shared_from_this { virtual bool ValidateParams() = 0; }; -// Transform operations for performing computer vision. -namespace vision { +// Transform operations for performing data transformation. +namespace transforms { // Transform Op classes (in alphabetical order) -class CenterCropOperation; -class CropOperation; -class CutMixBatchOperation; -class CutOutOperation; -class DecodeOperation; -class HwcToChwOperation; -class MixUpBatchOperation; -class NormalizeOperation; class OneHotOperation; -class PadOperation; -class RandomAffineOperation; -class RandomColorOperation; -class RandomColorAdjustOperation; -class RandomCropOperation; -class RandomHorizontalFlipOperation; -class RandomPosterizeOperation; -class RandomRotationOperation; -class RandomSharpnessOperation; -class RandomSolarizeOperation; -class RandomVerticalFlipOperation; -class ResizeOperation; -class RgbaToBgrOperation; -class RgbaToRgbOperation; -class SwapRedBlueOperation; -class UniformAugOperation; - -/// \brief Function to create a CenterCrop TensorOperation. -/// \notes Crops the input image at the center to the given size. -/// \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). -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr CenterCrop(std::vector size); - -/// \brief Function to create a Crop TensorOp -/// \notes Crop an image based on location and crop size -/// \param[in] coordinates Starting location of crop. Must be a vector of two values, in the form of {x_coor, y_coor} -/// \param[in] size Size of the cropped area. Must be a vector of two values, in the form of {height, width} -/// \return Shared pointer to the current TensorOp -std::shared_ptr Crop(std::vector coordinates, std::vector size); - -/// \brief Function to apply CutMix on a batch of images -/// \notes Masks a random section of each image with the corresponding part of another randomly selected image in -/// that batch -/// \param[in] image_batch_format The format of the batch -/// \param[in] alpha The hyperparameter of beta distribution (default = 1.0) -/// \param[in] prob The probability by which CutMix is applied to each image (default = 1.0) -/// \return Shared pointer to the current TensorOp -std::shared_ptr CutMixBatch(ImageBatchFormat image_batch_format, float alpha = 1.0, - float prob = 1.0); - -/// \brief Function to create a CutOut TensorOp -/// \notes Randomly cut (mask) out a given number of square patches from the input image -/// \param[in] length Integer representing the side length of each square patch -/// \param[in] num_patches Integer representing the number of patches to be cut out of an image -/// \return Shared pointer to the current TensorOp -std::shared_ptr CutOut(int32_t length, int32_t num_patches = 1); - -/// \brief Function to create a Decode TensorOperation. -/// \notes Decode the input image in RGB mode. -/// \param[in] rgb - a boolean of whether to decode in RGB mode or not. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr Decode(bool rgb = true); - -/// \brief Function to create a HwcToChw TensorOperation. -/// \notes Transpose the input image; shape (H, W, C) to shape (C, H, W). -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr HWC2CHW(); - -/// \brief Function to create a MixUpBatch TensorOperation. -/// \notes Apply MixUp transformation on an input batch of images and labels. The labels must be in one-hot format and -/// Batch must be called before calling this function. -/// \param[in] alpha hyperparameter of beta distribution (default = 1.0) -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr MixUpBatch(float alpha = 1); - -/// \brief Function to create a Normalize TensorOperation. -/// \notes Normalize the input image with respect to mean and standard deviation. -/// \param[in] mean A vector of mean values for each channel, w.r.t channel order. -/// \param[in] std A vector of standard deviations for each channel, w.r.t. channel order. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr Normalize(std::vector mean, std::vector std); /// \brief Function to create a OneHot TensorOperation. /// \notes Convert the labels into OneHot format. @@ -136,281 +55,8 @@ std::shared_ptr Normalize(std::vector mean, std::vect /// \return Shared pointer to the current TensorOperation. std::shared_ptr OneHot(int32_t num_classes); -/// \brief Function to create a Pad TensorOp -/// \notes Pads the image according to padding parameters -/// \param[in] padding A vector representing the number of pixels to pad the image -/// If vector has one value, it pads all sides of the image with that value -/// If vector has two values, it pads left and right with the first and -/// top and bottom with the second value -/// If vector has four values, it pads left, top, right, and bottom with -/// those values respectively -/// \param[in] fill_value A vector representing the pixel intensity of the borders if the padding_mode is -/// BorderType.kConstant. If 3 values are provided, -/// it is used to fill R, G, B channels respectively -/// \param[in] padding_mode The method of padding (default=BorderType.kConstant) -/// Can be any of -/// [BorderType.kConstant, BorderType.kEdge, BorderType.kReflect, BorderType.kSymmetric] -/// - BorderType.kConstant, means it fills the border with constant values -/// - BorderType.kEdge, means it pads with the last value on the edge -/// - BorderType.kReflect, means it reflects the values on the edge omitting the last value of edge -/// - BorderType.kSymmetric, means it reflects the values on the edge repeating the last value of edge -/// \return Shared pointer to the current TensorOp -std::shared_ptr Pad(std::vector padding, std::vector fill_value = {0}, - BorderType padding_mode = BorderType::kConstant); - -/// \brief Function to create a RandomAffine TensorOperation. -/// \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] 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] 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] 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. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomAffine( - const std::vector °rees, const std::vector &translate_range = {0.0, 0.0, 0.0, 0.0}, - const std::vector &scale_range = {1.0, 1.0}, const std::vector &shear_ranges = {0.0, 0.0, 0.0, 0.0}, - InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, - const std::vector &fill_value = {0, 0, 0}); - -/// \brief Blends an image with its grayscale version with random weights -/// t and 1 - t generated from a given range. If the range is trivial -/// then the weights are determinate and t equals the bound of the interval -/// \param[in] t_lb lower bound on the range of random weights -/// \param[in] t_lb upper bound on the range of random weights -/// \return Shared pointer to the current TensorOp -std::shared_ptr RandomColor(float t_lb, float t_ub); - -/// \brief Randomly adjust the brightness, contrast, saturation, and hue of the input image -/// \param[in] brightness Brightness adjustment factor. Must be a vector of one or two values -/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} -/// \param[in] contrast Contrast adjustment factor. Must be a vector of one or two values -/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} -/// \param[in] saturation Saturation adjustment factor. Must be a vector of one or two values -/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} -/// \param[in] hue Brightness adjustment factor. Must be a vector of one or two values -/// if it's a vector of two values it must be in the form of [min, max] where -0.5 <= min <= max <= 0.5 -/// Default value is {0, 0} -/// \return Shared pointer to the current TensorOp -std::shared_ptr RandomColorAdjust(std::vector brightness = {1.0, 1.0}, - std::vector contrast = {1.0, 1.0}, - std::vector saturation = {1.0, 1.0}, - std::vector hue = {0.0, 0.0}); - -/// \brief Function to create a RandomCrop TensorOperation. -/// \notes Crop the input image at a random location. -/// \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] padding - a vector with the value of pixels to pad the image. If 4 values are provided, -/// it pads the left, top, right and bottom respectively. -/// \param[in] pad_if_needed - a boolean whether to pad the image if either side is smaller than -/// the given output size. -/// \param[in] fill_value - a vector representing the pixel intensity of the borders, it is used to -/// fill R, G, B channels respectively. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomCrop(std::vector size, std::vector padding = {0, 0, 0, 0}, - bool pad_if_needed = false, std::vector fill_value = {0, 0, 0}, - BorderType padding_mode = BorderType::kConstant); - -/// \brief Function to create a RandomHorizontalFlip TensorOperation. -/// \notes Tensor operation to perform random horizontal flip. -/// \param[in] prob - float representing the probability of flip. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomHorizontalFlip(float prob = 0.5); - -/// \brief Function to create a RandomPosterize TensorOperation. -/// \notes Tensor operation to perform random posterize. -/// \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. -std::shared_ptr RandomPosterize(const std::vector &bit_range = {4, 8}); - -/// \brief Function to create a RandomRotation TensorOp -/// \notes Rotates the image according to parameters -/// \param[in] degrees A float vector size 2, representing the starting and ending degree -/// \param[in] resample An enum for the mode of interpolation -/// \param[in] expand A boolean representing whether the image is expanded after rotation -/// \param[in] center A float vector size 2, representing the x and y center of rotation. -/// \param[in] fill_value A uint8_t vector size 3, representing the rgb value of the fill color -/// \return Shared pointer to the current TensorOp -std::shared_ptr RandomRotation( - std::vector degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour, bool expand = false, - std::vector center = {-1, -1}, std::vector fill_value = {0, 0, 0}); - -/// \brief Function to create a RandomSharpness TensorOperation. -/// \notes Tensor operation to perform random sharpness. -/// \param[in] start_degree - float representing the start of the range to uniformly sample the factor from it. -/// \param[in] end_degree - float representing the end of the range. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomSharpness(std::vector degrees = {0.1, 1.9}); - -/// \brief Function to create a RandomSolarize TensorOperation. -/// \notes Invert pixels within specified range. If min=max, then it inverts all pixel above that threshold -/// \param[in] threshold - a vector with two elements specifying the pixel range to invert. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomSolarize(std::vector threshold = {0, 255}); - -/// \brief Function to create a RandomVerticalFlip TensorOperation. -/// \notes Tensor operation to perform random vertical flip. -/// \param[in] prob - float representing the probability of flip. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RandomVerticalFlip(float prob = 0.5); - -/// \brief Function to create a RgbaToBgr TensorOperation. -/// \notes Changes the input 4 channel RGBA tensor to 3 channel BGR. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RGBA2BGR(); - -/// \brief Function to create a RgbaToRgb TensorOperation. -/// \notes Changes the input 4 channel RGBA tensor to 3 channel RGB. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr RGBA2RGB(); - -/// \brief Function to create a Resize TensorOperation. -/// \notes Resize the input image to the given size. -/// \param[in] size - a vector representing the output size of the resized image. -/// If size is a single value, the image will be resized to this value with -/// the same image aspect ratio. If size has 2 values, it should be (height, width). -/// \param[in] interpolation An enum for the mode of interpolation -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr Resize(std::vector size, - InterpolationMode interpolation = InterpolationMode::kLinear); - -/// \brief Function to create a SwapRedBlue TensorOp -/// \notes Swaps the red and blue channels in image -/// \return Shared pointer to the current TensorOp -std::shared_ptr SwapRedBlue(); - -/// \brief Function to create a UniformAugment TensorOperation. -/// \notes Tensor operation to perform randomly selected augmentation. -/// \param[in] transforms - a vector of TensorOperation transforms. -/// \param[in] num_ops - integer representing the number of OPs to be selected and applied. -/// \return Shared pointer to the current TensorOperation. -std::shared_ptr UniformAugment(std::vector> transforms, - int32_t num_ops = 2); - /* ####################################### Derived TensorOperation classes ################################# */ -class CenterCropOperation : public TensorOperation { - public: - explicit CenterCropOperation(std::vector size); - - ~CenterCropOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector size_; -}; - -class CropOperation : public TensorOperation { - public: - CropOperation(std::vector coordinates, std::vector size); - - ~CropOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector coordinates_; - std::vector size_; -}; - -class CutMixBatchOperation : public TensorOperation { - public: - explicit CutMixBatchOperation(ImageBatchFormat image_batch_format, float alpha = 1.0, float prob = 1.0); - - ~CutMixBatchOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - float alpha_; - float prob_; - ImageBatchFormat image_batch_format_; -}; - -class CutOutOperation : public TensorOperation { - public: - explicit CutOutOperation(int32_t length, int32_t num_patches = 1); - - ~CutOutOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - int32_t length_; - int32_t num_patches_; - ImageBatchFormat image_batch_format_; -}; - -class DecodeOperation : public TensorOperation { - public: - explicit DecodeOperation(bool rgb = true); - - ~DecodeOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - bool rgb_; -}; - -class HwcToChwOperation : public TensorOperation { - public: - ~HwcToChwOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; -}; - -class MixUpBatchOperation : public TensorOperation { - public: - explicit MixUpBatchOperation(float alpha = 1); - - ~MixUpBatchOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - float alpha_; -}; - -class NormalizeOperation : public TensorOperation { - public: - NormalizeOperation(std::vector mean, std::vector std); - - ~NormalizeOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector mean_; - std::vector std_; -}; - class OneHotOperation : public TensorOperation { public: explicit OneHotOperation(int32_t num_classes_); @@ -424,254 +70,8 @@ class OneHotOperation : public TensorOperation { private: float num_classes_; }; - -class PadOperation : public TensorOperation { - public: - PadOperation(std::vector padding, std::vector fill_value = {0}, - BorderType padding_mode = BorderType::kConstant); - - ~PadOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector padding_; - std::vector fill_value_; - BorderType padding_mode_; -}; - -class RandomAffineOperation : public TensorOperation { - public: - RandomAffineOperation(const std::vector °rees, const std::vector &translate_range = {0.0, 0.0}, - const std::vector &scale_range = {1.0, 1.0}, - const std::vector &shear_ranges = {0.0, 0.0, 0.0, 0.0}, - InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, - const std::vector &fill_value = {0, 0, 0}); - - ~RandomAffineOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector degrees_; // min_degree, max_degree - std::vector translate_range_; // maximum x translation percentage, maximum y translation percentage - std::vector scale_range_; // min_scale, max_scale - std::vector shear_ranges_; // min_x_shear, max_x_shear, min_y_shear, max_y_shear - InterpolationMode interpolation_; - std::vector fill_value_; -}; - -class RandomColorOperation : public TensorOperation { - public: - RandomColorOperation(float t_lb, float t_ub); - - ~RandomColorOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - float t_lb_; - float t_ub_; -}; - -class RandomColorAdjustOperation : public TensorOperation { - public: - RandomColorAdjustOperation(std::vector brightness = {1.0, 1.0}, std::vector contrast = {1.0, 1.0}, - std::vector saturation = {1.0, 1.0}, std::vector hue = {0.0, 0.0}); - - ~RandomColorAdjustOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector brightness_; - std::vector contrast_; - std::vector saturation_; - std::vector hue_; -}; - -class RandomCropOperation : public TensorOperation { - public: - RandomCropOperation(std::vector size, std::vector padding = {0, 0, 0, 0}, - bool pad_if_needed = false, std::vector fill_value = {0, 0, 0}, - BorderType padding_mode = BorderType::kConstant); - - ~RandomCropOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector size_; - std::vector padding_; - bool pad_if_needed_; - std::vector fill_value_; - BorderType padding_mode_; -}; - -class RandomHorizontalFlipOperation : public TensorOperation { - public: - explicit RandomHorizontalFlipOperation(float probability = 0.5); - - ~RandomHorizontalFlipOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - float probability_; -}; - -class RandomPosterizeOperation : public TensorOperation { - public: - explicit RandomPosterizeOperation(const std::vector &bit_range = {4, 8}); - - ~RandomPosterizeOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector bit_range_; -}; - -class RandomRotationOperation : public TensorOperation { - public: - RandomRotationOperation(std::vector degrees, InterpolationMode interpolation_mode, bool expand, - std::vector center, std::vector fill_value); - - ~RandomRotationOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector degrees_; - InterpolationMode interpolation_mode_; - std::vector center_; - bool expand_; - std::vector fill_value_; -}; - -class RandomSharpnessOperation : public TensorOperation { - public: - explicit RandomSharpnessOperation(std::vector degrees = {0.1, 1.9}); - - ~RandomSharpnessOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector degrees_; -}; - -class RandomVerticalFlipOperation : public TensorOperation { - public: - explicit RandomVerticalFlipOperation(float probability = 0.5); - - ~RandomVerticalFlipOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - float probability_; -}; - -class ResizeOperation : public TensorOperation { - public: - explicit ResizeOperation(std::vector size, - InterpolationMode interpolation_mode = InterpolationMode::kLinear); - - ~ResizeOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector size_; - InterpolationMode interpolation_; -}; - -class RgbaToBgrOperation : public TensorOperation { - public: - RgbaToBgrOperation(); - - ~RgbaToBgrOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; -}; - -class RgbaToRgbOperation : public TensorOperation { - public: - RgbaToRgbOperation(); - - ~RgbaToRgbOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; -}; - -class UniformAugOperation : public TensorOperation { - public: - explicit UniformAugOperation(std::vector> transforms, int32_t num_ops = 2); - - ~UniformAugOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector> transforms_; - int32_t num_ops_; -}; - -class SwapRedBlueOperation : public TensorOperation { - public: - SwapRedBlueOperation(); - - ~SwapRedBlueOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; -}; - -class RandomSolarizeOperation : public TensorOperation { - public: - explicit RandomSolarizeOperation(std::vector threshold); - - ~RandomSolarizeOperation() = default; - - std::shared_ptr Build() override; - - bool ValidateParams() override; - - private: - std::vector threshold_; -}; -} // namespace vision +} // namespace transforms } // namespace api } // namespace dataset } // namespace mindspore -#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_API_TRANSFORMS_H_ +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_TRANSFORMS_H_ diff --git a/mindspore/ccsrc/minddata/dataset/include/vision.h b/mindspore/ccsrc/minddata/dataset/include/vision.h new file mode 100644 index 0000000000..c76ec585da --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/include/vision.h @@ -0,0 +1,639 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_H_ + +#include +#include +#include "minddata/dataset/core/constants.h" +#include "minddata/dataset/include/transforms.h" + +namespace mindspore { +namespace dataset { +namespace api { + +// Transform operations for performing computer vision. +namespace vision { + +// Transform Op classes (in alphabetical order) +class CenterCropOperation; +class CropOperation; +class CutMixBatchOperation; +class CutOutOperation; +class DecodeOperation; +class HwcToChwOperation; +class MixUpBatchOperation; +class NormalizeOperation; +class PadOperation; +class RandomAffineOperation; +class RandomColorOperation; +class RandomColorAdjustOperation; +class RandomCropOperation; +class RandomHorizontalFlipOperation; +class RandomPosterizeOperation; +class RandomRotationOperation; +class RandomSharpnessOperation; +class RandomSolarizeOperation; +class RandomVerticalFlipOperation; +class ResizeOperation; +class RgbaToBgrOperation; +class RgbaToRgbOperation; +class SwapRedBlueOperation; +class UniformAugOperation; + +/// \brief Function to create a CenterCrop TensorOperation. +/// \notes Crops the input image at the center to the given size. +/// \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). +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr CenterCrop(std::vector size); + +/// \brief Function to create a Crop TensorOp +/// \notes Crop an image based on location and crop size +/// \param[in] coordinates Starting location of crop. Must be a vector of two values, in the form of {x_coor, y_coor} +/// \param[in] size Size of the cropped area. Must be a vector of two values, in the form of {height, width} +/// \return Shared pointer to the current TensorOp +std::shared_ptr Crop(std::vector coordinates, std::vector size); + +/// \brief Function to apply CutMix on a batch of images +/// \notes Masks a random section of each image with the corresponding part of another randomly selected image in +/// that batch +/// \param[in] image_batch_format The format of the batch +/// \param[in] alpha The hyperparameter of beta distribution (default = 1.0) +/// \param[in] prob The probability by which CutMix is applied to each image (default = 1.0) +/// \return Shared pointer to the current TensorOp +std::shared_ptr CutMixBatch(ImageBatchFormat image_batch_format, float alpha = 1.0, + float prob = 1.0); + +/// \brief Function to create a CutOut TensorOp +/// \notes Randomly cut (mask) out a given number of square patches from the input image +/// \param[in] length Integer representing the side length of each square patch +/// \param[in] num_patches Integer representing the number of patches to be cut out of an image +/// \return Shared pointer to the current TensorOp +std::shared_ptr CutOut(int32_t length, int32_t num_patches = 1); + +/// \brief Function to create a Decode TensorOperation. +/// \notes Decode the input image in RGB mode. +/// \param[in] rgb - a boolean of whether to decode in RGB mode or not. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr Decode(bool rgb = true); + +/// \brief Function to create a HwcToChw TensorOperation. +/// \notes Transpose the input image; shape (H, W, C) to shape (C, H, W). +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr HWC2CHW(); + +/// \brief Function to create a MixUpBatch TensorOperation. +/// \notes Apply MixUp transformation on an input batch of images and labels. The labels must be in one-hot format and +/// Batch must be called before calling this function. +/// \param[in] alpha hyperparameter of beta distribution (default = 1.0) +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr MixUpBatch(float alpha = 1); + +/// \brief Function to create a Normalize TensorOperation. +/// \notes Normalize the input image with respect to mean and standard deviation. +/// \param[in] mean A vector of mean values for each channel, w.r.t channel order. +/// \param[in] std A vector of standard deviations for each channel, w.r.t. channel order. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr Normalize(std::vector mean, std::vector std); + +/// \brief Function to create a Pad TensorOp +/// \notes Pads the image according to padding parameters +/// \param[in] padding A vector representing the number of pixels to pad the image +/// If vector has one value, it pads all sides of the image with that value +/// If vector has two values, it pads left and right with the first and +/// top and bottom with the second value +/// If vector has four values, it pads left, top, right, and bottom with +/// those values respectively +/// \param[in] fill_value A vector representing the pixel intensity of the borders if the padding_mode is +/// BorderType.kConstant. If 3 values are provided, +/// it is used to fill R, G, B channels respectively +/// \param[in] padding_mode The method of padding (default=BorderType.kConstant) +/// Can be any of +/// [BorderType.kConstant, BorderType.kEdge, BorderType.kReflect, BorderType.kSymmetric] +/// - BorderType.kConstant, means it fills the border with constant values +/// - BorderType.kEdge, means it pads with the last value on the edge +/// - BorderType.kReflect, means it reflects the values on the edge omitting the last value of edge +/// - BorderType.kSymmetric, means it reflects the values on the edge repeating the last value of edge +/// \return Shared pointer to the current TensorOp +std::shared_ptr Pad(std::vector padding, std::vector fill_value = {0}, + BorderType padding_mode = BorderType::kConstant); + +/// \brief Function to create a RandomAffine TensorOperation. +/// \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] 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] 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] 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. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomAffine( + const std::vector °rees, const std::vector &translate_range = {0.0, 0.0, 0.0, 0.0}, + const std::vector &scale_range = {1.0, 1.0}, const std::vector &shear_ranges = {0.0, 0.0, 0.0, 0.0}, + InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, + const std::vector &fill_value = {0, 0, 0}); + +/// \brief Blends an image with its grayscale version with random weights +/// t and 1 - t generated from a given range. If the range is trivial +/// then the weights are determinate and t equals the bound of the interval +/// \param[in] t_lb lower bound on the range of random weights +/// \param[in] t_lb upper bound on the range of random weights +/// \return Shared pointer to the current TensorOp +std::shared_ptr RandomColor(float t_lb, float t_ub); + +/// \brief Randomly adjust the brightness, contrast, saturation, and hue of the input image +/// \param[in] brightness Brightness adjustment factor. Must be a vector of one or two values +/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} +/// \param[in] contrast Contrast adjustment factor. Must be a vector of one or two values +/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} +/// \param[in] saturation Saturation adjustment factor. Must be a vector of one or two values +/// if it's a vector of two values it needs to be in the form of [min, max]. Default value is {1, 1} +/// \param[in] hue Brightness adjustment factor. Must be a vector of one or two values +/// if it's a vector of two values it must be in the form of [min, max] where -0.5 <= min <= max <= 0.5 +/// Default value is {0, 0} +/// \return Shared pointer to the current TensorOp +std::shared_ptr RandomColorAdjust(std::vector brightness = {1.0, 1.0}, + std::vector contrast = {1.0, 1.0}, + std::vector saturation = {1.0, 1.0}, + std::vector hue = {0.0, 0.0}); + +/// \brief Function to create a RandomCrop TensorOperation. +/// \notes Crop the input image at a random location. +/// \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] padding - a vector with the value of pixels to pad the image. If 4 values are provided, +/// it pads the left, top, right and bottom respectively. +/// \param[in] pad_if_needed - a boolean whether to pad the image if either side is smaller than +/// the given output size. +/// \param[in] fill_value - a vector representing the pixel intensity of the borders, it is used to +/// fill R, G, B channels respectively. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomCrop(std::vector size, std::vector padding = {0, 0, 0, 0}, + bool pad_if_needed = false, std::vector fill_value = {0, 0, 0}, + BorderType padding_mode = BorderType::kConstant); + +/// \brief Function to create a RandomHorizontalFlip TensorOperation. +/// \notes Tensor operation to perform random horizontal flip. +/// \param[in] prob - float representing the probability of flip. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomHorizontalFlip(float prob = 0.5); + +/// \brief Function to create a RandomPosterize TensorOperation. +/// \notes Tensor operation to perform random posterize. +/// \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. +std::shared_ptr RandomPosterize(const std::vector &bit_range = {4, 8}); + +/// \brief Function to create a RandomRotation TensorOp +/// \notes Rotates the image according to parameters +/// \param[in] degrees A float vector size 2, representing the starting and ending degree +/// \param[in] resample An enum for the mode of interpolation +/// \param[in] expand A boolean representing whether the image is expanded after rotation +/// \param[in] center A float vector size 2, representing the x and y center of rotation. +/// \param[in] fill_value A uint8_t vector size 3, representing the rgb value of the fill color +/// \return Shared pointer to the current TensorOp +std::shared_ptr RandomRotation( + std::vector degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour, bool expand = false, + std::vector center = {-1, -1}, std::vector fill_value = {0, 0, 0}); + +/// \brief Function to create a RandomSharpness TensorOperation. +/// \notes Tensor operation to perform random sharpness. +/// \param[in] start_degree - float representing the start of the range to uniformly sample the factor from it. +/// \param[in] end_degree - float representing the end of the range. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomSharpness(std::vector degrees = {0.1, 1.9}); + +/// \brief Function to create a RandomSolarize TensorOperation. +/// \notes Invert pixels within specified range. If min=max, then it inverts all pixel above that threshold +/// \param[in] threshold - a vector with two elements specifying the pixel range to invert. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomSolarize(std::vector threshold = {0, 255}); + +/// \brief Function to create a RandomVerticalFlip TensorOperation. +/// \notes Tensor operation to perform random vertical flip. +/// \param[in] prob - float representing the probability of flip. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RandomVerticalFlip(float prob = 0.5); + +/// \brief Function to create a Resize TensorOperation. +/// \notes Resize the input image to the given size. +/// \param[in] size - a vector representing the output size of the resized image. +/// If size is a single value, the image will be resized to this value with +/// the same image aspect ratio. If size has 2 values, it should be (height, width). +/// \param[in] interpolation An enum for the mode of interpolation +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr Resize(std::vector size, + InterpolationMode interpolation = InterpolationMode::kLinear); + +/// \brief Function to create a RgbaToBgr TensorOperation. +/// \notes Changes the input 4 channel RGBA tensor to 3 channel BGR. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RGBA2BGR(); + +/// \brief Function to create a RgbaToRgb TensorOperation. +/// \notes Changes the input 4 channel RGBA tensor to 3 channel RGB. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RGBA2RGB(); + +/// \brief Function to create a SwapRedBlue TensorOp +/// \notes Swaps the red and blue channels in image +/// \return Shared pointer to the current TensorOp +std::shared_ptr SwapRedBlue(); + +/// \brief Function to create a UniformAugment TensorOperation. +/// \notes Tensor operation to perform randomly selected augmentation. +/// \param[in] transforms - a vector of TensorOperation transforms. +/// \param[in] num_ops - integer representing the number of OPs to be selected and applied. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr UniformAugment(std::vector> transforms, + int32_t num_ops = 2); + +/* ####################################### Derived TensorOperation classes ################################# */ + +class CenterCropOperation : public TensorOperation { + public: + explicit CenterCropOperation(std::vector size); + + ~CenterCropOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector size_; +}; + +class CropOperation : public TensorOperation { + public: + CropOperation(std::vector coordinates, std::vector size); + + ~CropOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector coordinates_; + std::vector size_; +}; + +class CutMixBatchOperation : public TensorOperation { + public: + explicit CutMixBatchOperation(ImageBatchFormat image_batch_format, float alpha = 1.0, float prob = 1.0); + + ~CutMixBatchOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + float alpha_; + float prob_; + ImageBatchFormat image_batch_format_; +}; + +class CutOutOperation : public TensorOperation { + public: + explicit CutOutOperation(int32_t length, int32_t num_patches = 1); + + ~CutOutOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + int32_t length_; + int32_t num_patches_; + ImageBatchFormat image_batch_format_; +}; + +class DecodeOperation : public TensorOperation { + public: + explicit DecodeOperation(bool rgb = true); + + ~DecodeOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + bool rgb_; +}; + +class HwcToChwOperation : public TensorOperation { + public: + ~HwcToChwOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + +class MixUpBatchOperation : public TensorOperation { + public: + explicit MixUpBatchOperation(float alpha = 1); + + ~MixUpBatchOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + float alpha_; +}; + +class NormalizeOperation : public TensorOperation { + public: + NormalizeOperation(std::vector mean, std::vector std); + + ~NormalizeOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector mean_; + std::vector std_; +}; + +class PadOperation : public TensorOperation { + public: + PadOperation(std::vector padding, std::vector fill_value = {0}, + BorderType padding_mode = BorderType::kConstant); + + ~PadOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector padding_; + std::vector fill_value_; + BorderType padding_mode_; +}; + +class RandomAffineOperation : public TensorOperation { + public: + RandomAffineOperation(const std::vector °rees, const std::vector &translate_range = {0.0, 0.0}, + const std::vector &scale_range = {1.0, 1.0}, + const std::vector &shear_ranges = {0.0, 0.0, 0.0, 0.0}, + InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, + const std::vector &fill_value = {0, 0, 0}); + + ~RandomAffineOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector degrees_; // min_degree, max_degree + std::vector translate_range_; // maximum x translation percentage, maximum y translation percentage + std::vector scale_range_; // min_scale, max_scale + std::vector shear_ranges_; // min_x_shear, max_x_shear, min_y_shear, max_y_shear + InterpolationMode interpolation_; + std::vector fill_value_; +}; + +class RandomColorOperation : public TensorOperation { + public: + RandomColorOperation(float t_lb, float t_ub); + + ~RandomColorOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + float t_lb_; + float t_ub_; +}; + +class RandomColorAdjustOperation : public TensorOperation { + public: + RandomColorAdjustOperation(std::vector brightness = {1.0, 1.0}, std::vector contrast = {1.0, 1.0}, + std::vector saturation = {1.0, 1.0}, std::vector hue = {0.0, 0.0}); + + ~RandomColorAdjustOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector brightness_; + std::vector contrast_; + std::vector saturation_; + std::vector hue_; +}; + +class RandomCropOperation : public TensorOperation { + public: + RandomCropOperation(std::vector size, std::vector padding = {0, 0, 0, 0}, + bool pad_if_needed = false, std::vector fill_value = {0, 0, 0}, + BorderType padding_mode = BorderType::kConstant); + + ~RandomCropOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector size_; + std::vector padding_; + bool pad_if_needed_; + std::vector fill_value_; + BorderType padding_mode_; +}; + +class RandomHorizontalFlipOperation : public TensorOperation { + public: + explicit RandomHorizontalFlipOperation(float probability = 0.5); + + ~RandomHorizontalFlipOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + float probability_; +}; + +class RandomPosterizeOperation : public TensorOperation { + public: + explicit RandomPosterizeOperation(const std::vector &bit_range = {4, 8}); + + ~RandomPosterizeOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector bit_range_; +}; + +class RandomRotationOperation : public TensorOperation { + public: + RandomRotationOperation(std::vector degrees, InterpolationMode interpolation_mode, bool expand, + std::vector center, std::vector fill_value); + + ~RandomRotationOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector degrees_; + InterpolationMode interpolation_mode_; + std::vector center_; + bool expand_; + std::vector fill_value_; +}; + +class RandomSharpnessOperation : public TensorOperation { + public: + explicit RandomSharpnessOperation(std::vector degrees = {0.1, 1.9}); + + ~RandomSharpnessOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector degrees_; +}; + +class RandomSolarizeOperation : public TensorOperation { + public: + explicit RandomSolarizeOperation(std::vector threshold); + + ~RandomSolarizeOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector threshold_; +}; + +class RandomVerticalFlipOperation : public TensorOperation { + public: + explicit RandomVerticalFlipOperation(float probability = 0.5); + + ~RandomVerticalFlipOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + float probability_; +}; + +class ResizeOperation : public TensorOperation { + public: + explicit ResizeOperation(std::vector size, + InterpolationMode interpolation_mode = InterpolationMode::kLinear); + + ~ResizeOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector size_; + InterpolationMode interpolation_; +}; + +class RgbaToBgrOperation : public TensorOperation { + public: + RgbaToBgrOperation(); + + ~RgbaToBgrOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + +class RgbaToRgbOperation : public TensorOperation { + public: + RgbaToRgbOperation(); + + ~RgbaToRgbOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + +class SwapRedBlueOperation : public TensorOperation { + public: + SwapRedBlueOperation(); + + ~SwapRedBlueOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + +class UniformAugOperation : public TensorOperation { + public: + explicit UniformAugOperation(std::vector> transforms, int32_t num_ops = 2); + + ~UniformAugOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector> transforms_; + int32_t num_ops_; +}; +} // namespace vision +} // namespace api +} // namespace dataset +} // namespace mindspore +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_H_ diff --git a/tests/ut/cpp/dataset/CMakeLists.txt b/tests/ut/cpp/dataset/CMakeLists.txt index acf763d55c..1072324ea1 100644 --- a/tests/ut/cpp/dataset/CMakeLists.txt +++ b/tests/ut/cpp/dataset/CMakeLists.txt @@ -102,6 +102,7 @@ SET(DE_UT_SRCS build_vocab_test.cc c_api_samplers_test.cc c_api_transforms_test.cc + c_api_vision_test.cc c_api_dataset_ops_test.cc c_api_dataset_album_test.cc c_api_dataset_cifar_test.cc @@ -124,8 +125,8 @@ SET(DE_UT_SRCS swap_red_blue_test.cc distributed_sampler_test.cc data_helper_test.cc - image_process_test.cc - slice_op_test.cc + image_process_test.cc + slice_op_test.cc ) if (ENABLE_PYTHON) diff --git a/tests/ut/cpp/dataset/c_api_dataset_ops_test.cc b/tests/ut/cpp/dataset/c_api_dataset_ops_test.cc index f8b2b2a856..53335da037 100644 --- a/tests/ut/cpp/dataset/c_api_dataset_ops_test.cc +++ b/tests/ut/cpp/dataset/c_api_dataset_ops_test.cc @@ -16,7 +16,7 @@ #include "common/common.h" #include "minddata/dataset/core/tensor_row.h" #include "minddata/dataset/include/datasets.h" -#include "minddata/dataset/include/transforms.h" +#include "minddata/dataset/include/vision.h" using namespace mindspore::dataset::api; using mindspore::dataset::Tensor; diff --git a/tests/ut/cpp/dataset/c_api_dataset_tfrecord_test.cc b/tests/ut/cpp/dataset/c_api_dataset_tfrecord_test.cc index 83d2ed2333..267b50177e 100644 --- a/tests/ut/cpp/dataset/c_api_dataset_tfrecord_test.cc +++ b/tests/ut/cpp/dataset/c_api_dataset_tfrecord_test.cc @@ -15,7 +15,7 @@ */ #include "common/common.h" #include "minddata/dataset/include/datasets.h" -#include "minddata/dataset/include/transforms.h" +#include "minddata/dataset/include/vision.h" #include "minddata/dataset/core/config_manager.h" #include "minddata/dataset/core/global_context.h" diff --git a/tests/ut/cpp/dataset/c_api_transforms_test.cc b/tests/ut/cpp/dataset/c_api_transforms_test.cc index 0df131076f..aaa8283581 100644 --- a/tests/ut/cpp/dataset/c_api_transforms_test.cc +++ b/tests/ut/cpp/dataset/c_api_transforms_test.cc @@ -16,6 +16,7 @@ #include "common/common.h" #include "minddata/dataset/include/datasets.h" #include "minddata/dataset/include/transforms.h" +#include "minddata/dataset/include/vision.h" using namespace mindspore::dataset::api; using mindspore::dataset::BorderType; @@ -25,7 +26,7 @@ class MindDataTestPipeline : public UT::DatasetOpTesting { protected: }; -TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess1) { +TEST_F(MindDataTestPipeline, TestOneHotSuccess1) { // Testing CutMixBatch on a batch of CHW images // Create a Cifar10 Dataset std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; @@ -47,7 +48,7 @@ TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess1) { EXPECT_NE(ds, nullptr); // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(number_of_classes); + std::shared_ptr one_hot_op = transforms::OneHot(number_of_classes); EXPECT_NE(one_hot_op, nullptr); // Create a Map operation on ds @@ -93,334 +94,7 @@ TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess1) { iter->Stop(); } -TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess2) { - // Calling CutMixBatch on a batch of HWC images with default values of alpha and prob - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - int number_of_classes = 10; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(number_of_classes); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr cutmix_batch_op = vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC); - EXPECT_NE(cutmix_batch_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({cutmix_batch_op}, {"image", "label"}); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> row; - iter->GetNextRow(&row); - - uint64_t i = 0; - while (row.size() != 0) { - i++; - auto image = row["image"]; - auto label = row["label"]; - MS_LOG(INFO) << "Tensor image shape: " << image->shape(); - MS_LOG(INFO) << "Label shape: " << label->shape(); - EXPECT_EQ(image->shape().AsVector().size() == 4 && batch_size == image->shape()[0] && 32 == image->shape()[1] && - 32 == image->shape()[2] && 3 == image->shape()[3], - true); - EXPECT_EQ(label->shape().AsVector().size() == 2 && batch_size == label->shape()[0] && - number_of_classes == label->shape()[1], - true); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 2); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestCutMixBatchFail1) { - // Must fail because alpha can't be negative - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr cutmix_batch_op = - vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, -1, 0.5); - EXPECT_EQ(cutmix_batch_op, nullptr); -} - -TEST_F(MindDataTestPipeline, TestCutMixBatchFail2) { - // Must fail because prob can't be negative - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr cutmix_batch_op = - vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, 1, -0.5); - EXPECT_EQ(cutmix_batch_op, nullptr); -} - -TEST_F(MindDataTestPipeline, TestCutMixBatchFail3) { - // Must fail because alpha can't be zero - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr cutmix_batch_op = - vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, 0.0, 0.5); - EXPECT_EQ(cutmix_batch_op, nullptr); -} - -TEST_F(MindDataTestPipeline, TestCutOut) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr cut_out1 = vision::CutOut(30, 5); - EXPECT_NE(cut_out1, nullptr); - - std::shared_ptr cut_out2 = vision::CutOut(30); - EXPECT_NE(cut_out2, nullptr); - - // Create a Map operation on ds - ds = ds->Map({cut_out1, cut_out2}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestDecode) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, false, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr decode = vision::Decode(true); - EXPECT_NE(decode, nullptr); - - // Create a Map operation on ds - ds = ds->Map({decode}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestHwcToChw) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr channel_swap = vision::HWC2CHW(); - EXPECT_NE(channel_swap, nullptr); - - // Create a Map operation on ds - ds = ds->Map({channel_swap}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - // check if the image is in NCHW - EXPECT_EQ(batch_size == image->shape()[0] && 3 == image->shape()[1] && 2268 == image->shape()[2] && - 4032 == image->shape()[3], - true); - iter->GetNextRow(&row); - } - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestMixUpBatchFail1) { - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr mixup_batch_op = vision::MixUpBatch(-1); - EXPECT_EQ(mixup_batch_op, nullptr); -} - -TEST_F(MindDataTestPipeline, TestMixUpBatchFail2) { - // This should fail because alpha can't be zero - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr mixup_batch_op = vision::MixUpBatch(0.0); - EXPECT_EQ(mixup_batch_op, nullptr); -} - -TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess1) { +TEST_F(MindDataTestPipeline, TestOneHotSuccess2) { // Create a Cifar10 Dataset std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); @@ -432,7 +106,7 @@ TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess1) { EXPECT_NE(ds, nullptr); // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); + std::shared_ptr one_hot_op = transforms::OneHot(10); EXPECT_NE(one_hot_op, nullptr); // Create a Map operation on ds @@ -468,847 +142,3 @@ TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess1) { // Manually terminate the pipeline iter->Stop(); } - -TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess2) { - // Create a Cifar10 Dataset - std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; - std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 5; - ds = ds->Batch(batch_size); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr one_hot_op = vision::OneHot(10); - EXPECT_NE(one_hot_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({one_hot_op}, {"label"}); - EXPECT_NE(ds, nullptr); - - std::shared_ptr mixup_batch_op = vision::MixUpBatch(); - EXPECT_NE(mixup_batch_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({mixup_batch_op}, {"image", "label"}); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 2); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestNormalize) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr normalize = vision::Normalize({121.0, 115.0, 100.0}, {70.0, 68.0, 71.0}); - EXPECT_NE(normalize, nullptr); - - // Create a Map operation on ds - ds = ds->Map({normalize}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestPad) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr pad_op1 = vision::Pad({1, 2, 3, 4}, {0}, BorderType::kSymmetric); - EXPECT_NE(pad_op1, nullptr); - - std::shared_ptr pad_op2 = vision::Pad({1}, {1, 1, 1}, BorderType::kEdge); - EXPECT_NE(pad_op2, nullptr); - - std::shared_ptr pad_op3 = vision::Pad({1, 4}); - EXPECT_NE(pad_op3, nullptr); - - // Create a Map operation on ds - ds = ds->Map({pad_op1, pad_op2, pad_op3}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomAffineFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineFail with invalid params."; - - // Create objects for the tensor ops - std::shared_ptr affine = vision::RandomAffine({0.0, 0.0}, {}); - EXPECT_EQ(affine, nullptr); - // Invalid number of values for translate - affine = vision::RandomAffine({0.0, 0.0}, {1, 1, 1, 1, 1}); - EXPECT_EQ(affine, nullptr); - // Invalid number of values for shear - affine = vision::RandomAffine({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0}); - EXPECT_EQ(affine, nullptr); -} - -TEST_F(MindDataTestPipeline, TestRandomAffineSuccess1) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineSuccess1 with non-default params."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr affine = - 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); - - // Create a Map operation on ds - ds = ds->Map({affine}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomAffineSuccess2) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineSuccess2 with default params."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr affine = vision::RandomAffine({0.0, 0.0}); - EXPECT_NE(affine, nullptr); - - // Create a Map operation on ds - ds = ds->Map({affine}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomColor) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomColor with non-default params."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_color_op_1 = vision::RandomColor(0.0, 0.0); - EXPECT_NE(random_color_op_1, nullptr); - - std::shared_ptr random_color_op_2 = vision::RandomColor(1.0, 0.1); - EXPECT_EQ(random_color_op_2, nullptr); - - std::shared_ptr random_color_op_3 = vision::RandomColor(0.0, 1.1); - EXPECT_NE(random_color_op_3, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_color_op_1, random_color_op_3}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomColorAdjust) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_color_adjust1 = vision::RandomColorAdjust({1.0}, {0.0}, {0.5}, {0.5}); - EXPECT_NE(random_color_adjust1, nullptr); - - std::shared_ptr random_color_adjust2 = - vision::RandomColorAdjust({1.0, 1.0}, {0.0, 0.0}, {0.5, 0.5}, {0.5, 0.5}); - EXPECT_NE(random_color_adjust2, nullptr); - - std::shared_ptr random_color_adjust3 = - vision::RandomColorAdjust({0.5, 1.0}, {0.0, 0.5}, {0.25, 0.5}, {0.25, 0.5}); - EXPECT_NE(random_color_adjust3, nullptr); - - std::shared_ptr random_color_adjust4 = vision::RandomColorAdjust(); - EXPECT_NE(random_color_adjust4, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_color_adjust1, random_color_adjust2, random_color_adjust3, random_color_adjust4}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomPosterizeFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterize with invalid params."; - - // Create objects for the tensor ops - // Invalid max > 8 - std::shared_ptr posterize = vision::RandomPosterize({1, 9}); - EXPECT_EQ(posterize, nullptr); - // Invalid min < 1 - posterize = vision::RandomPosterize({0, 8}); - EXPECT_EQ(posterize, nullptr); - // min > max - posterize = vision::RandomPosterize({8, 1}); - EXPECT_EQ(posterize, nullptr); - // empty - posterize = vision::RandomPosterize({}); - EXPECT_EQ(posterize, nullptr); -} - -TEST_F(MindDataTestPipeline, TestRandomPosterizeSuccess1) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterizeSuccess1 with non-default params."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr posterize = vision::RandomPosterize({1, 4}); - EXPECT_NE(posterize, nullptr); - - // Create a Map operation on ds - ds = ds->Map({posterize}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomPosterizeSuccess2) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterizeSuccess2 with default params."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr posterize = vision::RandomPosterize(); - EXPECT_NE(posterize, nullptr); - - // Create a Map operation on ds - ds = ds->Map({posterize}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomSharpness) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSharpness."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_sharpness_op_1 = vision::RandomSharpness({0.4, 2.3}); - EXPECT_NE(random_sharpness_op_1, nullptr); - - std::shared_ptr random_sharpness_op_2 = vision::RandomSharpness({}); - EXPECT_EQ(random_sharpness_op_2, nullptr); - - std::shared_ptr random_sharpness_op_3 = vision::RandomSharpness(); - EXPECT_NE(random_sharpness_op_3, nullptr); - - std::shared_ptr random_sharpness_op_4 = vision::RandomSharpness({0.1}); - EXPECT_EQ(random_sharpness_op_4, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_sharpness_op_1, random_sharpness_op_3}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomFlip) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_vertical_flip_op = vision::RandomVerticalFlip(0.5); - EXPECT_NE(random_vertical_flip_op, nullptr); - - std::shared_ptr random_horizontal_flip_op = vision::RandomHorizontalFlip(0.5); - EXPECT_NE(random_horizontal_flip_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_vertical_flip_op, random_horizontal_flip_op}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomRotation) { - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 2; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_rotation_op = vision::RandomRotation({-180, 180}); - EXPECT_NE(random_rotation_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_rotation_op}); - EXPECT_NE(ds, nullptr); - - // Create a Batch operation on ds - int32_t batch_size = 1; - ds = ds->Batch(batch_size); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestUniformAugWithOps) { - // Create a Mnist Dataset - std::string folder_path = datasets_root_path_ + "/testMnistData/"; - std::shared_ptr ds = Mnist(folder_path, "all", RandomSampler(false, 20)); - EXPECT_NE(ds, nullptr); - - // Create a Repeat operation on ds - int32_t repeat_num = 1; - ds = ds->Repeat(repeat_num); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr resize_op = vision::Resize({30, 30}); - EXPECT_NE(resize_op, nullptr); - - std::shared_ptr random_crop_op = vision::RandomCrop({28, 28}); - EXPECT_NE(random_crop_op, nullptr); - - std::shared_ptr center_crop_op = vision::CenterCrop({16, 16}); - EXPECT_NE(center_crop_op, nullptr); - - std::shared_ptr uniform_aug_op = vision::UniformAugment({random_crop_op, center_crop_op}, 2); - EXPECT_NE(uniform_aug_op, nullptr); - - // Create a Map operation on ds - ds = ds->Map({resize_op, uniform_aug_op}); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 20); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomSolarizeSucess1) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize."; - - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::vector threshold = {10, 100}; - std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); - EXPECT_NE(random_solarize, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_solarize}); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 10); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomSolarizeSucess2) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize with default params."; - // Create an ImageFolder Dataset - std::string folder_path = datasets_root_path_ + "/testPK/data/"; - std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); - EXPECT_NE(ds, nullptr); - - // Create objects for the tensor ops - std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(); - EXPECT_NE(random_solarize, nullptr); - - // Create a Map operation on ds - ds = ds->Map({random_solarize}); - 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 iter = ds->CreateIterator(); - EXPECT_NE(iter, nullptr); - - // Iterate the dataset and get each row - std::unordered_map> 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(); - iter->GetNextRow(&row); - } - - EXPECT_EQ(i, 10); - - // Manually terminate the pipeline - iter->Stop(); -} - -TEST_F(MindDataTestPipeline, TestRandomSolarizeFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize with invalid params."; - std::vector threshold = {13, 1}; - std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); - EXPECT_EQ(random_solarize, nullptr); - - threshold = {1, 2, 3}; - random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); - EXPECT_EQ(random_solarize, nullptr); - - threshold = {1}; - random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); - EXPECT_EQ(random_solarize, nullptr); - - threshold = {}; - random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); - EXPECT_EQ(random_solarize, nullptr); -} - -TEST_F(MindDataTestPipeline, TestResizeFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestResize with invalid params."; - // negative resize value - std::shared_ptr resize = mindspore::dataset::api::vision::Resize({30, -30}); - EXPECT_EQ(resize, nullptr); - // zero resize value - resize = mindspore::dataset::api::vision::Resize({0, 30}); - EXPECT_EQ(resize, nullptr); -} - -TEST_F(MindDataTestPipeline, TestCropFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCrop with invalid params."; - // wrong width - std::shared_ptr crop = mindspore::dataset::api::vision::Crop({0, 0}, {32, -32}); - EXPECT_EQ(crop, nullptr); - // wrong height - crop = mindspore::dataset::api::vision::Crop({0, 0}, {-32, -32}); - EXPECT_EQ(crop, nullptr); - // zero height - crop = mindspore::dataset::api::vision::Crop({0, 0}, {0, 32}); - EXPECT_EQ(crop, nullptr); -} - -TEST_F(MindDataTestPipeline, TestCenterCropFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCenterCrop with invalid params."; - // center crop height value negative - std::shared_ptr center_crop = mindspore::dataset::api::vision::CenterCrop({-32, 32}); - EXPECT_EQ(center_crop, nullptr); - // center crop width value negative - center_crop = mindspore::dataset::api::vision::CenterCrop({32, -32}); - EXPECT_EQ(center_crop, nullptr); - // 0 value would result in nullptr - center_crop = mindspore::dataset::api::vision::CenterCrop({0, 32}); - EXPECT_EQ(center_crop, nullptr); -} - -TEST_F(MindDataTestPipeline, TestNormalizeFail) { - MS_LOG(INFO) << "Doing MindDataTestPipeline-TestNormalize with invalid params."; - // mean value 0.0 - std::shared_ptr normalize = mindspore::dataset::api::vision::Normalize({0.0, 115.0, 100.0}, - {70.0, 68.0, 71.0}); - EXPECT_EQ(normalize, nullptr); - // std value at 0.0 - normalize = mindspore::dataset::api::vision::Normalize({121.0, 115.0, 100.0}, {0.0, 68.0, 71.0}); - EXPECT_EQ(normalize, nullptr); - // mean value 300.0 greater than 255.0 - normalize = mindspore::dataset::api::vision::Normalize({300.0, 115.0, 100.0}, {70.0, 68.0, 71.0}); - EXPECT_EQ(normalize, nullptr); -} diff --git a/tests/ut/cpp/dataset/c_api_vision_test.cc b/tests/ut/cpp/dataset/c_api_vision_test.cc new file mode 100644 index 0000000000..cdbe487cdc --- /dev/null +++ b/tests/ut/cpp/dataset/c_api_vision_test.cc @@ -0,0 +1,1315 @@ +/** + * Copyright 2020 Huawei Technologies Co., Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common/common.h" +#include "minddata/dataset/include/datasets.h" +#include "minddata/dataset/include/transforms.h" +#include "minddata/dataset/include/vision.h" + +using namespace mindspore::dataset::api; +using mindspore::dataset::BorderType; +using mindspore::dataset::Tensor; + +class MindDataTestPipeline : public UT::DatasetOpTesting { + protected: +}; + +TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess1) { + // Testing CutMixBatch on a batch of CHW images + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + int number_of_classes = 10; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr hwc_to_chw = vision::HWC2CHW(); + EXPECT_NE(hwc_to_chw, nullptr); + + // Create a Map operation on ds + ds = ds->Map({hwc_to_chw}, {"image"}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(number_of_classes); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr cutmix_batch_op = + vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNCHW, 1.0, 1.0); + EXPECT_NE(cutmix_batch_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({cutmix_batch_op}, {"image", "label"}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + uint64_t i = 0; + while (row.size() != 0) { + i++; + auto image = row["image"]; + auto label = row["label"]; + MS_LOG(INFO) << "Tensor image shape: " << image->shape(); + MS_LOG(INFO) << "Label shape: " << label->shape(); + EXPECT_EQ(image->shape().AsVector().size() == 4 && batch_size == image->shape()[0] && 3 == image->shape()[1] && + 32 == image->shape()[2] && 32 == image->shape()[3], + true); + EXPECT_EQ(label->shape().AsVector().size() == 2 && batch_size == label->shape()[0] && + number_of_classes == label->shape()[1], + true); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCutMixBatchSuccess2) { + // Calling CutMixBatch on a batch of HWC images with default values of alpha and prob + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + int number_of_classes = 10; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(number_of_classes); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr cutmix_batch_op = vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC); + EXPECT_NE(cutmix_batch_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({cutmix_batch_op}, {"image", "label"}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> row; + iter->GetNextRow(&row); + + uint64_t i = 0; + while (row.size() != 0) { + i++; + auto image = row["image"]; + auto label = row["label"]; + MS_LOG(INFO) << "Tensor image shape: " << image->shape(); + MS_LOG(INFO) << "Label shape: " << label->shape(); + EXPECT_EQ(image->shape().AsVector().size() == 4 && batch_size == image->shape()[0] && 32 == image->shape()[1] && + 32 == image->shape()[2] && 3 == image->shape()[3], + true); + EXPECT_EQ(label->shape().AsVector().size() == 2 && batch_size == label->shape()[0] && + number_of_classes == label->shape()[1], + true); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestCutMixBatchFail1) { + // Must fail because alpha can't be negative + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr cutmix_batch_op = + vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, -1, 0.5); + EXPECT_EQ(cutmix_batch_op, nullptr); +} + +TEST_F(MindDataTestPipeline, TestCutMixBatchFail2) { + // Must fail because prob can't be negative + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr cutmix_batch_op = + vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, 1, -0.5); + EXPECT_EQ(cutmix_batch_op, nullptr); +} + +TEST_F(MindDataTestPipeline, TestCutMixBatchFail3) { + // Must fail because alpha can't be zero + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr cutmix_batch_op = + vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNHWC, 0.0, 0.5); + EXPECT_EQ(cutmix_batch_op, nullptr); +} + +TEST_F(MindDataTestPipeline, TestCutOut) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr cut_out1 = vision::CutOut(30, 5); + EXPECT_NE(cut_out1, nullptr); + + std::shared_ptr cut_out2 = vision::CutOut(30); + EXPECT_NE(cut_out2, nullptr); + + // Create a Map operation on ds + ds = ds->Map({cut_out1, cut_out2}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestDecode) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, false, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr decode = vision::Decode(true); + EXPECT_NE(decode, nullptr); + + // Create a Map operation on ds + ds = ds->Map({decode}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestHwcToChw) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr channel_swap = vision::HWC2CHW(); + EXPECT_NE(channel_swap, nullptr); + + // Create a Map operation on ds + ds = ds->Map({channel_swap}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + // check if the image is in NCHW + EXPECT_EQ(batch_size == image->shape()[0] && 3 == image->shape()[1] && 2268 == image->shape()[2] && + 4032 == image->shape()[3], + true); + iter->GetNextRow(&row); + } + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestMixUpBatchFail1) { + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr mixup_batch_op = vision::MixUpBatch(-1); + EXPECT_EQ(mixup_batch_op, nullptr); +} + +TEST_F(MindDataTestPipeline, TestMixUpBatchFail2) { + // This should fail because alpha can't be zero + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr mixup_batch_op = vision::MixUpBatch(0.0); + EXPECT_EQ(mixup_batch_op, nullptr); +} + +TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess1) { + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr mixup_batch_op = vision::MixUpBatch(2.0); + EXPECT_NE(mixup_batch_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({mixup_batch_op}, {"image", "label"}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestMixUpBatchSuccess2) { + // Create a Cifar10 Dataset + std::string folder_path = datasets_root_path_ + "/testCifar10Data/"; + std::shared_ptr ds = Cifar10(folder_path, "all", RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 5; + ds = ds->Batch(batch_size); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr one_hot_op = transforms::OneHot(10); + EXPECT_NE(one_hot_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({one_hot_op}, {"label"}); + EXPECT_NE(ds, nullptr); + + std::shared_ptr mixup_batch_op = vision::MixUpBatch(); + EXPECT_NE(mixup_batch_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({mixup_batch_op}, {"image", "label"}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 2); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestNormalize) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr normalize = vision::Normalize({121.0, 115.0, 100.0}, {70.0, 68.0, 71.0}); + EXPECT_NE(normalize, nullptr); + + // Create a Map operation on ds + ds = ds->Map({normalize}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestPad) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr pad_op1 = vision::Pad({1, 2, 3, 4}, {0}, BorderType::kSymmetric); + EXPECT_NE(pad_op1, nullptr); + + std::shared_ptr pad_op2 = vision::Pad({1}, {1, 1, 1}, BorderType::kEdge); + EXPECT_NE(pad_op2, nullptr); + + std::shared_ptr pad_op3 = vision::Pad({1, 4}); + EXPECT_NE(pad_op3, nullptr); + + // Create a Map operation on ds + ds = ds->Map({pad_op1, pad_op2, pad_op3}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomAffineFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineFail with invalid params."; + + // Create objects for the tensor ops + std::shared_ptr affine = vision::RandomAffine({0.0, 0.0}, {}); + EXPECT_EQ(affine, nullptr); + // Invalid number of values for translate + affine = vision::RandomAffine({0.0, 0.0}, {1, 1, 1, 1, 1}); + EXPECT_EQ(affine, nullptr); + // Invalid number of values for shear + affine = vision::RandomAffine({30.0, 30.0}, {0.0, 0.0}, {2.0, 2.0}, {10.0}); + EXPECT_EQ(affine, nullptr); +} + +TEST_F(MindDataTestPipeline, TestRandomAffineSuccess1) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineSuccess1 with non-default params."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr affine = + 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); + + // Create a Map operation on ds + ds = ds->Map({affine}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomAffineSuccess2) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomAffineSuccess2 with default params."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr affine = vision::RandomAffine({0.0, 0.0}); + EXPECT_NE(affine, nullptr); + + // Create a Map operation on ds + ds = ds->Map({affine}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomColor) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomColor with non-default params."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_color_op_1 = vision::RandomColor(0.0, 0.0); + EXPECT_NE(random_color_op_1, nullptr); + + std::shared_ptr random_color_op_2 = vision::RandomColor(1.0, 0.1); + EXPECT_EQ(random_color_op_2, nullptr); + + std::shared_ptr random_color_op_3 = vision::RandomColor(0.0, 1.1); + EXPECT_NE(random_color_op_3, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_color_op_1, random_color_op_3}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomColorAdjust) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_color_adjust1 = vision::RandomColorAdjust({1.0}, {0.0}, {0.5}, {0.5}); + EXPECT_NE(random_color_adjust1, nullptr); + + std::shared_ptr random_color_adjust2 = + vision::RandomColorAdjust({1.0, 1.0}, {0.0, 0.0}, {0.5, 0.5}, {0.5, 0.5}); + EXPECT_NE(random_color_adjust2, nullptr); + + std::shared_ptr random_color_adjust3 = + vision::RandomColorAdjust({0.5, 1.0}, {0.0, 0.5}, {0.25, 0.5}, {0.25, 0.5}); + EXPECT_NE(random_color_adjust3, nullptr); + + std::shared_ptr random_color_adjust4 = vision::RandomColorAdjust(); + EXPECT_NE(random_color_adjust4, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_color_adjust1, random_color_adjust2, random_color_adjust3, random_color_adjust4}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomPosterizeFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterize with invalid params."; + + // Create objects for the tensor ops + // Invalid max > 8 + std::shared_ptr posterize = vision::RandomPosterize({1, 9}); + EXPECT_EQ(posterize, nullptr); + // Invalid min < 1 + posterize = vision::RandomPosterize({0, 8}); + EXPECT_EQ(posterize, nullptr); + // min > max + posterize = vision::RandomPosterize({8, 1}); + EXPECT_EQ(posterize, nullptr); + // empty + posterize = vision::RandomPosterize({}); + EXPECT_EQ(posterize, nullptr); +} + +TEST_F(MindDataTestPipeline, TestRandomPosterizeSuccess1) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterizeSuccess1 with non-default params."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr posterize = vision::RandomPosterize({1, 4}); + EXPECT_NE(posterize, nullptr); + + // Create a Map operation on ds + ds = ds->Map({posterize}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomPosterizeSuccess2) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomPosterizeSuccess2 with default params."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr posterize = vision::RandomPosterize(); + EXPECT_NE(posterize, nullptr); + + // Create a Map operation on ds + ds = ds->Map({posterize}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomSharpness) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSharpness."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_sharpness_op_1 = vision::RandomSharpness({0.4, 2.3}); + EXPECT_NE(random_sharpness_op_1, nullptr); + + std::shared_ptr random_sharpness_op_2 = vision::RandomSharpness({}); + EXPECT_EQ(random_sharpness_op_2, nullptr); + + std::shared_ptr random_sharpness_op_3 = vision::RandomSharpness(); + EXPECT_NE(random_sharpness_op_3, nullptr); + + std::shared_ptr random_sharpness_op_4 = vision::RandomSharpness({0.1}); + EXPECT_EQ(random_sharpness_op_4, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_sharpness_op_1, random_sharpness_op_3}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomFlip) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_vertical_flip_op = vision::RandomVerticalFlip(0.5); + EXPECT_NE(random_vertical_flip_op, nullptr); + + std::shared_ptr random_horizontal_flip_op = vision::RandomHorizontalFlip(0.5); + EXPECT_NE(random_horizontal_flip_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_vertical_flip_op, random_horizontal_flip_op}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomRotation) { + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 2; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_rotation_op = vision::RandomRotation({-180, 180}); + EXPECT_NE(random_rotation_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_rotation_op}); + EXPECT_NE(ds, nullptr); + + // Create a Batch operation on ds + int32_t batch_size = 1; + ds = ds->Batch(batch_size); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestUniformAugWithOps) { + // Create a Mnist Dataset + std::string folder_path = datasets_root_path_ + "/testMnistData/"; + std::shared_ptr ds = Mnist(folder_path, "all", RandomSampler(false, 20)); + EXPECT_NE(ds, nullptr); + + // Create a Repeat operation on ds + int32_t repeat_num = 1; + ds = ds->Repeat(repeat_num); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr resize_op = vision::Resize({30, 30}); + EXPECT_NE(resize_op, nullptr); + + std::shared_ptr random_crop_op = vision::RandomCrop({28, 28}); + EXPECT_NE(random_crop_op, nullptr); + + std::shared_ptr center_crop_op = vision::CenterCrop({16, 16}); + EXPECT_NE(center_crop_op, nullptr); + + std::shared_ptr uniform_aug_op = vision::UniformAugment({random_crop_op, center_crop_op}, 2); + EXPECT_NE(uniform_aug_op, nullptr); + + // Create a Map operation on ds + ds = ds->Map({resize_op, uniform_aug_op}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 20); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomSolarizeSucess1) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize."; + + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::vector threshold = {10, 100}; + std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); + EXPECT_NE(random_solarize, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_solarize}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 10); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomSolarizeSucess2) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize with default params."; + // Create an ImageFolder Dataset + std::string folder_path = datasets_root_path_ + "/testPK/data/"; + std::shared_ptr ds = ImageFolder(folder_path, true, RandomSampler(false, 10)); + EXPECT_NE(ds, nullptr); + + // Create objects for the tensor ops + std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(); + EXPECT_NE(random_solarize, nullptr); + + // Create a Map operation on ds + ds = ds->Map({random_solarize}); + 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 iter = ds->CreateIterator(); + EXPECT_NE(iter, nullptr); + + // Iterate the dataset and get each row + std::unordered_map> 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(); + iter->GetNextRow(&row); + } + + EXPECT_EQ(i, 10); + + // Manually terminate the pipeline + iter->Stop(); +} + +TEST_F(MindDataTestPipeline, TestRandomSolarizeFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSolarize with invalid params."; + std::vector threshold = {13, 1}; + std::shared_ptr random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); + EXPECT_EQ(random_solarize, nullptr); + + threshold = {1, 2, 3}; + random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); + EXPECT_EQ(random_solarize, nullptr); + + threshold = {1}; + random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); + EXPECT_EQ(random_solarize, nullptr); + + threshold = {}; + random_solarize = mindspore::dataset::api::vision::RandomSolarize(threshold); + EXPECT_EQ(random_solarize, nullptr); +} + +TEST_F(MindDataTestPipeline, TestResizeFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestResize with invalid params."; + // negative resize value + std::shared_ptr resize = mindspore::dataset::api::vision::Resize({30, -30}); + EXPECT_EQ(resize, nullptr); + // zero resize value + resize = mindspore::dataset::api::vision::Resize({0, 30}); + EXPECT_EQ(resize, nullptr); +} + +TEST_F(MindDataTestPipeline, TestCropFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCrop with invalid params."; + // wrong width + std::shared_ptr crop = mindspore::dataset::api::vision::Crop({0, 0}, {32, -32}); + EXPECT_EQ(crop, nullptr); + // wrong height + crop = mindspore::dataset::api::vision::Crop({0, 0}, {-32, -32}); + EXPECT_EQ(crop, nullptr); + // zero height + crop = mindspore::dataset::api::vision::Crop({0, 0}, {0, 32}); + EXPECT_EQ(crop, nullptr); +} + +TEST_F(MindDataTestPipeline, TestCenterCropFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCenterCrop with invalid params."; + // center crop height value negative + std::shared_ptr center_crop = mindspore::dataset::api::vision::CenterCrop({-32, 32}); + EXPECT_EQ(center_crop, nullptr); + // center crop width value negative + center_crop = mindspore::dataset::api::vision::CenterCrop({32, -32}); + EXPECT_EQ(center_crop, nullptr); + // 0 value would result in nullptr + center_crop = mindspore::dataset::api::vision::CenterCrop({0, 32}); + EXPECT_EQ(center_crop, nullptr); +} + +TEST_F(MindDataTestPipeline, TestNormalizeFail) { + MS_LOG(INFO) << "Doing MindDataTestPipeline-TestNormalize with invalid params."; + // mean value 0.0 + std::shared_ptr normalize = mindspore::dataset::api::vision::Normalize({0.0, 115.0, 100.0}, + {70.0, 68.0, 71.0}); + EXPECT_EQ(normalize, nullptr); + // std value at 0.0 + normalize = mindspore::dataset::api::vision::Normalize({121.0, 115.0, 100.0}, {0.0, 68.0, 71.0}); + EXPECT_EQ(normalize, nullptr); + // mean value 300.0 greater than 255.0 + normalize = mindspore::dataset::api::vision::Normalize({300.0, 115.0, 100.0}, {70.0, 68.0, 71.0}); + EXPECT_EQ(normalize, nullptr); +} diff --git a/tests/ut/cpp/dataset/center_crop_op_test.cc b/tests/ut/cpp/dataset/center_crop_op_test.cc index 20e2be3991..92f069d475 100644 --- a/tests/ut/cpp/dataset/center_crop_op_test.cc +++ b/tests/ut/cpp/dataset/center_crop_op_test.cc @@ -55,3 +55,17 @@ TEST_F(MindDataTestCenterCropOp, TestOp2) { EXPECT_TRUE(s.IsError()); ASSERT_TRUE(s.get_code() == StatusCode::kUnexpectedError); } + +TEST_F(MindDataTestCenterCropOp, TestOp3) { + MS_LOG(INFO) << "Doing MindDataTestCenterCropOp::TestOp3. Test single integer input for square crop."; + std::shared_ptr output_tensor; + int side = 128; + std::unique_ptr op(new CenterCropOp(side)); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor); + EXPECT_TRUE(s.IsOk()); + // Confirm both height and width are of size . + EXPECT_EQ(side, output_tensor->shape()[0]); + EXPECT_EQ(side, output_tensor->shape()[1]); + std::shared_ptr p = CVTensor::AsCVTensor(output_tensor); +}