forked from mindspore-Ecosystem/mindspore
!19748 Fix param check and default value of center in Rotate and RandomRotation Ops
Merge pull request !19748 from xiaotianci/fix_rotate_center
This commit is contained in:
commit
53633ebfd8
|
@ -642,13 +642,13 @@ class RandomRotation final : public TensorTransform {
|
|||
/// - InterpolationMode::kArea, Interpolation method is pixel area interpolation.
|
||||
/// - InterpolationMode::kCubicPil, Interpolation method is bicubic interpolation like implemented in pillow.
|
||||
/// \param[in] expand A boolean representing whether the image is expanded after rotation.
|
||||
/// \param[in] center A float vector of size 2, representing the x and y center of rotation.
|
||||
/// \param[in] center A float vector of size 2 or empty, representing the x and y center of rotation
|
||||
/// or the center of the image.
|
||||
/// \param[in] fill_value A vector representing the value to fill the area outside the transform
|
||||
/// in the output image. If 1 value is provided, it is used for all RGB channels.
|
||||
/// If 3 values are provided, it is used to fill R, G, B channels respectively.
|
||||
RandomRotation(std::vector<float> degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour,
|
||||
bool expand = false, std::vector<float> center = {-1, -1},
|
||||
std::vector<uint8_t> fill_value = {0, 0, 0});
|
||||
bool expand = false, std::vector<float> center = {}, std::vector<uint8_t> fill_value = {0, 0, 0});
|
||||
|
||||
/// \brief Destructor.
|
||||
~RandomRotation() = default;
|
||||
|
|
|
@ -323,12 +323,13 @@ class Rotate final : public TensorTransform {
|
|||
/// - InterpolationMode::kArea, Interpolation method is pixel area interpolation.
|
||||
/// - InterpolationMode::kCubicPil, Interpolation method is bicubic interpolation like implemented in pillow.
|
||||
/// \param[in] expand A boolean representing whether the image is expanded after rotation.
|
||||
/// \param[in] center A float vector of size 2, representing the x and y center of rotation.
|
||||
/// \param[in] center A float vector of size 2 or empty, representing the x and y center of rotation
|
||||
/// or the center of the image.
|
||||
/// \param[in] fill_value A vector representing the value to fill the area outside the transform
|
||||
/// in the output image. If 1 value is provided, it is used for all RGB channels.
|
||||
/// If 3 values are provided, it is used to fill R, G, B channels respectively.
|
||||
Rotate(float degrees, InterpolationMode resample = InterpolationMode::kNearestNeighbour, bool expand = false,
|
||||
std::vector<float> center = {-1, -1}, std::vector<uint8_t> fill_value = {0, 0, 0});
|
||||
std::vector<float> center = {}, std::vector<uint8_t> fill_value = {0, 0, 0});
|
||||
|
||||
/// \brief Destructor.
|
||||
~Rotate() = default;
|
||||
|
|
|
@ -627,8 +627,9 @@ Status CropAndResize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tenso
|
|||
}
|
||||
}
|
||||
|
||||
Status Rotate(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float fx, float fy, float degree,
|
||||
InterpolationMode interpolation, bool expand, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b) {
|
||||
Status Rotate(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, std::vector<float> center,
|
||||
float degree, InterpolationMode interpolation, bool expand, uint8_t fill_r, uint8_t fill_g,
|
||||
uint8_t fill_b) {
|
||||
try {
|
||||
std::shared_ptr<CVTensor> input_cv = CVTensor::AsCVTensor(input);
|
||||
if (!input_cv->mat().data) {
|
||||
|
@ -642,12 +643,14 @@ Status Rotate(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
|
|||
if (input_img.cols > (MAX_INT_PRECISION * 2) || input_img.rows > (MAX_INT_PRECISION * 2)) {
|
||||
RETURN_STATUS_UNEXPECTED("Rotate: image is too large and center is not precise.");
|
||||
}
|
||||
// default to center of image
|
||||
if (fx == -1) {
|
||||
float fx = 0, fy = 0;
|
||||
if (center.empty()) {
|
||||
// default to center of image
|
||||
fx = (input_img.cols - 1) / 2.0;
|
||||
}
|
||||
if (fy == -1) {
|
||||
fy = (input_img.rows - 1) / 2.0;
|
||||
} else {
|
||||
fx = center[0];
|
||||
fy = center[1];
|
||||
}
|
||||
cv::Mat output_img;
|
||||
cv::Scalar fill_color = cv::Scalar(fill_b, fill_g, fill_r);
|
||||
|
|
|
@ -183,13 +183,12 @@ Status CropAndResize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tenso
|
|||
|
||||
/// \brief Returns rotated image
|
||||
/// \param input: Tensor of shape <H,W,C> or <H,W> and any OpenCv compatible type, see CVTensor.
|
||||
/// \param fx: rotation center x coordinate
|
||||
/// \param fy: rotation center y coordinate
|
||||
/// \param center: rotation center
|
||||
/// \param degree: degree to rotate
|
||||
/// \param expand: if reshape is necessary
|
||||
/// \param output: rotated image of same input type.
|
||||
Status Rotate(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, float fx, float fy, float degree,
|
||||
InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, bool expand = false,
|
||||
Status Rotate(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, std::vector<float> center,
|
||||
float degree, InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, bool expand = false,
|
||||
uint8_t fill_r = 0, uint8_t fill_g = 0, uint8_t fill_b = 0);
|
||||
|
||||
/// \brief Returns Normalized image
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
const float RandomRotationOp::kDefCenterX = -1;
|
||||
const float RandomRotationOp::kDefCenterY = -1;
|
||||
const std::vector<float> RandomRotationOp::kDefCenter = {};
|
||||
const InterpolationMode RandomRotationOp::kDefInterpolation = InterpolationMode::kNearestNeighbour;
|
||||
const bool RandomRotationOp::kDefExpand = false;
|
||||
const uint8_t RandomRotationOp::kDefFillR = 0;
|
||||
|
@ -34,11 +33,10 @@ const uint8_t RandomRotationOp::kDefFillB = 0;
|
|||
|
||||
// constructor
|
||||
RandomRotationOp::RandomRotationOp(float start_degree, float end_degree, InterpolationMode resample, bool expand,
|
||||
float center_x, float center_y, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b)
|
||||
std::vector<float> center, uint8_t fill_r, uint8_t fill_g, uint8_t fill_b)
|
||||
: degree_start_(start_degree),
|
||||
degree_end_(end_degree),
|
||||
center_x_(center_x),
|
||||
center_y_(center_y),
|
||||
center_(center),
|
||||
interpolation_(resample),
|
||||
expand_(expand),
|
||||
fill_r_(fill_r),
|
||||
|
@ -60,8 +58,9 @@ Status RandomRotationOp::Compute(const std::shared_ptr<Tensor> &input, std::shar
|
|||
float mid = (degree_end_ + degree_start_) / 2;
|
||||
float degree = mid + random_double * degree_range;
|
||||
|
||||
return Rotate(input, output, center_x_, center_y_, degree, interpolation_, expand_, fill_r_, fill_g_, fill_b_);
|
||||
return Rotate(input, output, center_, degree, interpolation_, expand_, fill_r_, fill_g_, fill_b_);
|
||||
}
|
||||
|
||||
Status RandomRotationOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
|
||||
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
|
||||
outputs.clear();
|
||||
|
|
|
@ -31,8 +31,7 @@ namespace dataset {
|
|||
class RandomRotationOp : public TensorOp {
|
||||
public:
|
||||
// Default values, also used by python_bindings.cc
|
||||
static const float kDefCenterX;
|
||||
static const float kDefCenterY;
|
||||
static const std::vector<float> kDefCenter;
|
||||
static const InterpolationMode kDefInterpolation;
|
||||
static const bool kDefExpand;
|
||||
static const uint8_t kDefFillR;
|
||||
|
@ -44,8 +43,7 @@ class RandomRotationOp : public TensorOp {
|
|||
// @param endDegree ending range for random degree
|
||||
// @param interpolation DE interpolation mode for rotation
|
||||
// @param expand option for the output image shape to change
|
||||
// @param center_x coordinate for center of image rotation
|
||||
// @param center_y coordinate for center of image rotation
|
||||
// @param center coordinate for center of image rotation
|
||||
// @param fill_r R value for the color to pad with
|
||||
// @param fill_g G value for the color to pad with
|
||||
// @param fill_b B value for the color to pad with
|
||||
|
@ -53,8 +51,8 @@ class RandomRotationOp : public TensorOp {
|
|||
// @details the output shape, if changed, will contain the entire rotated image
|
||||
// @note maybe using unsigned long int isn't the best here according to our coding rules
|
||||
RandomRotationOp(float start_degree, float end_degree, InterpolationMode resample = kDefInterpolation,
|
||||
bool expand = kDefExpand, float center_x = kDefCenterX, float center_y = kDefCenterY,
|
||||
uint8_t fill_r = kDefFillR, uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB);
|
||||
bool expand = kDefExpand, std::vector<float> center = kDefCenter, uint8_t fill_r = kDefFillR,
|
||||
uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB);
|
||||
|
||||
~RandomRotationOp() override = default;
|
||||
|
||||
|
@ -63,6 +61,7 @@ class RandomRotationOp : public TensorOp {
|
|||
// and transforms its data using openCV, the output memory is manipulated to contain the result
|
||||
// @return Status The status code returned
|
||||
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
|
||||
|
||||
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
|
||||
|
||||
std::string Name() const override { return kRandomRotationOp; }
|
||||
|
@ -70,8 +69,7 @@ class RandomRotationOp : public TensorOp {
|
|||
private:
|
||||
float degree_start_;
|
||||
float degree_end_;
|
||||
float center_x_;
|
||||
float center_y_;
|
||||
std::vector<float> center_;
|
||||
InterpolationMode interpolation_;
|
||||
bool expand_;
|
||||
uint8_t fill_r_;
|
||||
|
|
|
@ -24,8 +24,7 @@
|
|||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
const float RotateOp::kDefCenterX = -1;
|
||||
const float RotateOp::kDefCenterY = -1;
|
||||
const std::vector<float> RotateOp::kDefCenter = {};
|
||||
const InterpolationMode RotateOp::kDefInterpolation = InterpolationMode::kNearestNeighbour;
|
||||
const bool RotateOp::kDefExpand = false;
|
||||
const uint8_t RotateOp::kDefFillR = 0;
|
||||
|
@ -34,11 +33,10 @@ const uint8_t RotateOp::kDefFillB = 0;
|
|||
|
||||
RotateOp::RotateOp(int angle_id) : angle_id_(angle_id) {}
|
||||
|
||||
RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, float center_x, float center_y,
|
||||
uint8_t fill_r, uint8_t fill_g, uint8_t fill_b)
|
||||
RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, std::vector<float> center, uint8_t fill_r,
|
||||
uint8_t fill_g, uint8_t fill_b)
|
||||
: degrees_(degrees),
|
||||
center_x_(center_x),
|
||||
center_y_(center_y),
|
||||
center_(center),
|
||||
interpolation_(resample),
|
||||
expand_(expand),
|
||||
fill_r_(fill_r),
|
||||
|
@ -48,7 +46,7 @@ RotateOp::RotateOp(float degrees, InterpolationMode resample, bool expand, float
|
|||
Status RotateOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
|
||||
IO_CHECK(input, output);
|
||||
#ifndef ENABLE_ANDROID
|
||||
return Rotate(input, output, center_x_, center_y_, degrees_, interpolation_, expand_, fill_r_, fill_g_, fill_b_);
|
||||
return Rotate(input, output, center_, degrees_, interpolation_, expand_, fill_r_, fill_g_, fill_b_);
|
||||
#else
|
||||
return Rotate(input, output, angle_id_);
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,7 @@ namespace dataset {
|
|||
class RotateOp : public TensorOp {
|
||||
public:
|
||||
// Default values, also used by python_bindings.cc
|
||||
static const float kDefCenterX;
|
||||
static const float kDefCenterY;
|
||||
static const std::vector<float> kDefCenter;
|
||||
static const InterpolationMode kDefInterpolation;
|
||||
static const bool kDefExpand;
|
||||
static const uint8_t kDefFillR;
|
||||
|
@ -42,8 +41,8 @@ class RotateOp : public TensorOp {
|
|||
explicit RotateOp(int angle_id);
|
||||
|
||||
explicit RotateOp(float degrees, InterpolationMode resample = kDefInterpolation, bool expand = kDefExpand,
|
||||
float center_x = kDefCenterX, float center_y = kDefCenterY, uint8_t fill_r = kDefFillR,
|
||||
uint8_t fill_g = kDefFillG, uint8_t fill_b = kDefFillB);
|
||||
std::vector<float> center = kDefCenter, uint8_t fill_r = kDefFillR, uint8_t fill_g = kDefFillG,
|
||||
uint8_t fill_b = kDefFillB);
|
||||
|
||||
~RotateOp() override = default;
|
||||
|
||||
|
@ -61,8 +60,7 @@ class RotateOp : public TensorOp {
|
|||
|
||||
private:
|
||||
float degrees_;
|
||||
float center_x_;
|
||||
float center_y_;
|
||||
std::vector<float> center_;
|
||||
InterpolationMode interpolation_;
|
||||
bool expand_;
|
||||
uint8_t fill_r_;
|
||||
|
|
|
@ -64,9 +64,9 @@ Status RandomRotationOperation::ValidateParams() {
|
|||
RETURN_STATUS_SYNTAX_ERROR(err_msg);
|
||||
}
|
||||
// center
|
||||
if (center_.empty() || center_.size() != 2) {
|
||||
if (center_.size() != 0 && center_.size() != 2) {
|
||||
std::string err_msg =
|
||||
"RandomRotation: center must be a vector of two values, got: " + std::to_string(center_.size());
|
||||
"RandomRotation: center must be a vector of two values or empty, got: " + std::to_string(center_.size());
|
||||
MS_LOG(ERROR) << err_msg;
|
||||
RETURN_STATUS_SYNTAX_ERROR(err_msg);
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ std::shared_ptr<TensorOp> RandomRotationOperation::Build() {
|
|||
}
|
||||
|
||||
std::shared_ptr<RandomRotationOp> tensor_op = std::make_shared<RandomRotationOp>(
|
||||
start_degree, end_degree, interpolation_mode_, expand_, center_[0], center_[1], fill_r, fill_g, fill_b);
|
||||
start_degree, end_degree, interpolation_mode_, expand_, center_, fill_r, fill_g, fill_b);
|
||||
return tensor_op;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,8 +37,9 @@ std::string RotateOperation::Name() const { return kRotateOperation; }
|
|||
Status RotateOperation::ValidateParams() {
|
||||
#ifndef ENABLE_ANDROID
|
||||
// center
|
||||
if (center_.empty() || center_.size() != 2) {
|
||||
std::string err_msg = "Rotate: center must be a vector of two values, got: " + std::to_string(center_.size());
|
||||
if (center_.size() != 0 && center_.size() != 2) {
|
||||
std::string err_msg =
|
||||
"Rotate: center must be a vector of two values or empty, got: " + std::to_string(center_.size());
|
||||
MS_LOG(ERROR) << err_msg;
|
||||
RETURN_STATUS_SYNTAX_ERROR(err_msg);
|
||||
}
|
||||
|
@ -62,7 +63,7 @@ std::shared_ptr<TensorOp> RotateOperation::Build() {
|
|||
}
|
||||
|
||||
std::shared_ptr<RotateOp> tensor_op =
|
||||
std::make_shared<RotateOp>(degrees_, interpolation_mode_, expand_, center_[0], center_[1], fill_r, fill_g, fill_b);
|
||||
std::make_shared<RotateOp>(degrees_, interpolation_mode_, expand_, center_, fill_r, fill_g, fill_b);
|
||||
return tensor_op;
|
||||
#else
|
||||
return rotate_op_;
|
||||
|
|
|
@ -90,6 +90,7 @@ DE_C_INTER_MODE = {Inter.NEAREST: cde.InterpolationMode.DE_INTER_NEAREST_NEIGHBO
|
|||
DE_C_SLICE_MODE = {SliceMode.PAD: cde.SliceMode.DE_SLICE_PAD,
|
||||
SliceMode.DROP: cde.SliceMode.DE_SLICE_DROP}
|
||||
|
||||
|
||||
def parse_padding(padding):
|
||||
""" Parses and prepares the padding tuple"""
|
||||
if isinstance(padding, numbers.Number):
|
||||
|
@ -1214,7 +1215,7 @@ class RandomRotation(ImageTensorOperation):
|
|||
if degrees[0] > degrees[1]:
|
||||
degrees[1] += 360
|
||||
if center is None:
|
||||
center = (-1, -1)
|
||||
center = ()
|
||||
if isinstance(fill_value, int):
|
||||
fill_value = tuple([fill_value] * 3)
|
||||
self.degrees = degrees
|
||||
|
@ -1525,7 +1526,7 @@ class Rotate(ImageTensorOperation):
|
|||
if isinstance(degrees, (int, float)):
|
||||
degrees = degrees % 360
|
||||
if center is None:
|
||||
center = (-1, -1)
|
||||
center = ()
|
||||
if isinstance(fill_value, int):
|
||||
fill_value = tuple([fill_value] * 3)
|
||||
self.degrees = degrees
|
||||
|
@ -1576,6 +1577,7 @@ class SlicePatches(ImageTensorOperation):
|
|||
return cde.SlicePatchesOperation(self.num_height, self.num_width,
|
||||
DE_C_SLICE_MODE[self.slice_mode], self.fill_value)
|
||||
|
||||
|
||||
class SoftDvppDecodeRandomCropResizeJpeg(ImageTensorOperation):
|
||||
"""
|
||||
A combination of `Crop`, `Decode` and `Resize` using the simulation algorithm of Ascend series chip DVPP module.
|
||||
|
|
|
@ -20,8 +20,9 @@ import numpy as np
|
|||
from mindspore._c_dataengine import TensorOp, TensorOperation
|
||||
|
||||
from mindspore.dataset.core.validator_helpers import check_value, check_uint8, FLOAT_MAX_INTEGER, check_pos_float32, \
|
||||
check_float32, check_2tuple, check_range, check_positive, INT32_MAX, parse_user_args, type_check, type_check_list, \
|
||||
check_c_tensor_op, UINT8_MAX, check_value_normalize_std, check_value_cutoff, check_value_ratio, check_odd
|
||||
check_float32, check_2tuple, check_range, check_positive, INT32_MAX, INT32_MIN, parse_user_args, type_check, \
|
||||
type_check_list, check_c_tensor_op, UINT8_MAX, check_value_normalize_std, check_value_cutoff, check_value_ratio, \
|
||||
check_odd
|
||||
from .utils import Inter, Border, ImageBatchFormat, SliceMode
|
||||
|
||||
|
||||
|
@ -427,7 +428,7 @@ def check_resample_expand_center_fill_value_params(resample, expand, center, fil
|
|||
check_2tuple(center, "center")
|
||||
for value in center:
|
||||
type_check(value, (int, float), "center")
|
||||
check_value(value, [-1, INT32_MAX], "center")
|
||||
check_value(value, [INT32_MIN, INT32_MAX], "center")
|
||||
check_fill_value(fill_value)
|
||||
|
||||
|
||||
|
@ -528,6 +529,7 @@ def check_slice_patches(method):
|
|||
|
||||
return new_method
|
||||
|
||||
|
||||
def check_random_perspective(method):
|
||||
"""Wrapper method to check the parameters of random perspective."""
|
||||
|
||||
|
|
|
@ -35,11 +35,10 @@ TEST_F(MindDataTestRandomRotationOp, TestOp) {
|
|||
float sDegree = -180;
|
||||
float eDegree = 180;
|
||||
// use compute center to use for rotation
|
||||
float xCenter = -1;
|
||||
float yCenter = -1;
|
||||
std::vector<float> center = {};
|
||||
bool expand = false;
|
||||
std::unique_ptr<RandomRotationOp> op(
|
||||
new RandomRotationOp(sDegree, eDegree, InterpolationMode::kLinear, expand, xCenter, yCenter));
|
||||
new RandomRotationOp(sDegree, eDegree, InterpolationMode::kLinear, expand, center));
|
||||
EXPECT_TRUE(op->OneToOne());
|
||||
Status s = op->Compute(input_tensor_, &output_tensor);
|
||||
EXPECT_TRUE(s.IsOk());
|
||||
|
|
|
@ -36,11 +36,10 @@ TEST_F(MindDataTestToFloat16Op, TestOp) {
|
|||
float s_degree = -180;
|
||||
float e_degree = 180;
|
||||
// use compute center to use for rotation
|
||||
float x_center = -1;
|
||||
float y_center = -1;
|
||||
std::vector<float> center = {};
|
||||
bool expand = false;
|
||||
std::unique_ptr<RandomRotationOp> op(
|
||||
new RandomRotationOp(s_degree, e_degree, InterpolationMode::kLinear, expand, x_center, y_center));
|
||||
new RandomRotationOp(s_degree, e_degree, InterpolationMode::kLinear, expand, center));
|
||||
EXPECT_TRUE(op->OneToOne());
|
||||
Status s = op->Compute(input_tensor_, &output_tensor);
|
||||
EXPECT_TRUE(s.IsOk());
|
||||
|
|
Loading…
Reference in New Issue