提交 94a4a3f2 编写于 作者: I islam_amin

changing affine and posterize apis

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