Add transforms API

This commit is contained in:
shenwei41 2020-10-26 19:16:21 +08:00
parent f655e3fadf
commit 779f0f387b
3 changed files with 1008 additions and 101 deletions

View File

@ -21,6 +21,7 @@
#endif
// Kernel image headers (in alphabetical order)
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/auto_contrast_op.h"
#include "minddata/dataset/kernels/image/center_crop_op.h"
#endif
#include "minddata/dataset/kernels/image/crop_op.h"
@ -31,6 +32,7 @@
#include "minddata/dataset/kernels/image/decode_op.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/hwc_to_chw_op.h"
#include "minddata/dataset/kernels/image/invert_op.h"
#include "minddata/dataset/kernels/image/mixup_batch_op.h"
#endif
#include "minddata/dataset/kernels/image/normalize_op.h"
@ -42,12 +44,15 @@
#include "minddata/dataset/kernels/image/random_crop_and_resize_op.h"
#include "minddata/dataset/kernels/image/random_crop_op.h"
#include "minddata/dataset/kernels/image/random_crop_decode_resize_op.h"
#include "minddata/dataset/kernels/image/random_crop_with_bbox_op.h"
#include "minddata/dataset/kernels/image/random_horizontal_flip_op.h"
#include "minddata/dataset/kernels/image/random_horizontal_flip_with_bbox_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/random_vertical_flip_with_bbox_op.h"
#include "minddata/dataset/kernels/image/rescale_op.h"
#endif
#include "minddata/dataset/kernels/image/resize_op.h"
@ -68,6 +73,16 @@ namespace vision {
// FUNCTIONS TO CREATE VISION TRANSFORM OPERATIONS
// (In alphabetical order)
// Function to create AutoContrastOperation.
std::shared_ptr<AutoContrastOperation> AutoContrast(float cutoff, std::vector<uint32_t> ignore) {
auto op = std::make_shared<AutoContrastOperation>(cutoff, ignore);
// Input validation
if (!op->ValidateParams()) {
return nullptr;
}
return op;
}
// Function to create CenterCropOperation.
std::shared_ptr<CenterCropOperation> CenterCrop(std::vector<int32_t> size) {
auto op = std::make_shared<CenterCropOperation>(size);
@ -129,6 +144,16 @@ std::shared_ptr<HwcToChwOperation> HWC2CHW() {
return op;
}
// Function to create InvertOperation.
std::shared_ptr<InvertOperation> Invert() {
auto op = std::make_shared<InvertOperation>();
// Input validation
if (!op->ValidateParams()) {
return nullptr;
}
return op;
}
// Function to create MixUpBatchOperation.
std::shared_ptr<MixUpBatchOperation> MixUpBatch(float alpha) {
auto op = std::make_shared<MixUpBatchOperation>(alpha);
@ -229,6 +254,18 @@ std::shared_ptr<RandomCropDecodeResizeOperation> RandomCropDecodeResize(std::vec
return op;
}
// Function to create RandomCropWithBBoxOperation.
std::shared_ptr<RandomCropWithBBoxOperation> RandomCropWithBBox(std::vector<int32_t> size, std::vector<int32_t> padding,
bool pad_if_needed, std::vector<uint8_t> fill_value,
BorderType padding_mode) {
auto op = std::make_shared<RandomCropWithBBoxOperation>(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<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob) {
auto op = std::make_shared<RandomHorizontalFlipOperation>(prob);
@ -239,6 +276,16 @@ std::shared_ptr<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob)
return op;
}
// Function to create RandomHorizontalFlipOperation.
std::shared_ptr<RandomHorizontalFlipWithBBoxOperation> RandomHorizontalFlipWithBBox(float prob) {
auto op = std::make_shared<RandomHorizontalFlipWithBBoxOperation>(prob);
// Input validation
if (!op->ValidateParams()) {
return nullptr;
}
return op;
}
// Function to create RandomPosterizeOperation.
std::shared_ptr<RandomPosterizeOperation> RandomPosterize(const std::vector<uint8_t> &bit_range) {
auto op = std::make_shared<RandomPosterizeOperation>(bit_range);
@ -303,6 +350,16 @@ std::shared_ptr<RandomVerticalFlipOperation> RandomVerticalFlip(float prob) {
return op;
}
// Function to create RandomVerticalFlipWithBBoxOperation.
std::shared_ptr<RandomVerticalFlipWithBBoxOperation> RandomVerticalFlipWithBBox(float prob) {
auto op = std::make_shared<RandomVerticalFlipWithBBoxOperation>(prob);
// Input validation
if (!op->ValidateParams()) {
return nullptr;
}
return op;
}
// Function to create RescaleOperation.
std::shared_ptr<RescaleOperation> Rescale(float rescale, float shift) {
auto op = std::make_shared<RescaleOperation>(rescale, shift);
@ -368,6 +425,60 @@ std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<
#endif
/* ####################################### Validator Functions ############################################ */
Status ValidateVectorFillvalue(const std::string &dataset_name, const std::vector<uint8_t> &fill_value) {
if (fill_value.empty() || (fill_value.size() != 1 && fill_value.size() != 3)) {
std::string err_msg = dataset_name + ": fill_value vector has incorrect size: " + std::to_string(fill_value.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (uint8_t single_fill_value : fill_value) {
if (single_fill_value > 255) {
std::string err_msg =
dataset_name + ": fill_value has to be between 0 and 255, got:" + std::to_string(single_fill_value);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
return Status::OK();
}
Status ValidateVectorProbability(const std::string &dataset_name, const float &probability) {
if (probability < 0.0 || probability > 1.0) {
std::string err_msg =
dataset_name + ": probability must be between 0.0 and 1.0, got: " + std::to_string(probability);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
return Status::OK();
}
Status ValidateVectorPadding(const std::string &dataset_name, const std::vector<int32_t> &padding) {
if (padding.empty() || padding.size() == 3 || padding.size() > 4) {
std::string err_msg = dataset_name + ": padding vector has incorrect size: " + std::to_string(padding.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < padding.size(); ++i) {
if (padding[i] < 0) {
std::string err_msg =
dataset_name +
": invalid padding, padding value must be greater than or equal to 0, got: " + std::to_string(padding[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (padding[i] == INT_MAX) {
std::string err_msg =
dataset_name + ": invalid padding, padding value too large, got: " + std::to_string(padding[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
return Status::OK();
}
Status ValidateVectorPositive(const std::string &dataset_name, const std::vector<int32_t> &size) {
for (int32_t i = 0; i < size.size(); ++i) {
if (size[i] <= 0) {
@ -387,6 +498,34 @@ bool CmpFloat(const float &a, const float &b, float epsilon = 0.0000000001f) { r
// (In alphabetical order)
#ifndef ENABLE_ANDROID
// AutoContrastOperation
AutoContrastOperation::AutoContrastOperation(float cutoff, std::vector<uint32_t> ignore)
: cutoff_(cutoff), ignore_(ignore) {}
Status AutoContrastOperation::ValidateParams() {
if (cutoff_ < 0 || cutoff_ > 100) {
std::string err_msg = "AutoContrast: cutoff has to be between 0 and 100, got: " + std::to_string(cutoff_);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (uint32_t single_ignore : ignore_) {
if (single_ignore > 255) {
std::string err_msg =
"AutoContrast: invalid size, ignore has to be between 0 and 255, got: " + std::to_string(single_ignore);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
return Status::OK();
}
std::shared_ptr<TensorOp> AutoContrastOperation::Build() {
std::shared_ptr<AutoContrastOp> tensor_op = std::make_shared<AutoContrastOp>(cutoff_, ignore_);
return tensor_op;
}
// CenterCropOperation
CenterCropOperation::CenterCropOperation(std::vector<int32_t> size) : size_(size) {}
@ -542,6 +681,11 @@ Status HwcToChwOperation::ValidateParams() { return Status::OK(); }
std::shared_ptr<TensorOp> HwcToChwOperation::Build() { return std::make_shared<HwcToChwOp>(); }
// InvertOperation
Status InvertOperation::ValidateParams() { return Status::OK(); }
std::shared_ptr<TensorOp> InvertOperation::Build() { return std::make_shared<InvertOp>(); }
// MixUpOperation
MixUpBatchOperation::MixUpBatchOperation(float alpha) : alpha_(alpha) {}
@ -598,37 +742,9 @@ PadOperation::PadOperation(std::vector<int32_t> padding, std::vector<uint8_t> fi
Status PadOperation::ValidateParams() {
// padding
if (padding_.empty() || padding_.size() == 3 || padding_.size() > 4) {
std::string err_msg = "Pad: padding vector has incorrect size: " + std::to_string(padding_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < padding_.size(); ++i) {
if (padding_[i] < 0) {
std::string err_msg =
"Pad: invalid padding, padding value must be greater than or equal to 0, got: " + std::to_string(padding_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (padding_[i] == INT_MAX) {
std::string err_msg = "Pad: invalid padding, padding value too large, got: " + std::to_string(padding_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
RETURN_IF_NOT_OK(ValidateVectorPadding("Pad", padding_));
// fill_value
if (fill_value_.empty() || (fill_value_.size() != 1 && fill_value_.size() != 3)) {
std::string err_msg = "Pad: fill_value vector has incorrect size: " + std::to_string(fill_value_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < fill_value_.size(); ++i) {
if (fill_value_[i] < 0 || fill_value_[i] > 255) {
std::string err_msg = "Pad: fill_value has to be between 0 and 255, got:" + std::to_string(fill_value_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
RETURN_IF_NOT_OK(ValidateVectorFillvalue("Pad", fill_value_));
return Status::OK();
}
@ -975,37 +1091,9 @@ Status RandomCropOperation::ValidateParams() {
}
RETURN_IF_NOT_OK(ValidateVectorPositive("RandomCrop", size_));
// padding
if (padding_.empty() || padding_.size() != 4) {
std::string err_msg = "RandomCrop: padding vector has incorrect size: " + std::to_string(padding_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < padding_.size(); ++i) {
if (padding_[i] < 0) {
std::string err_msg = "RandomCrop: invalid padding, padding value must be greater than or equal to 0, got: " +
std::to_string(padding_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (padding_[i] == INT_MAX) {
std::string err_msg = "RandomCrop: invalid padding, padding value too large, got: " + std::to_string(padding_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
RETURN_IF_NOT_OK(ValidateVectorPadding("RandomCrop", padding_));
// fill_value
if (fill_value_.empty() || fill_value_.size() != 3) {
std::string err_msg = "RandomCrop: fill_value vector has incorrect size: " + std::to_string(fill_value_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < fill_value_.size(); ++i) {
if (fill_value_[i] < 0 || fill_value_[i] > 255) {
std::string err_msg = "RandomCrop: fill_value has to be between 0 and 255, got:" + std::to_string(fill_value_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
RETURN_IF_NOT_OK(ValidateVectorFillvalue("RandomCrop", fill_value_));
return Status::OK();
}
@ -1018,14 +1106,37 @@ std::shared_ptr<TensorOp> RandomCropOperation::Build() {
crop_width = size_[1];
}
int32_t pad_top = padding_[0];
int32_t pad_bottom = padding_[1];
int32_t pad_left = padding_[2];
int32_t pad_right = padding_[3];
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_value_[0];
uint8_t fill_g = fill_value_[1];
uint8_t fill_b = fill_value_[2];
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];
}
auto tensor_op = std::make_shared<RandomCropOp>(crop_height, crop_width, pad_top, pad_bottom, pad_left, pad_right,
padding_mode_, pad_if_needed_, fill_r, fill_g, fill_b);
@ -1125,15 +1236,83 @@ std::shared_ptr<TensorOp> RandomCropDecodeResizeOperation::Build() {
return tensor_op;
}
// RandomCropWithBBoxOperation
RandomCropWithBBoxOperation::RandomCropWithBBoxOperation(std::vector<int32_t> size, std::vector<int32_t> padding,
bool pad_if_needed, std::vector<uint8_t> fill_value,
BorderType padding_mode)
: size_(size),
padding_(padding),
pad_if_needed_(pad_if_needed),
fill_value_(fill_value),
padding_mode_(padding_mode) {}
Status RandomCropWithBBoxOperation::ValidateParams() {
// size
if (size_.empty() || size_.size() > 2) {
std::string err_msg = "RandomCropWithBBox: size must be a vector of one or two values";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
RETURN_IF_NOT_OK(ValidateVectorPositive("RandomCropWithBBox", size_));
// padding
RETURN_IF_NOT_OK(ValidateVectorPadding("RandomCropWithBBox", padding_));
// fill_value
RETURN_IF_NOT_OK(ValidateVectorFillvalue("RandomCropWithBBox", fill_value_));
return Status::OK();
}
std::shared_ptr<TensorOp> RandomCropWithBBoxOperation::Build() {
int32_t crop_height = size_[0];
int32_t crop_width = size_[0];
// User has specified the crop_width value.
if (size_.size() == 2) {
crop_width = size_[1];
}
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];
}
auto tensor_op =
std::make_shared<RandomCropWithBBoxOp>(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) {}
Status RandomHorizontalFlipOperation::ValidateParams() {
if (probability_ < 0.0 || probability_ > 1.0) {
std::string err_msg = "RandomHorizontalFlip: probability must be between 0.0 and 1.0.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
RETURN_IF_NOT_OK(ValidateVectorProbability("RandomHorizontalFlip", probability_));
return Status::OK();
}
@ -1143,6 +1322,22 @@ std::shared_ptr<TensorOp> RandomHorizontalFlipOperation::Build() {
return tensor_op;
}
// RandomHorizontalFlipWithBBoxOperation
RandomHorizontalFlipWithBBoxOperation::RandomHorizontalFlipWithBBoxOperation(float probability)
: probability_(probability) {}
Status RandomHorizontalFlipWithBBoxOperation::ValidateParams() {
RETURN_IF_NOT_OK(ValidateVectorProbability("RandomHorizontalFlipWithBBox", probability_));
return Status::OK();
}
std::shared_ptr<TensorOp> RandomHorizontalFlipWithBBoxOperation::Build() {
std::shared_ptr<RandomHorizontalFlipWithBBoxOp> tensor_op =
std::make_shared<RandomHorizontalFlipWithBBoxOp>(probability_);
return tensor_op;
}
// RandomPosterizeOperation
RandomPosterizeOperation::RandomPosterizeOperation(const std::vector<uint8_t> &bit_range) : bit_range_(bit_range) {}
@ -1253,16 +1448,21 @@ RandomRotationOperation::RandomRotationOperation(std::vector<float> degrees, Int
Status RandomRotationOperation::ValidateParams() {
// degrees
if (degrees_.size() != 2) {
if (degrees_.size() != 2 && degrees_.size() != 1) {
std::string err_msg =
"RandomRotation: degrees must be a vector of two values, got: " + std::to_string(degrees_.size());
MS_LOG(ERROR) << "RandomRotation: degrees must be a vector of two values, got: " << degrees_;
"RandomRotation: degrees must be a vector of one or two values, got: " + std::to_string(degrees_.size());
MS_LOG(ERROR) << "RandomRotation: degrees must be a vector of one or two values, got: " << degrees_;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (degrees_[1] < degrees_[0]) {
if ((degrees_[1] < degrees_[0]) && (degrees_.size() == 2)) {
std::string err_msg = "RandomRotation: degrees must be in the format of (min, max).";
MS_LOG(ERROR) << "RandomRotation: degrees must be in the format of (min, max), got: " << degrees_;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
} else if ((degrees_[0] <= 0) && degrees_.size() == 1) {
std::string err_msg = "RandomRotation: if the degress has one element, the value must be greater than 0.";
MS_LOG(ERROR) << "RandomRotation: if the degress has one element, the value must be greater than 0, got: "
<< degrees_;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
// center
if (center_.empty() || center_.size() != 2) {
@ -1272,27 +1472,33 @@ Status RandomRotationOperation::ValidateParams() {
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
// fill_value
if (fill_value_.empty() || fill_value_.size() != 3) {
std::string err_msg =
"RandomRotation: fill_value must be a vector of two values, got: " + std::to_string(fill_value_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
for (int32_t i = 0; i < fill_value_.size(); ++i) {
if (fill_value_[i] < 0 || fill_value_[i] > 255) {
std::string err_msg =
"RandomRotation: fill_value has to be between 0 and 255, got: " + std::to_string(fill_value_[i]);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
RETURN_IF_NOT_OK(ValidateVectorFillvalue("RandomRotation", fill_value_));
return Status::OK();
}
std::shared_ptr<TensorOp> RandomRotationOperation::Build() {
std::shared_ptr<RandomRotationOp> tensor_op =
std::make_shared<RandomRotationOp>(degrees_[0], degrees_[1], center_[0], center_[1], interpolation_mode_, expand_,
fill_value_[0], fill_value_[1], fill_value_[2]);
float start_degree, end_degree;
if (degrees_.size() == 1) {
start_degree = -degrees_[0];
end_degree = degrees_[0];
} else if (degrees_.size() == 2) {
start_degree = degrees_[0];
end_degree = degrees_[1];
}
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<RandomRotationOp> tensor_op = std::make_shared<RandomRotationOp>(
start_degree, end_degree, center_[0], center_[1], interpolation_mode_, expand_, fill_r, fill_g, fill_b);
return tensor_op;
}
@ -1355,11 +1561,7 @@ std::shared_ptr<TensorOp> RandomSolarizeOperation::Build() {
RandomVerticalFlipOperation::RandomVerticalFlipOperation(float probability) : probability_(probability) {}
Status RandomVerticalFlipOperation::ValidateParams() {
if (probability_ < 0.0 || probability_ > 1.0) {
std::string err_msg = "RandomVerticalFlip: probability must be between 0.0 and 1.0.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
RETURN_IF_NOT_OK(ValidateVectorProbability("RandomVerticalFlip", probability_));
return Status::OK();
}
@ -1369,6 +1571,22 @@ std::shared_ptr<TensorOp> RandomVerticalFlipOperation::Build() {
return tensor_op;
}
// RandomVerticalFlipWithBBoxOperation
RandomVerticalFlipWithBBoxOperation::RandomVerticalFlipWithBBoxOperation(float probability)
: probability_(probability) {}
Status RandomVerticalFlipWithBBoxOperation::ValidateParams() {
RETURN_IF_NOT_OK(ValidateVectorProbability("RandomVerticalFlipWithBBox", probability_));
return Status::OK();
}
std::shared_ptr<TensorOp> RandomVerticalFlipWithBBoxOperation::Build() {
std::shared_ptr<RandomVerticalFlipWithBBoxOp> tensor_op =
std::make_shared<RandomVerticalFlipWithBBoxOp>(probability_);
return tensor_op;
}
// RescaleOperation
RescaleOperation::RescaleOperation(float rescale, float shift) : rescale_(rescale), shift_(shift) {}

View File

@ -32,6 +32,7 @@ namespace vision {
// Transform Op classes (in alphabetical order)
#ifndef ENABLE_ANDROID
class AutoContrastOperation;
class CenterCropOperation;
#endif
class CropOperation;
@ -42,6 +43,7 @@ class CutOutOperation;
class DecodeOperation;
#ifndef ENABLE_ANDROID
class HwcToChwOperation;
class InvertOperation;
class MixUpBatchOperation;
#endif
class NormalizeOperation;
@ -52,13 +54,16 @@ class RandomColorOperation;
class RandomColorAdjustOperation;
class RandomCropOperation;
class RandomCropDecodeResizeOperation;
class RandomCropWithBBoxOperation;
class RandomHorizontalFlipOperation;
class RandomHorizontalFlipWithBBoxOperation;
class RandomPosterizeOperation;
class RandomResizedCropOperation;
class RandomRotationOperation;
class RandomSharpnessOperation;
class RandomSolarizeOperation;
class RandomVerticalFlipOperation;
class RandomVerticalFlipWithBBoxOperation;
class RescaleOperation;
#endif
class ResizeOperation;
@ -68,6 +73,13 @@ class RgbaToRgbOperation;
class SwapRedBlueOperation;
class UniformAugOperation;
/// \brief Function to create a AutoContrast TensorOperation.
/// \notes Apply automatic contrast on input image.
/// \param[in] cutoff Percent of pixels to cut off from the histogram, the valid range of cutoff value is 0 to 100.
/// \param[in] ignore Pixel values to ignore.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<AutoContrastOperation> AutoContrast(float cutoff = 0.0, std::vector<uint32_t> ignore = {});
/// \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.
@ -113,6 +125,11 @@ std::shared_ptr<DecodeOperation> Decode(bool rgb = true);
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<HwcToChwOperation> HWC2CHW();
/// \brief Function to create a Invert TensorOperation.
/// \notes Apply invert on input image in RGB mode.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<InvertOperation> Invert();
/// \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.
@ -232,12 +249,38 @@ std::shared_ptr<RandomCropDecodeResizeOperation> RandomCropDecodeResize(
std::vector<int32_t> size, std::vector<float> scale = {0.08, 1.0}, std::vector<float> ratio = {3. / 4, 4. / 3},
InterpolationMode interpolation = InterpolationMode::kLinear, int32_t max_attempts = 10);
/// \brief Function to create a RandomCropWithBBox TensorOperation.
/// \Crop the input image at a random location and adjust bounding boxes accordingly.
/// \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.
/// \param[in] padding_mode The method of padding (default=BorderType::kConstant).It can be any of
/// [BorderType::kConstant, BorderType::kEdge, BorderType::kReflect, BorderType::kSymmetric].
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RandomCropWithBBoxOperation> RandomCropWithBBox(std::vector<int32_t> size,
std::vector<int32_t> padding = {0, 0, 0, 0},
bool pad_if_needed = false,
std::vector<uint8_t> 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 A float representing the probability of flip.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RandomHorizontalFlipOperation> RandomHorizontalFlip(float prob = 0.5);
/// \brief Function to create a RandomHorizontalFlipWithBBox TensorOperation.
/// \notes Flip the input image horizontally, randomly with a given probability and adjust bounding boxes accordingly.
/// \param[in] prob A float representing the probability of flip.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RandomHorizontalFlipWithBBoxOperation> RandomHorizontalFlipWithBBox(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})
@ -293,6 +336,12 @@ std::shared_ptr<RandomSolarizeOperation> RandomSolarize(std::vector<uint8_t> thr
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RandomVerticalFlipOperation> RandomVerticalFlip(float prob = 0.5);
/// \brief Function to create a RandomVerticalFlipWithBBox TensorOperation.
/// \notes Flip the input image vertically, randomly with a given probability and adjust bounding boxes accordingly.
/// \param[in] prob A float representing the probability of flip.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RandomVerticalFlipWithBBoxOperation> RandomVerticalFlipWithBBox(float prob = 0.5);
/// \brief Function to create a RescaleOperation TensorOperation.
/// \notes Tensor operation to rescale the input image.
/// \param[in] rescale Rescale factor.
@ -337,6 +386,21 @@ std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<
/* ####################################### Derived TensorOperation classes ################################# */
class AutoContrastOperation : public TensorOperation {
public:
explicit AutoContrastOperation(float cutoff = 0.0, std::vector<uint32_t> ignore = {});
~AutoContrastOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
private:
float cutoff_;
std::vector<uint32_t> ignore_;
};
class CenterCropOperation : public TensorOperation {
public:
explicit CenterCropOperation(std::vector<int32_t> size);
@ -423,6 +487,15 @@ class HwcToChwOperation : public TensorOperation {
Status ValidateParams() override;
};
class InvertOperation : public TensorOperation {
public:
~InvertOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
};
class MixUpBatchOperation : public TensorOperation {
public:
explicit MixUpBatchOperation(float alpha = 1);
@ -566,6 +639,26 @@ class RandomCropDecodeResizeOperation : public TensorOperation {
int32_t max_attempts_;
};
class RandomCropWithBBoxOperation : public TensorOperation {
public:
RandomCropWithBBoxOperation(std::vector<int32_t> size, std::vector<int32_t> padding = {0, 0, 0, 0},
bool pad_if_needed = false, std::vector<uint8_t> fill_value = {0, 0, 0},
BorderType padding_mode = BorderType::kConstant);
~RandomCropWithBBoxOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
private:
std::vector<int32_t> size_;
std::vector<int32_t> padding_;
bool pad_if_needed_;
std::vector<uint8_t> fill_value_;
BorderType padding_mode_;
};
class RandomHorizontalFlipOperation : public TensorOperation {
public:
explicit RandomHorizontalFlipOperation(float probability = 0.5);
@ -580,6 +673,20 @@ class RandomHorizontalFlipOperation : public TensorOperation {
float probability_;
};
class RandomHorizontalFlipWithBBoxOperation : public TensorOperation {
public:
explicit RandomHorizontalFlipWithBBoxOperation(float probability = 0.5);
~RandomHorizontalFlipWithBBoxOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
private:
float probability_;
};
class RandomPosterizeOperation : public TensorOperation {
public:
explicit RandomPosterizeOperation(const std::vector<uint8_t> &bit_range = {4, 8});
@ -676,6 +783,20 @@ class RandomVerticalFlipOperation : public TensorOperation {
float probability_;
};
class RandomVerticalFlipWithBBoxOperation : public TensorOperation {
public:
explicit RandomVerticalFlipWithBBoxOperation(float probability = 0.5);
~RandomVerticalFlipWithBBoxOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
private:
float probability_;
};
class RescaleOperation : public TensorOperation {
public:
explicit RescaleOperation(float rescale, float shift);

View File

@ -33,9 +33,11 @@
#include "minddata/dataset/engine/ir/datasetops/source/cifar10_node.h"
#include "minddata/dataset/engine/ir/datasetops/source/image_folder_node.h"
#include "minddata/dataset/engine/ir/datasetops/source/mnist_node.h"
#include "minddata/dataset/engine/ir/datasetops/source/voc_node.h"
using namespace mindspore::dataset::api;
using mindspore::dataset::BorderType;
using mindspore::dataset::InterpolationMode;
using mindspore::dataset::Tensor;
class MindDataTestPipeline : public UT::DatasetOpTesting {
@ -44,6 +46,114 @@ class MindDataTestPipeline : public UT::DatasetOpTesting {
// Tests for vision ops (in alphabetical order)
TEST_F(MindDataTestPipeline, TestAutoContrastSuccess1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestAutoContrastSuccess1.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 5));
EXPECT_NE(ds, nullptr);
// Create a Repeat operation on ds
int32_t repeat_num = 3;
ds = ds->Repeat(repeat_num);
EXPECT_NE(ds, nullptr);
// Create auto contrast object with default values
std::shared_ptr<TensorOperation> auto_contrast = vision::AutoContrast();
EXPECT_NE(auto_contrast, nullptr);
// Create a Map operation on ds
ds = ds->Map({auto_contrast});
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<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 15);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestAutoContrastSuccess2) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestAutoContrastSuccess2.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 5));
EXPECT_NE(ds, nullptr);
// Create a Repeat operation on ds
int32_t repeat_num = 3;
ds = ds->Repeat(repeat_num);
EXPECT_NE(ds, nullptr);
// Create auto contrast object
std::shared_ptr<TensorOperation> auto_contrast = vision::AutoContrast(10, {10, 20});
EXPECT_NE(auto_contrast, nullptr);
// Create a Map operation on ds
ds = ds->Map({auto_contrast});
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<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 15);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestAutoContrastFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestAutoContrastFail with invalid params.";
// Testing invalid cutoff < 0
std::shared_ptr<TensorOperation> auto_contrast1 = vision::AutoContrast(-1.0);
EXPECT_EQ(auto_contrast1, nullptr);
// Testing invalid cutoff > 100
std::shared_ptr<TensorOperation> auto_contrast2 = vision::AutoContrast(110.0, {10, 20});
EXPECT_EQ(auto_contrast2, nullptr);
}
TEST_F(MindDataTestPipeline, TestCenterCrop) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestCenterCrop with single integer input.";
@ -535,6 +645,44 @@ TEST_F(MindDataTestPipeline, TestHwcToChw) {
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestInvert) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestInvert.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 20));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> invert_op = vision::Invert();
EXPECT_NE(invert_op, nullptr);
// Create a Map operation on ds
ds = ds->Map({invert_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<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 20);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestMixUpBatchFail1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestMixUpBatchFail1 with negative alpha parameter.";
@ -947,7 +1095,7 @@ TEST_F(MindDataTestPipeline, TestRandomColor) {
// Failure case: Set invalid negative lower bound
std::shared_ptr<TensorOperation> random_color_op_4 = vision::RandomColor(-0.5, 0.5);
EXPECT_EQ(random_color_op_2, nullptr);
EXPECT_EQ(random_color_op_4, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_color_op_1, random_color_op_3});
@ -1050,6 +1198,182 @@ TEST_F(MindDataTestPipeline, TestRandomColorAdjust) {
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomCropSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomCropSuccess.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 10));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// Testing siez of size vector is 1
std::shared_ptr<TensorOperation> random_crop = vision::RandomCrop({20});
EXPECT_NE(random_crop, nullptr);
// Testing siez of size vector is 2
std::shared_ptr<TensorOperation> random_crop1 = vision::RandomCrop({20, 20});
EXPECT_NE(random_crop1, nullptr);
// Testing siez of paddiing vector is 1
std::shared_ptr<TensorOperation> random_crop2 = vision::RandomCrop({20, 20}, {10});
EXPECT_NE(random_crop2, nullptr);
// Testing siez of paddiing vector is 2
std::shared_ptr<TensorOperation> random_crop3 = vision::RandomCrop({20, 20}, {10, 20});
EXPECT_NE(random_crop3, nullptr);
// Testing siez of paddiing vector is 2
std::shared_ptr<TensorOperation> random_crop4 = vision::RandomCrop({20, 20}, {10, 10, 10, 10});
EXPECT_NE(random_crop4, nullptr);
// Testing siez of fill_value vector is 1
std::shared_ptr<TensorOperation> random_crop5 = vision::RandomCrop({20, 20}, {10, 10, 10, 10}, false, {5});
EXPECT_NE(random_crop5, nullptr);
// Testing siez of fill_value vector is 3
std::shared_ptr<TensorOperation> random_crop6 = vision::RandomCrop({20, 20}, {10, 10, 10, 10}, false, {4, 4, 4});
EXPECT_NE(random_crop6, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_crop, random_crop1, random_crop2, random_crop3, random_crop4, random_crop5, random_crop6});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 10);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomCropFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomCropFail with invalid parameters.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// Testing the size parameter is negative.
std::shared_ptr<TensorOperation> random_crop = vision::RandomCrop({-28, 28});
EXPECT_EQ(random_crop, nullptr);
// Testing the size parameter is None.
std::shared_ptr<TensorOperation> random_crop1 = vision::RandomCrop({});
EXPECT_EQ(random_crop1, nullptr);
// Testing the size of size vector is 3.
std::shared_ptr<TensorOperation> random_crop2 = vision::RandomCrop({28, 28, 28});
EXPECT_EQ(random_crop2, nullptr);
// Testing the padding parameter is negative.
std::shared_ptr<TensorOperation> random_crop3 = vision::RandomCrop({28, 28}, {-5});
EXPECT_EQ(random_crop3, nullptr);
// Testing the size of padding vector is empty.
std::shared_ptr<TensorOperation> random_crop4 = vision::RandomCrop({28, 28}, {});
EXPECT_EQ(random_crop4, nullptr);
// Testing the size of padding vector is 3.
std::shared_ptr<TensorOperation> random_crop5 = vision::RandomCrop({28, 28}, {5, 5, 5});
EXPECT_EQ(random_crop5, nullptr);
// Testing the size of padding vector is 5.
std::shared_ptr<TensorOperation> random_crop6 = vision::RandomCrop({28, 28}, {5, 5, 5, 5, 5});
EXPECT_EQ(random_crop6, nullptr);
// Testing the size of fill_value vector is empty.
std::shared_ptr<TensorOperation> random_crop7 = vision::RandomCrop({28, 28}, {0, 0, 0, 0}, false, {});
EXPECT_EQ(random_crop7, nullptr);
// Testing the size of fill_value vector is 2.
std::shared_ptr<TensorOperation> random_crop8 = vision::RandomCrop({28, 28}, {0, 0, 0, 0}, false, {0, 0});
EXPECT_EQ(random_crop8, nullptr);
// Testing the size of fill_value vector is 4.
std::shared_ptr<TensorOperation> random_crop9 = vision::RandomCrop({28, 28}, {0, 0, 0, 0}, false, {0, 0, 0, 0});
EXPECT_EQ(random_crop9, nullptr);
}
TEST_F(MindDataTestPipeline, TestRandomCropWithBboxSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomCropWithBboxSuccess.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_crop = mindspore::dataset::api::vision::RandomCropWithBBox({128, 128});
EXPECT_NE(random_crop, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_crop}, {"image", "bbox"}, {"image", "bbox"}, {"image", "bbox"});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
EXPECT_EQ(image->shape()[0], 128);
EXPECT_EQ(image->shape()[1], 128);
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 3);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomCropWithBboxFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomCropWithBboxFail with invalid parameters.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// The size parameter is negative.
std::shared_ptr<TensorOperation> random_crop = vision::RandomCropWithBBox({-10});
EXPECT_EQ(random_crop, nullptr);
// The parameter in the padding vector is negative.
std::shared_ptr<TensorOperation> random_crop1 = vision::RandomCropWithBBox({10, 10}, {-2, 2, 2, 2});
EXPECT_EQ(random_crop1, nullptr);
// The size container is empty.
std::shared_ptr<TensorOperation> random_crop2 = vision::RandomCropWithBBox({});
EXPECT_EQ(random_crop2, nullptr);
// The size of the size container is too large.
std::shared_ptr<TensorOperation> random_crop3 = vision::RandomCropWithBBox({10, 10, 10});
EXPECT_EQ(random_crop3, nullptr);
// The padding container is empty.
std::shared_ptr<TensorOperation> random_crop4 = vision::RandomCropWithBBox({10, 10}, {});
EXPECT_EQ(random_crop4, nullptr);
// The size of the padding container is too large.
std::shared_ptr<TensorOperation> random_crop5 = vision::RandomCropWithBBox({10, 10}, {5, 5, 5, 5, 5});
EXPECT_EQ(random_crop5, nullptr);
// The fill_value container is empty.
std::shared_ptr<TensorOperation> random_crop6 = vision::RandomCropWithBBox({10, 10}, {5, 5, 5, 5}, false, {});
EXPECT_EQ(random_crop6, nullptr);
// The size of the fill_value container is too large.
std::shared_ptr<TensorOperation> random_crop7 =
vision::RandomCropWithBBox({10, 10}, {5, 5, 5, 5}, false, {3, 3, 3, 3});
EXPECT_EQ(random_crop7, nullptr);
}
TEST_F(MindDataTestPipeline, DISABLED_TestRandomHorizontalFlipFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomHorizontalFlipFail with invalid parameters.";
@ -1062,6 +1386,59 @@ TEST_F(MindDataTestPipeline, DISABLED_TestRandomHorizontalFlipFail) {
EXPECT_EQ(random_horizontal_flip_op, nullptr);
}
TEST_F(MindDataTestPipeline, TestRandomHorizontalFlipWithBBoxSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomHorizontalFlipWithBBoxSuccess.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_horizontal_flip_op = vision::RandomHorizontalFlipWithBBox(0.5);
EXPECT_NE(random_horizontal_flip_op, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_horizontal_flip_op}, {"image", "bbox"}, {"image", "bbox"}, {"image", "bbox"});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 3);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomHorizontalFlipWithBBoxFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomHorizontalFlipWithBBoxFail with invalid parameters.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// Incorrect prob parameter.
std::shared_ptr<TensorOperation> random_horizontal_flip_op = vision::RandomHorizontalFlipWithBBox(-1.0);
EXPECT_EQ(random_horizontal_flip_op, nullptr);
// Incorrect prob parameter.
std::shared_ptr<TensorOperation> random_horizontal_flip_op1 = vision::RandomHorizontalFlipWithBBox(2.0);
EXPECT_EQ(random_horizontal_flip_op1, nullptr);
}
TEST_F(MindDataTestPipeline, TestRandomHorizontalAndVerticalFlip) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomHorizontalAndVerticalFlip for horizontal and vertical flips.";
@ -1371,11 +1748,23 @@ TEST_F(MindDataTestPipeline, TestRandomRotation) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_rotation_op = vision::RandomRotation({-180, 180});
// Testing the size of degrees is 1
std::shared_ptr<TensorOperation> random_rotation_op = vision::RandomRotation({180});
EXPECT_NE(random_rotation_op, nullptr);
// Testing the size of degrees is 2
std::shared_ptr<TensorOperation> random_rotation_op1 = vision::RandomRotation({-180, 180});
EXPECT_NE(random_rotation_op1, nullptr);
// Testing the size of fill_value is 1
std::shared_ptr<TensorOperation> random_rotation_op2 =
vision::RandomRotation({180}, InterpolationMode::kNearestNeighbour, false, {-1, -1}, {2});
EXPECT_NE(random_rotation_op2, nullptr);
// Testing the size of fill_value is 3
std::shared_ptr<TensorOperation> random_rotation_op3 =
vision::RandomRotation({180}, InterpolationMode::kNearestNeighbour, false, {-1, -1}, {2, 2, 2});
EXPECT_NE(random_rotation_op3, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_rotation_op});
ds = ds->Map({random_rotation_op, random_rotation_op1, random_rotation_op2, random_rotation_op3});
EXPECT_NE(ds, nullptr);
// Create a Batch operation on ds
@ -1406,6 +1795,42 @@ TEST_F(MindDataTestPipeline, TestRandomRotation) {
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomRotationFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomRotationFail with invalid parameters.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 10));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// Testing the size of degrees vector is 0
std::shared_ptr<TensorOperation> random_rotation_op = vision::RandomRotation({});
EXPECT_EQ(random_rotation_op, nullptr);
// Testing the size of degrees vector is 3
std::shared_ptr<TensorOperation> random_rotation_op1 = vision::RandomRotation({-50.0, 50.0, 100.0});
EXPECT_EQ(random_rotation_op1, nullptr);
// Test the case where the first column value of degrees is greater than the second column value
std::shared_ptr<TensorOperation> random_rotation_op2 = vision::RandomRotation({50.0, -50.0});
EXPECT_EQ(random_rotation_op2, nullptr);
// Testing the size of center vector is 1
std::shared_ptr<TensorOperation> random_rotation_op3 =
vision::RandomRotation({-50.0, 50.0}, InterpolationMode::kNearestNeighbour, false, {-1.0});
EXPECT_EQ(random_rotation_op3, nullptr);
// Testing the size of center vector is 3
std::shared_ptr<TensorOperation> random_rotation_op4 =
vision::RandomRotation({-50.0, 50.0}, InterpolationMode::kNearestNeighbour, false, {-1.0, -1.0, -1.0});
EXPECT_EQ(random_rotation_op4, nullptr);
// Testing the size of fill_value vector is 2
std::shared_ptr<TensorOperation> random_rotation_op5 =
vision::RandomRotation({-50.0, 50.0}, InterpolationMode::kNearestNeighbour, false, {-1.0, -1.0}, {2, 2});
EXPECT_EQ(random_rotation_op5, nullptr);
// Testing the size of fill_value vector is 4
std::shared_ptr<TensorOperation> random_rotation_op6 =
vision::RandomRotation({-50.0, 50.0}, InterpolationMode::kNearestNeighbour, false, {-1.0, -1.0}, {2, 2, 2, 2});
EXPECT_EQ(random_rotation_op6, nullptr);
}
TEST_F(MindDataTestPipeline, TestRandomSharpness) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomSharpness.";
@ -1592,6 +2017,59 @@ TEST_F(MindDataTestPipeline, TestResizeFail) {
EXPECT_EQ(resize_op, nullptr);
}
TEST_F(MindDataTestPipeline, TestRandomVerticalFlipWithBBoxSuccess) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomVerticalFlipWithBBoxSuccess.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_vertical_flip_op = vision::RandomVerticalFlipWithBBox(0.4);
EXPECT_NE(random_vertical_flip_op, nullptr);
// Create a Map operation on ds
ds = ds->Map({random_vertical_flip_op}, {"image", "bbox"}, {"image", "bbox"}, {"image", "bbox"});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 3);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRandomVerticalFlipWithBBoxFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomVerticalFlipWithBBoxFail with invalid parameters.";
// Create an VOC Dataset
std::string folder_path = datasets_root_path_ + "/testVOC2012_2";
std::shared_ptr<Dataset> ds = VOC(folder_path, "Detection", "train", {}, true, SequentialSampler(0, 3));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
// Incorrect prob parameter.
std::shared_ptr<TensorOperation> random_vertical_flip_op = vision::RandomVerticalFlipWithBBox(-0.5);
EXPECT_EQ(random_vertical_flip_op, nullptr);
// Incorrect prob parameter.
std::shared_ptr<TensorOperation> random_vertical_flip_op1 = vision::RandomVerticalFlipWithBBox(3.0);
EXPECT_EQ(random_vertical_flip_op1, nullptr);
}
TEST_F(MindDataTestPipeline, TestResize1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestResize1 with single integer input.";
// Create an ImageFolder Dataset
@ -1640,6 +2118,96 @@ TEST_F(MindDataTestPipeline, TestResize1) {
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRescaleSucess1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRescaleSucess1.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, SequentialSampler(0, 1));
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
auto image = row["image"];
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> rescale = mindspore::dataset::api::vision::Rescale(1.0, 0.0);
EXPECT_NE(rescale, nullptr);
// Convert to the same type
std::shared_ptr<TensorOperation> type_cast = transforms::TypeCast("uint8");
EXPECT_NE(type_cast, nullptr);
ds = ds->Map({rescale, type_cast}, {"image"});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter1 = ds->CreateIterator();
EXPECT_NE(iter1, nullptr);
// Iterate the dataset and get each row1
std::unordered_map<std::string, std::shared_ptr<Tensor>> row1;
iter1->GetNextRow(&row1);
auto image1 = row1["image"];
EXPECT_EQ(*image, *image1);
// Manually terminate the pipeline
iter1->Stop();
}
TEST_F(MindDataTestPipeline, TestRescaleSucess2) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRescaleSucess2 with different params.";
// Create an ImageFolder Dataset
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 1));
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> rescale = mindspore::dataset::api::vision::Rescale(1.0 / 255, 1.0);
EXPECT_NE(rescale, nullptr);
ds = ds->Map({rescale}, {"image"});
EXPECT_NE(ds, nullptr);
// Create an iterator over the result of the above dataset
// This will trigger the creation of the Execution Tree and launch it.
std::shared_ptr<Iterator> iter = ds->CreateIterator();
EXPECT_NE(iter, nullptr);
// Iterate the dataset and get each row
std::unordered_map<std::string, std::shared_ptr<Tensor>> row;
iter->GetNextRow(&row);
uint64_t i = 0;
while (row.size() != 0) {
i++;
auto image = row["image"];
MS_LOG(INFO) << "Tensor image shape: " << image->shape();
iter->GetNextRow(&row);
}
EXPECT_EQ(i, 1);
// Manually terminate the pipeline
iter->Stop();
}
TEST_F(MindDataTestPipeline, TestRescaleFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRescaleFail with invalid params.";
// incorrect negative rescale parameter
std::shared_ptr<TensorOperation> rescale = mindspore::dataset::api::vision::Rescale(-1.0, 0.0);
EXPECT_EQ(rescale, nullptr);
}
TEST_F(MindDataTestPipeline, DISABLED_TestUniformAugmentFail1) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestUniformAugmentFail1 with invalid zero num_ops parameter.";