Update Python UA op, AutoContrast Op and UT

Updated Validators.py

Fixed UA UT

Fixed UA UT

Fixed PyLint Errors

Added aditional changes

remove old golden AutoContrast UT file

updated Autocontrast python UT

Added golden files

Fixed issue

fixed UT
pull/3180/head
Amir Lashkari 5 years ago committed by alashkari
parent d15b4c5d61
commit 6f186aafa0

@ -425,7 +425,7 @@ void bindTensorOps1(py::module *m) {
(void)py::class_<UniformAugOp, TensorOp, std::shared_ptr<UniformAugOp>>( (void)py::class_<UniformAugOp, TensorOp, std::shared_ptr<UniformAugOp>>(
*m, "UniformAugOp", "Tensor operation to apply random augmentation(s).") *m, "UniformAugOp", "Tensor operation to apply random augmentation(s).")
.def(py::init<std::vector<std::shared_ptr<TensorOp>>, int32_t>(), py::arg("operations"), .def(py::init<std::vector<std::shared_ptr<TensorOp>>, int32_t>(), py::arg("transforms"),
py::arg("NumOps") = UniformAugOp::kDefNumOps); py::arg("NumOps") = UniformAugOp::kDefNumOps);
(void)py::class_<BoundingBoxAugmentOp, TensorOp, std::shared_ptr<BoundingBoxAugmentOp>>( (void)py::class_<BoundingBoxAugmentOp, TensorOp, std::shared_ptr<BoundingBoxAugmentOp>>(

@ -90,9 +90,9 @@ std::shared_ptr<CenterCropOperation> CenterCrop(std::vector<int32_t> size) {
} }
// Function to create UniformAugOperation. // Function to create UniformAugOperation.
std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<TensorOperation>> operations, std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<TensorOperation>> transforms,
int32_t num_ops) { int32_t num_ops) {
auto op = std::make_shared<UniformAugOperation>(operations, num_ops); auto op = std::make_shared<UniformAugOperation>(transforms, num_ops);
// Input validation // Input validation
if (!op->ValidateParams()) { if (!op->ValidateParams()) {
return nullptr; return nullptr;
@ -290,14 +290,14 @@ std::shared_ptr<TensorOp> CenterCropOperation::Build() {
} }
// UniformAugOperation // UniformAugOperation
UniformAugOperation::UniformAugOperation(std::vector<std::shared_ptr<TensorOperation>> operations, int32_t num_ops) UniformAugOperation::UniformAugOperation(std::vector<std::shared_ptr<TensorOperation>> transforms, int32_t num_ops)
: operations_(operations), num_ops_(num_ops) {} : transforms_(transforms), num_ops_(num_ops) {}
bool UniformAugOperation::ValidateParams() { return true; } bool UniformAugOperation::ValidateParams() { return true; }
std::shared_ptr<TensorOp> UniformAugOperation::Build() { std::shared_ptr<TensorOp> UniformAugOperation::Build() {
std::vector<std::shared_ptr<TensorOp>> tensor_ops; std::vector<std::shared_ptr<TensorOp>> tensor_ops;
(void)std::transform(operations_.begin(), operations_.end(), std::back_inserter(tensor_ops), (void)std::transform(transforms_.begin(), transforms_.end(), std::back_inserter(tensor_ops),
[](std::shared_ptr<TensorOperation> op) -> std::shared_ptr<TensorOp> { return op->Build(); }); [](std::shared_ptr<TensorOperation> op) -> std::shared_ptr<TensorOp> { return op->Build(); });
std::shared_ptr<UniformAugOp> tensor_op = std::make_shared<UniformAugOp>(tensor_ops, num_ops_); std::shared_ptr<UniformAugOp> tensor_op = std::make_shared<UniformAugOp>(tensor_ops, num_ops_);
return tensor_op; return tensor_op;

@ -108,10 +108,10 @@ std::shared_ptr<CenterCropOperation> CenterCrop(std::vector<int32_t> size);
/// \brief Function to create a UniformAugment TensorOperation. /// \brief Function to create a UniformAugment TensorOperation.
/// \notes Tensor operation to perform randomly selected augmentation. /// \notes Tensor operation to perform randomly selected augmentation.
/// \param[in] operations - a vector of TensorOperation operations. /// \param[in] transforms - a vector of TensorOperation transforms.
/// \param[in] num_ops - integer representing the number of OPs to be selected and applied. /// \param[in] num_ops - integer representing the number of OPs to be selected and applied.
/// \return Shared pointer to the current TensorOperation. /// \return Shared pointer to the current TensorOperation.
std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<TensorOperation>> operations, std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<TensorOperation>> transforms,
int32_t num_ops = 2); int32_t num_ops = 2);
/// \brief Function to create a RandomHorizontalFlip TensorOperation. /// \brief Function to create a RandomHorizontalFlip TensorOperation.
@ -264,7 +264,7 @@ class CenterCropOperation : public TensorOperation {
class UniformAugOperation : public TensorOperation { class UniformAugOperation : public TensorOperation {
public: public:
explicit UniformAugOperation(std::vector<std::shared_ptr<TensorOperation>> operations, int32_t num_ops = 2); explicit UniformAugOperation(std::vector<std::shared_ptr<TensorOperation>> transforms, int32_t num_ops = 2);
~UniformAugOperation() = default; ~UniformAugOperation() = default;
@ -273,7 +273,7 @@ class UniformAugOperation : public TensorOperation {
bool ValidateParams() override; bool ValidateParams() override;
private: private:
std::vector<std::shared_ptr<TensorOperation>> operations_; std::vector<std::shared_ptr<TensorOperation>> transforms_;
int32_t num_ops_; int32_t num_ops_;
}; };

@ -722,7 +722,7 @@ class UniformAugment(cde.UniformAugOp):
Tensor operation to perform randomly selected augmentation. Tensor operation to perform randomly selected augmentation.
Args: Args:
operations: list of C++ operations (python OPs are not accepted). transforms: list of C++ operations (python OPs are not accepted).
num_ops (int, optional): number of OPs to be selected and applied (default=2). num_ops (int, optional): number of OPs to be selected and applied (default=2).
Examples: Examples:
@ -730,7 +730,7 @@ class UniformAugment(cde.UniformAugOp):
>>> c_transforms.RandomVerticalFlip(), >>> c_transforms.RandomVerticalFlip(),
>>> c_transforms.RandomColorAdjust(), >>> c_transforms.RandomColorAdjust(),
>>> c_transforms.RandomRotation(degrees=45)] >>> c_transforms.RandomRotation(degrees=45)]
>>> uni_aug = c_transforms.UniformAugment(operations=transforms_list, num_ops=2) >>> uni_aug = c_transforms.UniformAugment(transforms=transforms_list, num_ops=2)
>>> transforms_all = [c_transforms.Decode(), c_transforms.Resize(size=[224, 224]), >>> transforms_all = [c_transforms.Decode(), c_transforms.Resize(size=[224, 224]),
>>> uni_aug, F.ToTensor()] >>> uni_aug, F.ToTensor()]
>>> ds_ua = ds.map(input_columns="image", >>> ds_ua = ds.map(input_columns="image",
@ -738,10 +738,10 @@ class UniformAugment(cde.UniformAugOp):
""" """
@check_uniform_augment_cpp @check_uniform_augment_cpp
def __init__(self, operations, num_ops=2): def __init__(self, transforms, num_ops=2):
self.operations = operations self.transforms = transforms
self.num_ops = num_ops self.num_ops = num_ops
super().__init__(operations, num_ops) super().__init__(transforms, num_ops)
class RandomSelectSubpolicy(cde.RandomSelectSubpolicyOp): class RandomSelectSubpolicy(cde.RandomSelectSubpolicyOp):

@ -33,7 +33,7 @@ from .validators import check_prob, check_crop, check_resize_interpolation, chec
check_normalize_py, check_random_crop, check_random_color_adjust, check_random_rotation, \ check_normalize_py, check_random_crop, check_random_color_adjust, check_random_rotation, \
check_transforms_list, check_random_apply, check_ten_crop, check_num_channels, check_pad, \ check_transforms_list, check_random_apply, check_ten_crop, check_num_channels, check_pad, \
check_random_perspective, check_random_erasing, check_cutout, check_linear_transform, check_random_affine, \ check_random_perspective, check_random_erasing, check_cutout, check_linear_transform, check_random_affine, \
check_mix_up, check_positive_degrees, check_uniform_augment_py, check_compose_list check_mix_up, check_positive_degrees, check_uniform_augment_py, check_compose_list, check_auto_contrast
from .utils import Inter, Border from .utils import Inter, Border
DE_PY_INTER_MODE = {Inter.NEAREST: Image.NEAREST, DE_PY_INTER_MODE = {Inter.NEAREST: Image.NEAREST,
@ -1361,6 +1361,10 @@ class AutoContrast:
""" """
Automatically maximize the contrast of the input PIL image. Automatically maximize the contrast of the input PIL image.
Args:
cutoff (float, optional): Percent of pixels to cut off from the histogram (default=0.0).
ignore (int or sequence, optional): Pixel values to ignore (default=None).
Examples: Examples:
>>> py_transforms.ComposeOp([py_transforms.Decode(), >>> py_transforms.ComposeOp([py_transforms.Decode(),
>>> py_transforms.AutoContrast(), >>> py_transforms.AutoContrast(),
@ -1368,6 +1372,11 @@ class AutoContrast:
""" """
@check_auto_contrast
def __init__(self, cutoff=0.0, ignore=None):
self.cutoff = cutoff
self.ignore = ignore
def __call__(self, img): def __call__(self, img):
""" """
Call method. Call method.
@ -1379,7 +1388,7 @@ class AutoContrast:
img (PIL Image), Augmented image. img (PIL Image), Augmented image.
""" """
return util.auto_contrast(img) return util.auto_contrast(img, self.cutoff, self.ignore)
class Invert: class Invert:

@ -1457,13 +1457,15 @@ def random_sharpness(img, degrees):
return ImageEnhance.Sharpness(img).enhance(v) return ImageEnhance.Sharpness(img).enhance(v)
def auto_contrast(img): def auto_contrast(img, cutoff, ignore):
""" """
Automatically maximize the contrast of the input PIL image. Automatically maximize the contrast of the input PIL image.
Args: Args:
img (PIL Image): Image to be augmented with AutoContrast. img (PIL Image): Image to be augmented with AutoContrast.
cutoff (float, optional): Percent of pixels to cut off from the histogram (default=0.0).
ignore (int or sequence, optional): Pixel values to ignore (default=None).
Returns: Returns:
img (PIL Image), Augmented image. img (PIL Image), Augmented image.
@ -1473,7 +1475,7 @@ def auto_contrast(img):
if not is_pil(img): if not is_pil(img):
raise TypeError('img should be PIL Image. Got {}'.format(type(img))) raise TypeError('img should be PIL Image. Got {}'.format(type(img)))
return ImageOps.autocontrast(img) return ImageOps.autocontrast(img, cutoff, ignore)
def invert_color(img): def invert_color(img):

@ -506,13 +506,13 @@ def check_uniform_augment_cpp(method):
@wraps(method) @wraps(method)
def new_method(self, *args, **kwargs): def new_method(self, *args, **kwargs):
[operations, num_ops], _ = parse_user_args(method, *args, **kwargs) [transforms, num_ops], _ = parse_user_args(method, *args, **kwargs)
type_check(num_ops, (int,), "num_ops") type_check(num_ops, (int,), "num_ops")
check_positive(num_ops, "num_ops") check_positive(num_ops, "num_ops")
if num_ops > len(operations): if num_ops > len(transforms):
raise ValueError("num_ops is greater than operations list size") raise ValueError("num_ops is greater than transforms list size")
type_check_list(operations, (TensorOp,), "tensor_ops") type_check_list(transforms, (TensorOp,), "tensor_ops")
return method(self, *args, **kwargs) return method(self, *args, **kwargs)

@ -58,7 +58,7 @@ def test_auto_contrast_py(plot=False):
transforms_auto_contrast = F.ComposeOp([F.Decode(), transforms_auto_contrast = F.ComposeOp([F.Decode(),
F.Resize((224, 224)), F.Resize((224, 224)),
F.AutoContrast(), F.AutoContrast(cutoff=10.0, ignore=[10, 20]),
F.ToTensor()]) F.ToTensor()])
ds_auto_contrast = ds.map(input_columns="image", ds_auto_contrast = ds.map(input_columns="image",
@ -99,8 +99,8 @@ def test_auto_contrast_c(plot=False):
ds = ds.map(input_columns=["image"], ds = ds.map(input_columns=["image"],
operations=[C.Decode(), operations=[C.Decode(),
C.Resize((224, 224))]) C.Resize((224, 224))])
python_op = F.AutoContrast() python_op = F.AutoContrast(cutoff=10.0, ignore=[10, 20])
c_op = C.AutoContrast() c_op = C.AutoContrast(cutoff=10.0, ignore=[10, 20])
transforms_op = F.ComposeOp([lambda img: F.ToPIL()(img.astype(np.uint8)), transforms_op = F.ComposeOp([lambda img: F.ToPIL()(img.astype(np.uint8)),
python_op, python_op,
np.array])() np.array])()
@ -143,6 +143,10 @@ def test_auto_contrast_c(plot=False):
logger.info("MSE= {}".format(str(np.mean(mse)))) logger.info("MSE= {}".format(str(np.mean(mse))))
np.testing.assert_equal(np.mean(mse), 0.0) np.testing.assert_equal(np.mean(mse), 0.0)
# Compare with expected md5 from images
filename = "autcontrast_01_result_c.npz"
save_and_check_md5(ds_auto_contrast_c, filename, generate_golden=GENERATE_GOLDEN)
if plot: if plot:
visualize_list(images_auto_contrast_c, images_auto_contrast_py, visualize_mode=2) visualize_list(images_auto_contrast_c, images_auto_contrast_py, visualize_mode=2)
@ -209,11 +213,11 @@ def test_auto_contrast_one_channel_c(plot=False):
visualize_list(images_auto_contrast_c, images_auto_contrast_py, visualize_mode=2) visualize_list(images_auto_contrast_c, images_auto_contrast_py, visualize_mode=2)
def test_auto_contrast_invalid_input_c(): def test_auto_contrast_invalid_ignore_param_c():
""" """
Test AutoContrast C Op with invalid params Test AutoContrast C Op with invalid ignore parameter
""" """
logger.info("Test AutoContrast C Op with invalid params") logger.info("Test AutoContrast C Op with invalid ignore parameter")
try: try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False) ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"], ds = ds.map(input_columns=["image"],
@ -226,10 +230,110 @@ def test_auto_contrast_invalid_input_c():
except TypeError as error: except TypeError as error:
logger.info("Got an exception in DE: {}".format(str(error))) logger.info("Got an exception in DE: {}".format(str(error)))
assert "Argument ignore with value 255.5 is not of type" in str(error) assert "Argument ignore with value 255.5 is not of type" in str(error)
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[C.Decode(),
C.Resize((224, 224)),
lambda img: np.array(img[:, :, 0])])
# invalid ignore
ds = ds.map(input_columns="image",
operations=C.AutoContrast(ignore=(10, 100)))
except TypeError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Argument ignore with value (10,100) is not of type" in str(error)
def test_auto_contrast_invalid_cutoff_param_c():
"""
Test AutoContrast C Op with invalid cutoff parameter
"""
logger.info("Test AutoContrast C Op with invalid cutoff parameter")
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[C.Decode(),
C.Resize((224, 224)),
lambda img: np.array(img[:, :, 0])])
# invalid ignore
ds = ds.map(input_columns="image",
operations=C.AutoContrast(cutoff=-10.0))
except ValueError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Input cutoff is not within the required interval of (0 to 100)." in str(error)
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[C.Decode(),
C.Resize((224, 224)),
lambda img: np.array(img[:, :, 0])])
# invalid ignore
ds = ds.map(input_columns="image",
operations=C.AutoContrast(cutoff=120.0))
except ValueError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Input cutoff is not within the required interval of (0 to 100)." in str(error)
def test_auto_contrast_invalid_ignore_param_py():
"""
Test AutoContrast python Op with invalid ignore parameter
"""
logger.info("Test AutoContrast python Op with invalid ignore parameter")
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[F.ComposeOp([F.Decode(),
F.Resize((224, 224)),
F.AutoContrast(ignore=255.5),
F.ToTensor()])])
except TypeError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Argument ignore with value 255.5 is not of type" in str(error)
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[F.ComposeOp([F.Decode(),
F.Resize((224, 224)),
F.AutoContrast(ignore=(10, 100)),
F.ToTensor()])])
except TypeError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Argument ignore with value (10,100) is not of type" in str(error)
def test_auto_contrast_invalid_cutoff_param_py():
"""
Test AutoContrast python Op with invalid cutoff parameter
"""
logger.info("Test AutoContrast python Op with invalid cutoff parameter")
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[F.ComposeOp([F.Decode(),
F.Resize((224, 224)),
F.AutoContrast(cutoff=-10.0),
F.ToTensor()])])
except ValueError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Input cutoff is not within the required interval of (0 to 100)." in str(error)
try:
ds = de.ImageFolderDatasetV2(dataset_dir=DATA_DIR, shuffle=False)
ds = ds.map(input_columns=["image"],
operations=[F.ComposeOp([F.Decode(),
F.Resize((224, 224)),
F.AutoContrast(cutoff=120.0),
F.ToTensor()])])
except ValueError as error:
logger.info("Got an exception in DE: {}".format(str(error)))
assert "Input cutoff is not within the required interval of (0 to 100)." in str(error)
if __name__ == "__main__": if __name__ == "__main__":
test_auto_contrast_py(plot=True) test_auto_contrast_py(plot=True)
test_auto_contrast_c(plot=True) test_auto_contrast_c(plot=True)
test_auto_contrast_one_channel_c(plot=True) test_auto_contrast_one_channel_c(plot=True)
test_auto_contrast_invalid_input_c() test_auto_contrast_invalid_ignore_param_c()
test_auto_contrast_invalid_ignore_param_py()
test_auto_contrast_invalid_cutoff_param_c()
test_auto_contrast_invalid_cutoff_param_py()

@ -124,7 +124,7 @@ def test_cpp_uniform_augment(plot=False, num_ops=2):
C.RandomColorAdjust(), C.RandomColorAdjust(),
C.RandomRotation(degrees=45)] C.RandomRotation(degrees=45)]
uni_aug = C.UniformAugment(operations=transforms_ua, num_ops=num_ops) uni_aug = C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
transforms_all = [C.Decode(), C.Resize(size=[224, 224]), transforms_all = [C.Decode(), C.Resize(size=[224, 224]),
uni_aug, uni_aug,
@ -166,7 +166,7 @@ def test_cpp_uniform_augment_exception_pyops(num_ops=2):
F.Invert()] F.Invert()]
with pytest.raises(TypeError) as e: with pytest.raises(TypeError) as e:
C.UniformAugment(operations=transforms_ua, num_ops=num_ops) C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
logger.info("Got an exception in DE: {}".format(str(e))) logger.info("Got an exception in DE: {}".format(str(e)))
assert "Argument tensor_ops[5] with value" \ assert "Argument tensor_ops[5] with value" \
@ -187,7 +187,7 @@ def test_cpp_uniform_augment_exception_large_numops(num_ops=6):
C.RandomRotation(degrees=45)] C.RandomRotation(degrees=45)]
try: try:
_ = C.UniformAugment(operations=transforms_ua, num_ops=num_ops) _ = C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
except Exception as e: except Exception as e:
logger.info("Got an exception in DE: {}".format(str(e))) logger.info("Got an exception in DE: {}".format(str(e)))
@ -207,7 +207,7 @@ def test_cpp_uniform_augment_exception_nonpositive_numops(num_ops=0):
C.RandomRotation(degrees=45)] C.RandomRotation(degrees=45)]
try: try:
_ = C.UniformAugment(operations=transforms_ua, num_ops=num_ops) _ = C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
except Exception as e: except Exception as e:
logger.info("Got an exception in DE: {}".format(str(e))) logger.info("Got an exception in DE: {}".format(str(e)))
@ -227,7 +227,7 @@ def test_cpp_uniform_augment_exception_float_numops(num_ops=2.5):
C.RandomRotation(degrees=45)] C.RandomRotation(degrees=45)]
try: try:
_ = C.UniformAugment(operations=transforms_ua, num_ops=num_ops) _ = C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
except Exception as e: except Exception as e:
logger.info("Got an exception in DE: {}".format(str(e))) logger.info("Got an exception in DE: {}".format(str(e)))
@ -248,7 +248,7 @@ def test_cpp_uniform_augment_random_crop_badinput(num_ops=1):
C.RandomCrop(size=[224, 224]), C.RandomCrop(size=[224, 224]),
C.RandomHorizontalFlip() C.RandomHorizontalFlip()
] ]
uni_aug = C.UniformAugment(operations=transforms_ua, num_ops=num_ops) uni_aug = C.UniformAugment(transforms=transforms_ua, num_ops=num_ops)
ds1 = ds1.map(input_columns="image", operations=uni_aug) ds1 = ds1.map(input_columns="image", operations=uni_aug)
# apply DatasetOps # apply DatasetOps

Loading…
Cancel
Save