[MD] Transform Unification Feature - Phase 2C - legacy deprecated Python UT tests
This commit is contained in:
parent
351ce03fb2
commit
a275b8b267
|
@ -0,0 +1,15 @@
|
|||
# Copyright 2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ============================================================================
|
||||
"""Deprecated dataset tests for c_transforms.py and py_transforms.py"""
|
|
@ -0,0 +1,29 @@
|
|||
# Copyright 2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ============================================================================
|
||||
"""
|
||||
@File : conftest.py
|
||||
@Desc : common fixtures for pytest dataset_deprecated
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from mindspore.dataset.engine.iterators import _cleanup, _unset_iterator_cleanup
|
||||
|
||||
|
||||
@pytest.fixture(scope="function", autouse=True)
|
||||
def close_iterators():
|
||||
yield
|
||||
# Note: code after `yield` is teardown code
|
||||
_cleanup()
|
||||
_unset_iterator_cleanup()
|
|
@ -0,0 +1,365 @@
|
|||
# Copyright 2020-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
import mindspore.common.dtype as mstype
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.c_transforms as c_transforms
|
||||
import mindspore.dataset.transforms.py_transforms as py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
|
||||
from ..dataset.util import visualize_list, save_and_check_md5, config_get_set_seed, config_get_set_num_parallel_workers
|
||||
|
||||
GENERATE_GOLDEN = False
|
||||
|
||||
|
||||
def test_compose():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test C++ and Python Compose Op
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
original_seed = config_get_set_seed(0)
|
||||
|
||||
def test_config(arr, op_list):
|
||||
try:
|
||||
data = ds.NumpySlicesDataset(arr, column_names="col", shuffle=False)
|
||||
data = data.map(input_columns=["col"], operations=op_list)
|
||||
res = []
|
||||
for i in data.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
res.append(i["col"].tolist())
|
||||
return res
|
||||
except (TypeError, ValueError) as e:
|
||||
return str(e)
|
||||
|
||||
# Test simple compose with only 1 op, this would generate a warning
|
||||
assert test_config([[1, 0], [3, 4]], c_transforms.Compose([c_transforms.Fill(2)])) == [[2, 2], [2, 2]]
|
||||
|
||||
# Test 1 column -> 2 columns -> 1 -> 2 -> 1
|
||||
assert test_config([[1, 0]],
|
||||
c_transforms.Compose(
|
||||
[c_transforms.Duplicate(), c_transforms.Concatenate(), c_transforms.Duplicate(),
|
||||
c_transforms.Concatenate()])) \
|
||||
== [[1, 0] * 4]
|
||||
|
||||
# Test one Python transform followed by a C++ transform. Type after OneHot is a float (mixed use-case)
|
||||
assert test_config([1, 0],
|
||||
c_transforms.Compose([py_transforms.OneHotOp(2), c_transforms.TypeCast(mstype.int32)])) \
|
||||
== [[0, 1], [1, 0]]
|
||||
|
||||
# Test exceptions.
|
||||
with pytest.raises(TypeError) as error_info:
|
||||
c_transforms.Compose([1, c_transforms.TypeCast(mstype.int32)])
|
||||
assert "op_list[0] is neither a c_transform op (TensorOperation) nor a callable pyfunc." in str(error_info.value)
|
||||
|
||||
# Test empty op list
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
test_config([1, 0], c_transforms.Compose([]))
|
||||
assert "op_list can not be empty." in str(error_info.value)
|
||||
|
||||
# Test Python compose op
|
||||
assert test_config([1, 0], py_transforms.Compose([py_transforms.OneHotOp(2)])) == [[0, 1], [1, 0]]
|
||||
assert test_config([1, 0], py_transforms.Compose([py_transforms.OneHotOp(2), (lambda x: x + x)])) == [[0, 2],
|
||||
[2, 0]]
|
||||
|
||||
# Test nested Python compose op
|
||||
assert test_config([1, 0],
|
||||
py_transforms.Compose([py_transforms.Compose([py_transforms.OneHotOp(2)]), (lambda x: x + x)])) \
|
||||
== [[0, 2], [2, 0]]
|
||||
|
||||
# Test passing a list of Python ops without Compose wrapper
|
||||
assert test_config([1, 0],
|
||||
[py_transforms.Compose([py_transforms.OneHotOp(2)]), (lambda x: x + x)]) \
|
||||
== [[0, 2], [2, 0]]
|
||||
assert test_config([1, 0], [py_transforms.OneHotOp(2), (lambda x: x + x)]) == [[0, 2], [2, 0]]
|
||||
|
||||
# Test a non callable function
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
py_transforms.Compose([1])
|
||||
assert "transforms[0] is not callable." in str(error_info.value)
|
||||
|
||||
# Test empty Python op list
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
test_config([1, 0], py_transforms.Compose([]))
|
||||
assert "transforms list is empty." in str(error_info.value)
|
||||
|
||||
# Pass in extra brackets
|
||||
with pytest.raises(TypeError) as error_info:
|
||||
py_transforms.Compose([(lambda x: x + x)])()
|
||||
assert "Compose was called without an image. Fix invocation (avoid it being invoked as Compose([...])())." in str(
|
||||
error_info.value)
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
|
||||
|
||||
def test_lambdas():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test Multi Column Python Compose Op
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
original_seed = config_get_set_seed(0)
|
||||
|
||||
def test_config(arr, input_columns, output_columns, op_list):
|
||||
data = ds.NumpySlicesDataset(arr, column_names=input_columns, shuffle=False)
|
||||
data = data.map(operations=op_list, input_columns=input_columns, output_columns=output_columns,
|
||||
column_order=output_columns)
|
||||
res = []
|
||||
for i in data.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
for col_name in output_columns:
|
||||
res.append(i[col_name].tolist())
|
||||
return res
|
||||
|
||||
arr = ([[1]], [[3]])
|
||||
|
||||
assert test_config(arr, ["col0", "col1"], ["a"], py_transforms.Compose([(lambda x, y: x)])) == [[1]]
|
||||
assert test_config(arr, ["col0", "col1"], ["a"], py_transforms.Compose([lambda x, y: x, lambda x: x])) == [[1]]
|
||||
assert test_config(arr, ["col0", "col1"], ["a", "b"],
|
||||
py_transforms.Compose([lambda x, y: x, lambda x: (x, x * 2)])) == \
|
||||
[[1], [2]]
|
||||
assert test_config(arr, ["col0", "col1"], ["a", "b"],
|
||||
[lambda x, y: (x, x + y), lambda x, y: (x, y * 2)]) == [[1], [8]]
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
|
||||
|
||||
def test_c_py_compose_transforms_module():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test combining Python and C++ transforms
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
original_seed = config_get_set_seed(0)
|
||||
|
||||
def test_config(arr, input_columns, output_cols, op_list):
|
||||
data = ds.NumpySlicesDataset(arr, column_names=input_columns, shuffle=False)
|
||||
data = data.map(operations=op_list, input_columns=input_columns, output_columns=output_cols,
|
||||
column_order=output_cols)
|
||||
res = []
|
||||
for i in data.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
for col_name in output_cols:
|
||||
res.append(i[col_name].tolist())
|
||||
return res
|
||||
|
||||
arr = [1, 0]
|
||||
assert test_config(arr, ["cols"], ["cols"],
|
||||
[py_transforms.OneHotOp(2), c_transforms.Mask(c_transforms.Relational.EQ, 1)]) == \
|
||||
[[False, True],
|
||||
[True, False]]
|
||||
assert test_config(arr, ["cols"], ["cols"],
|
||||
[py_transforms.OneHotOp(2), (lambda x: x + x), c_transforms.Fill(1)]) \
|
||||
== [[1, 1], [1, 1]]
|
||||
assert test_config(arr, ["cols"], ["cols"],
|
||||
[py_transforms.OneHotOp(2), (lambda x: x + x), c_transforms.Fill(1), (lambda x: x + x)]) \
|
||||
== [[2, 2], [2, 2]]
|
||||
assert test_config([[1, 3]], ["cols"], ["cols"],
|
||||
[c_transforms.PadEnd([3], -1), (lambda x: x + x)]) \
|
||||
== [[2, 6, -2]]
|
||||
|
||||
arr = ([[1]], [[3]])
|
||||
assert test_config(arr, ["col0", "col1"], ["a"], [(lambda x, y: x + y), c_transforms.PadEnd([2], -1)]) == [[4, -1]]
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
|
||||
|
||||
def test_c_py_compose_vision_module(plot=False, run_golden=True):
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test combining Python and C++ vision transforms
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
original_seed = config_get_set_seed(10)
|
||||
original_num_parallel_workers = config_get_set_num_parallel_workers(1)
|
||||
|
||||
def test_config(plot, file_name, op_list):
|
||||
data_dir = "../data/dataset/testImageNetData/train/"
|
||||
data1 = ds.ImageFolderDataset(dataset_dir=data_dir, shuffle=False)
|
||||
data1 = data1.map(operations=op_list, input_columns=["image"])
|
||||
data2 = ds.ImageFolderDataset(dataset_dir=data_dir, shuffle=False)
|
||||
data2 = data2.map(operations=c_vision.Decode(), input_columns=["image"])
|
||||
original_images = []
|
||||
transformed_images = []
|
||||
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
transformed_images.append(item["image"])
|
||||
for item in data2.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
original_images.append(item["image"])
|
||||
|
||||
if run_golden:
|
||||
# Compare with expected md5 from images
|
||||
save_and_check_md5(data1, file_name, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
if plot:
|
||||
visualize_list(original_images, transformed_images)
|
||||
|
||||
test_config(op_list=[c_vision.Decode(),
|
||||
py_vision.ToPIL(),
|
||||
py_vision.Resize((224, 224)),
|
||||
np.array],
|
||||
plot=plot, file_name="compose_c_py_1.npz")
|
||||
|
||||
test_config(op_list=[c_vision.Decode(),
|
||||
c_vision.Resize((224, 244)),
|
||||
py_vision.ToPIL(),
|
||||
np.array,
|
||||
c_vision.Resize((24, 24))],
|
||||
plot=plot, file_name="compose_c_py_2.npz")
|
||||
|
||||
test_config(op_list=[py_vision.Decode(),
|
||||
py_vision.Resize((224, 224)),
|
||||
np.array,
|
||||
c_vision.RandomColor()],
|
||||
plot=plot, file_name="compose_c_py_3.npz")
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
ds.config.set_num_parallel_workers((original_num_parallel_workers))
|
||||
|
||||
|
||||
def test_py_transforms_with_c_vision():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test invalid scenarios since as c_transform should not be used in
|
||||
py_transforms.Random(Apply/Choice/Order)
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
original_seed = config_get_set_seed(0)
|
||||
|
||||
def test_config(op_list):
|
||||
data_dir = "../data/dataset/testImageNetData/train/"
|
||||
data = ds.ImageFolderDataset(dataset_dir=data_dir, shuffle=False)
|
||||
data = data.map(operations=op_list)
|
||||
res = []
|
||||
for i in data.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
for col_name in output_cols:
|
||||
res.append(i[col_name].tolist())
|
||||
return res
|
||||
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
test_config(py_transforms.RandomApply([c_vision.RandomResizedCrop(200)]))
|
||||
assert "transforms[0] is not a py transforms." in str(error_info.value)
|
||||
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
test_config(py_transforms.RandomChoice([c_vision.RandomResizedCrop(200)]))
|
||||
assert "transforms[0] is not a py transforms." in str(error_info.value)
|
||||
|
||||
with pytest.raises(ValueError) as error_info:
|
||||
test_config(py_transforms.RandomOrder([np.array, c_vision.RandomResizedCrop(200)]))
|
||||
assert "transforms[1] is not a py transforms." in str(error_info.value)
|
||||
|
||||
with pytest.raises(RuntimeError) as error_info:
|
||||
test_config([py_transforms.OneHotOp(20, 0.1)])
|
||||
assert "is smaller than the category number" in str(error_info.value)
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
|
||||
|
||||
def test_py_vision_with_c_transforms():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test combining Python vision operations with C++ transforms operations
|
||||
Expectation: Dataset pipeline runs successfully for valid input and results verified. Invalid input is detected.
|
||||
"""
|
||||
original_seed = config_get_set_seed(0)
|
||||
|
||||
def test_config(op_list):
|
||||
data_dir = "../data/dataset/testImageNetData/train/"
|
||||
data1 = ds.ImageFolderDataset(dataset_dir=data_dir, shuffle=False)
|
||||
data1 = data1.map(operations=op_list, input_columns=["image"])
|
||||
transformed_images = []
|
||||
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
transformed_images.append(item["image"])
|
||||
return transformed_images
|
||||
|
||||
# Test with Mask Op
|
||||
output_arr = test_config([py_vision.Decode(),
|
||||
py_vision.CenterCrop((2)), np.array,
|
||||
c_transforms.Mask(c_transforms.Relational.GE, 100)])
|
||||
|
||||
exp_arr = [np.array([[[True, False, False],
|
||||
[True, False, False]],
|
||||
[[True, False, False],
|
||||
[True, False, False]]]),
|
||||
np.array([[[True, False, False],
|
||||
[True, False, False]],
|
||||
[[True, False, False],
|
||||
[True, False, False]]])]
|
||||
|
||||
for exp_a, output in zip(exp_arr, output_arr):
|
||||
np.testing.assert_array_equal(exp_a, output)
|
||||
|
||||
# Test with Fill Op
|
||||
output_arr = test_config([py_vision.Decode(),
|
||||
py_vision.CenterCrop((4)), np.array,
|
||||
c_transforms.Fill(10)])
|
||||
|
||||
exp_arr = [np.ones((4, 4, 3)) * 10] * 2
|
||||
for exp_a, output in zip(exp_arr, output_arr):
|
||||
np.testing.assert_array_equal(exp_a, output)
|
||||
|
||||
# Test with Concatenate Op, which will raise an error since ConcatenateOp only supports rank 1 tensors.
|
||||
with pytest.raises(RuntimeError) as error_info:
|
||||
test_config([py_vision.Decode(),
|
||||
py_vision.CenterCrop((2)), np.array,
|
||||
c_transforms.Concatenate(0)])
|
||||
assert "only 1D input supported" in str(error_info.value)
|
||||
|
||||
# Restore configuration
|
||||
ds.config.set_seed(original_seed)
|
||||
|
||||
|
||||
def test_compose_with_custom_function():
|
||||
"""
|
||||
Feature: Compose Op
|
||||
Description: Test Python Compose with custom function
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
|
||||
def custom_function(x):
|
||||
return (x, x * x)
|
||||
|
||||
# First dataset
|
||||
op_list = [
|
||||
lambda x: x * 3,
|
||||
custom_function,
|
||||
# convert two column output to one
|
||||
lambda *images: np.stack(images)
|
||||
]
|
||||
|
||||
data = ds.NumpySlicesDataset([[1, 2]], column_names=["col0"], shuffle=False)
|
||||
data = data.map(input_columns=["col0"], operations=op_list)
|
||||
#
|
||||
|
||||
res = []
|
||||
for i in data.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
res.append(i["col0"].tolist())
|
||||
assert res == [[[3, 6], [9, 36]]]
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_compose()
|
||||
test_lambdas()
|
||||
test_c_py_compose_transforms_module()
|
||||
test_c_py_compose_vision_module(plot=True)
|
||||
test_py_transforms_with_c_vision()
|
||||
test_py_vision_with_c_transforms()
|
||||
test_compose_with_custom_function()
|
|
@ -0,0 +1,226 @@
|
|||
# Copyright 2019-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing CutOut op in DE
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as c
|
||||
import mindspore.dataset.vision.py_transforms as f
|
||||
from mindspore import log as logger
|
||||
from ..dataset.util import visualize_image, visualize_list, diff_mse, save_and_check_md5, \
|
||||
config_get_set_seed, config_get_set_num_parallel_workers
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
GENERATE_GOLDEN = False
|
||||
|
||||
|
||||
def test_cut_out_op(plot=False):
|
||||
"""
|
||||
Feature: CutOut Op
|
||||
Description: Test CutOut C++ op
|
||||
Expectation: Dataset pipeline runs successfully and results are verified against RandomErasing Op
|
||||
"""
|
||||
logger.info("test_cut_out")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
|
||||
transforms_1 = [
|
||||
f.Decode(),
|
||||
f.ToTensor(),
|
||||
f.RandomErasing(value='random')
|
||||
]
|
||||
transform_1 = mindspore.dataset.transforms.py_transforms.Compose(transforms_1)
|
||||
data1 = data1.map(operations=transform_1, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
decode_op = c.Decode()
|
||||
cut_out_op = c.CutOut(80)
|
||||
|
||||
transforms_2 = [
|
||||
decode_op,
|
||||
cut_out_op
|
||||
]
|
||||
|
||||
data2 = data2.map(operations=transforms_2, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
num_iter += 1
|
||||
image_1 = (item1["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
# C image doesn't require transpose
|
||||
image_2 = item2["image"]
|
||||
|
||||
logger.info("shape of image_1: {}".format(image_1.shape))
|
||||
logger.info("shape of image_2: {}".format(image_2.shape))
|
||||
|
||||
logger.info("dtype of image_1: {}".format(image_1.dtype))
|
||||
logger.info("dtype of image_2: {}".format(image_2.dtype))
|
||||
|
||||
mse = diff_mse(image_1, image_2)
|
||||
if plot:
|
||||
visualize_image(image_1, image_2, mse)
|
||||
|
||||
|
||||
def test_cut_out_op_multicut(plot=False):
|
||||
"""
|
||||
Feature: CutOut Op
|
||||
Description: Test CutOut o with multiple patches
|
||||
Expectation: Dataset pipeline runs successfully and results are visually verified
|
||||
"""
|
||||
logger.info("test_cut_out")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
|
||||
transforms_1 = [
|
||||
f.Decode(),
|
||||
f.ToTensor(),
|
||||
]
|
||||
transform_1 = mindspore.dataset.transforms.py_transforms.Compose(transforms_1)
|
||||
data1 = data1.map(operations=transform_1, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
decode_op = c.Decode()
|
||||
cut_out_op = c.CutOut(80, num_patches=10)
|
||||
|
||||
transforms_2 = [
|
||||
decode_op,
|
||||
cut_out_op
|
||||
]
|
||||
|
||||
data2 = data2.map(operations=transforms_2, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
image_list_1, image_list_2 = [], []
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
num_iter += 1
|
||||
image_1 = (item1["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
# C image doesn't require transpose
|
||||
image_2 = item2["image"]
|
||||
image_list_1.append(image_1)
|
||||
image_list_2.append(image_2)
|
||||
|
||||
logger.info("shape of image_1: {}".format(image_1.shape))
|
||||
logger.info("shape of image_2: {}".format(image_2.shape))
|
||||
|
||||
logger.info("dtype of image_1: {}".format(image_1.dtype))
|
||||
logger.info("dtype of image_2: {}".format(image_2.dtype))
|
||||
if plot:
|
||||
visualize_list(image_list_1, image_list_2)
|
||||
|
||||
|
||||
def test_cut_out_md5():
|
||||
"""
|
||||
Feature: CutOut Op
|
||||
Description: Test CutOut C++ op and Cutout Py op with md5 check
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("test_cut_out_md5")
|
||||
original_seed = config_get_set_seed(2)
|
||||
original_num_parallel_workers = config_get_set_num_parallel_workers(1)
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
decode_op = c.Decode()
|
||||
cut_out_op = c.CutOut(100)
|
||||
data1 = data1.map(operations=decode_op, input_columns=["image"])
|
||||
data1 = data1.map(operations=cut_out_op, input_columns=["image"])
|
||||
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
transforms = [
|
||||
f.Decode(),
|
||||
f.ToTensor(),
|
||||
f.Cutout(100)
|
||||
]
|
||||
transform = mindspore.dataset.transforms.py_transforms.Compose(transforms)
|
||||
data2 = data2.map(operations=transform, input_columns=["image"])
|
||||
|
||||
# Compare with expected md5 from images
|
||||
filename1 = "cut_out_01_c_result.npz"
|
||||
save_and_check_md5(data1, filename1, generate_golden=GENERATE_GOLDEN)
|
||||
filename2 = "cut_out_01_py_result.npz"
|
||||
save_and_check_md5(data2, filename2, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
# Restore config
|
||||
ds.config.set_seed(original_seed)
|
||||
ds.config.set_num_parallel_workers(original_num_parallel_workers)
|
||||
|
||||
|
||||
def test_cut_out_comp(plot=False):
|
||||
"""
|
||||
Feature: CutOut Op
|
||||
Description: Test Test CutOut C++ op and Cutout Py op
|
||||
Expectation: Dataset pipeline runs successfully and results are visually verified
|
||||
"""
|
||||
logger.info("test_cut_out_comp")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
|
||||
transforms_1 = [
|
||||
f.Decode(),
|
||||
f.ToTensor(),
|
||||
f.Cutout(200)
|
||||
]
|
||||
transform_1 = mindspore.dataset.transforms.py_transforms.Compose(transforms_1)
|
||||
data1 = data1.map(operations=transform_1, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
|
||||
transforms_2 = [
|
||||
c.Decode(),
|
||||
c.CutOut(200)
|
||||
]
|
||||
|
||||
data2 = data2.map(operations=transforms_2, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
image_list_1, image_list_2 = [], []
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
num_iter += 1
|
||||
image_1 = (item1["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
# C image doesn't require transpose
|
||||
image_2 = item2["image"]
|
||||
|
||||
logger.info("shape of image_1: {}".format(image_1.shape))
|
||||
logger.info("shape of image_2: {}".format(image_2.shape))
|
||||
|
||||
logger.info("dtype of image_1: {}".format(image_1.dtype))
|
||||
logger.info("dtype of image_2: {}".format(image_2.dtype))
|
||||
|
||||
image_list_1.append(image_1)
|
||||
image_list_2.append(image_2)
|
||||
|
||||
if plot:
|
||||
visualize_list(image_list_1, image_list_2, visualize_mode=2)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_cut_out_op(plot=True)
|
||||
test_cut_out_op_multicut(plot=True)
|
||||
test_cut_out_md5()
|
||||
test_cut_out_comp(plot=True)
|
|
@ -0,0 +1,338 @@
|
|||
# Copyright 2020-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
import cv2
|
||||
import numpy as np
|
||||
import pytest
|
||||
from PIL import Image
|
||||
import mindspore.dataset.vision.c_transforms as C
|
||||
import mindspore.dataset.vision.py_transforms as PY
|
||||
from mindspore import log as logger
|
||||
|
||||
|
||||
def test_eager_decode_c():
|
||||
"""
|
||||
Feature: Decode op
|
||||
Description: Test eager support for Decode C++ op
|
||||
Expectation: Output image size from op is correct
|
||||
"""
|
||||
img = np.fromfile("../data/dataset/apple.jpg", dtype=np.uint8)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
|
||||
img = C.Decode()(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
assert img.shape == (2268, 4032, 3)
|
||||
|
||||
fp = open("../data/dataset/apple.jpg", "rb")
|
||||
img2 = fp.read()
|
||||
|
||||
img2 = C.Decode()(img2)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img2), img2.shape))
|
||||
assert img2.shape == (2268, 4032, 3)
|
||||
|
||||
|
||||
def test_eager_decode_py():
|
||||
"""
|
||||
Feature: Decode op
|
||||
Description: Test eager support for Decode Python op
|
||||
Expectation: Output image size from op is correct
|
||||
"""
|
||||
img = np.fromfile("../data/dataset/apple.jpg", dtype=np.uint8)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = PY.Decode()(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
assert img.size == (4032, 2268)
|
||||
|
||||
fp = open("../data/dataset/apple.jpg", "rb")
|
||||
img2 = fp.read()
|
||||
|
||||
img2 = PY.Decode()(img2)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img2), img2.size))
|
||||
assert img2.size == (4032, 2268)
|
||||
|
||||
|
||||
def test_eager_resize():
|
||||
"""
|
||||
Feature: Resize op
|
||||
Description: Test eager support for Resize C++ op
|
||||
Expectation: Output image info from op is correct
|
||||
"""
|
||||
img = cv2.imread("../data/dataset/apple.jpg")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
|
||||
img = C.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
|
||||
assert img.shape == (32, 32, 3)
|
||||
|
||||
|
||||
def test_eager_rescale():
|
||||
"""
|
||||
Feature: Rescale op
|
||||
Description: Test eager support for Rescale C++ op
|
||||
Expectation: Output image info from op is correct
|
||||
"""
|
||||
img = cv2.imread("../data/dataset/apple.jpg")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
pixel = img[0][0][0]
|
||||
|
||||
rescale_factor = 0.5
|
||||
img = C.Rescale(rescale=rescale_factor, shift=0)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
pixel_rescaled = img[0][0][0]
|
||||
|
||||
assert pixel * rescale_factor == pixel_rescaled
|
||||
|
||||
|
||||
def test_eager_normalize_c():
|
||||
"""
|
||||
Feature: Normalize op
|
||||
Description: Test eager support for Normalize C++ op
|
||||
Expectation: Output image info from op is correct
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
pixel = img.getpixel((0, 0))[0]
|
||||
|
||||
mean_vec = [100, 100, 100]
|
||||
std_vec = [2, 2, 2]
|
||||
img = C.Normalize(mean=mean_vec, std=std_vec)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
pixel_normalized = img[0][0][0]
|
||||
|
||||
assert (pixel - mean_vec[0]) / std_vec[0] == pixel_normalized
|
||||
|
||||
|
||||
def test_eager_normalize_py():
|
||||
"""
|
||||
Feature: Normalize op
|
||||
Description: Test eager support for Normalize Python op
|
||||
Expectation: Output image info from op is correct
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
pixel = img.getpixel((0, 0))[0]
|
||||
|
||||
img = PY.ToTensor()(img)
|
||||
|
||||
mean_vec = [.100, .100, .100]
|
||||
std_vec = [.2, .2, .2]
|
||||
img = PY.Normalize(mean=mean_vec, std=std_vec)(img)
|
||||
pixel_normalized = img[0][0][0]
|
||||
|
||||
assert (pixel / 255 - mean_vec[0]) / std_vec[0] == pytest.approx(pixel_normalized, 0.0001)
|
||||
|
||||
|
||||
def test_eager_hwc2chw():
|
||||
"""
|
||||
Feature: HWC2CHW op
|
||||
Description: Test eager support for HWC2CHW C++ op
|
||||
Expectation: Output image info from op is correct
|
||||
"""
|
||||
img = cv2.imread("../data/dataset/apple.jpg")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
channel = img.shape
|
||||
|
||||
img = C.HWC2CHW()(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
channel_swaped = img.shape
|
||||
|
||||
assert channel == (channel_swaped[1], channel_swaped[2], channel_swaped[0])
|
||||
|
||||
|
||||
def test_eager_pad_c():
|
||||
"""
|
||||
Feature: Pad op
|
||||
Description: Test eager support for Pad C++ op
|
||||
Expectation: Output image size info from op is correct
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = C.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size = img.shape
|
||||
|
||||
pad = 4
|
||||
img = C.Pad(padding=pad)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size_padded = img.shape
|
||||
|
||||
assert size_padded == (size[0] + 2 * pad, size[1] + 2 * pad, size[2])
|
||||
|
||||
|
||||
def test_eager_pad_py():
|
||||
"""
|
||||
Feature: Pad op
|
||||
Description: Test eager support for Pad Python op
|
||||
Expectation: Output image size info from op is correct
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = PY.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size = img.size
|
||||
|
||||
pad = 4
|
||||
img = PY.Pad(padding=pad)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size_padded = img.size
|
||||
|
||||
assert size_padded == (size[0] + 2 * pad, size[1] + 2 * pad)
|
||||
|
||||
|
||||
def test_eager_cutout_pil_c():
|
||||
"""
|
||||
Feature: CutOut op
|
||||
Description: Test eager support for CutOut C++ op with PIL input
|
||||
Expectation: Output image size info from op is correct
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = C.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size = img.shape
|
||||
|
||||
img = C.CutOut(2, 4)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size_cutout = img.shape
|
||||
|
||||
assert size_cutout == size
|
||||
|
||||
|
||||
def test_eager_cutout_pil_py():
|
||||
"""
|
||||
Feature: CutOut op
|
||||
Description: Test eager support for CutOut Python op with PIL input
|
||||
Expectation: Receive non-None output image from op
|
||||
"""
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = PY.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = PY.ToTensor()(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = PY.Cutout(2, 4)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
assert img is not None
|
||||
|
||||
|
||||
def test_eager_cutout_cv_c():
|
||||
"""
|
||||
Feature: CutOut op
|
||||
Description: Test eager support for CutOut C++ op with CV input
|
||||
Expectation: Output image size info from op is correct
|
||||
"""
|
||||
img = cv2.imread("../data/dataset/apple.jpg")
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
|
||||
img = C.Resize(size=(32, 32))(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size = img.shape
|
||||
|
||||
img = C.CutOut(2, 4)(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.size))
|
||||
size_cutout = img.shape
|
||||
|
||||
assert size_cutout == size
|
||||
|
||||
|
||||
def test_eager_exceptions():
|
||||
"""
|
||||
Feature: Eager Support
|
||||
Description: Exception eager support test for various vision C++ ops
|
||||
Expectation: Error input image is detected
|
||||
"""
|
||||
try:
|
||||
img = "../data/dataset/apple.jpg"
|
||||
_ = C.Decode()(img)
|
||||
assert False
|
||||
except TypeError as e:
|
||||
assert "Input should be an encoded image in 1-D NumPy format" in str(e)
|
||||
|
||||
try:
|
||||
img = np.array(["a", "b", "c"])
|
||||
_ = C.Decode()(img)
|
||||
assert False
|
||||
except TypeError as e:
|
||||
assert "Input should be an encoded image in 1-D NumPy format" in str(e)
|
||||
|
||||
try:
|
||||
img = cv2.imread("../data/dataset/apple.jpg")
|
||||
_ = C.Resize(size=(-32, 32))(img)
|
||||
assert False
|
||||
except ValueError as e:
|
||||
assert "not within the required interval" in str(e)
|
||||
|
||||
try:
|
||||
img = "../data/dataset/apple.jpg"
|
||||
_ = C.Pad(padding=4)(img)
|
||||
assert False
|
||||
except TypeError as e:
|
||||
assert "Input should be NumPy or PIL image" in str(e)
|
||||
|
||||
|
||||
def test_eager_exceptions_normalize():
|
||||
"""
|
||||
Feature: Normalize op
|
||||
Description: Exception eager support test for Normalize Python op
|
||||
Expectation: Error input image is detected
|
||||
"""
|
||||
try:
|
||||
img = Image.open("../data/dataset/apple.jpg").convert("RGB")
|
||||
mean_vec = [.100, .100, .100]
|
||||
std_vec = [.2, .2, .2]
|
||||
_ = PY.Normalize(mean=mean_vec, std=std_vec)(img)
|
||||
assert False
|
||||
except TypeError as e:
|
||||
assert "img should be NumPy image" in str(e)
|
||||
|
||||
|
||||
def test_eager_exceptions_pad():
|
||||
"""
|
||||
Feature: Pad op
|
||||
Description: Exception eager support test for Pad Python op
|
||||
Expectation: Error input image is detected
|
||||
"""
|
||||
try:
|
||||
img = "../data/dataset/apple.jpg"
|
||||
_ = PY.Pad(padding=4)(img)
|
||||
assert False
|
||||
except TypeError as e:
|
||||
assert "img should be PIL image" in str(e)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_eager_decode_c()
|
||||
test_eager_decode_py()
|
||||
test_eager_resize()
|
||||
test_eager_rescale()
|
||||
test_eager_normalize_c()
|
||||
test_eager_normalize_py()
|
||||
test_eager_hwc2chw()
|
||||
test_eager_pad_c()
|
||||
test_eager_pad_py()
|
||||
test_eager_cutout_pil_c()
|
||||
test_eager_cutout_pil_py()
|
||||
test_eager_cutout_cv_c()
|
||||
test_eager_exceptions()
|
||||
test_eager_exceptions_normalize()
|
||||
test_eager_exceptions_pad()
|
|
@ -0,0 +1,315 @@
|
|||
# Copyright 2020-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing Equalize op in DE
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as C
|
||||
import mindspore.dataset.vision.py_transforms as F
|
||||
from mindspore import log as logger
|
||||
from ..dataset.util import visualize_list, visualize_one_channel_dataset, diff_mse, save_and_check_md5
|
||||
|
||||
DATA_DIR = "../data/dataset/testImageNetData/train/"
|
||||
MNIST_DATA_DIR = "../data/dataset/testMnistData"
|
||||
|
||||
GENERATE_GOLDEN = False
|
||||
|
||||
|
||||
def test_equalize_callable():
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test op in eager mode
|
||||
Expectation: Output image shape from op is verified
|
||||
"""
|
||||
logger.info("Test Equalize callable")
|
||||
img = np.fromfile("../data/dataset/apple.jpg", dtype=np.uint8)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
|
||||
img = C.Decode()(img)
|
||||
img = C.Equalize()(img)
|
||||
logger.info("Image.type: {}, Image.shape: {}".format(type(img), img.shape))
|
||||
|
||||
assert img.shape == (2268, 4032, 3)
|
||||
|
||||
|
||||
def test_equalize_py(plot=False):
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test Python op
|
||||
Expectation: Dataset pipeline runs successfully and results are visually verified
|
||||
"""
|
||||
logger.info("Test Equalize")
|
||||
|
||||
# Original Images
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
|
||||
transforms_original = mindspore.dataset.transforms.py_transforms.Compose([F.Decode(),
|
||||
F.Resize((224, 224)),
|
||||
F.ToTensor()])
|
||||
|
||||
ds_original = data_set.map(operations=transforms_original, input_columns="image")
|
||||
|
||||
ds_original = ds_original.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_original):
|
||||
if idx == 0:
|
||||
images_original = np.transpose(image.asnumpy(), (0, 2, 3, 1))
|
||||
else:
|
||||
images_original = np.append(images_original,
|
||||
np.transpose(image.asnumpy(), (0, 2, 3, 1)),
|
||||
axis=0)
|
||||
|
||||
# Color Equalized Images
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
|
||||
transforms_equalize = mindspore.dataset.transforms.py_transforms.Compose([F.Decode(),
|
||||
F.Resize((224, 224)),
|
||||
F.Equalize(),
|
||||
F.ToTensor()])
|
||||
|
||||
ds_equalize = data_set.map(operations=transforms_equalize, input_columns="image")
|
||||
|
||||
ds_equalize = ds_equalize.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_equalize):
|
||||
if idx == 0:
|
||||
images_equalize = np.transpose(image.asnumpy(), (0, 2, 3, 1))
|
||||
else:
|
||||
images_equalize = np.append(images_equalize,
|
||||
np.transpose(image.asnumpy(), (0, 2, 3, 1)),
|
||||
axis=0)
|
||||
|
||||
num_samples = images_original.shape[0]
|
||||
mse = np.zeros(num_samples)
|
||||
for i in range(num_samples):
|
||||
mse[i] = diff_mse(images_equalize[i], images_original[i])
|
||||
logger.info("MSE= {}".format(str(np.mean(mse))))
|
||||
|
||||
if plot:
|
||||
visualize_list(images_original, images_equalize)
|
||||
|
||||
|
||||
def test_equalize_c(plot=False):
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test C++ op
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test Equalize cpp op")
|
||||
|
||||
# Original Images
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
|
||||
transforms_original = [C.Decode(), C.Resize(size=[224, 224])]
|
||||
|
||||
ds_original = data_set.map(operations=transforms_original, input_columns="image")
|
||||
|
||||
ds_original = ds_original.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_original):
|
||||
if idx == 0:
|
||||
images_original = image.asnumpy()
|
||||
else:
|
||||
images_original = np.append(images_original,
|
||||
image.asnumpy(),
|
||||
axis=0)
|
||||
|
||||
# Equalize Images
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
|
||||
transform_equalize = [C.Decode(), C.Resize(size=[224, 224]),
|
||||
C.Equalize()]
|
||||
|
||||
ds_equalize = data_set.map(operations=transform_equalize, input_columns="image")
|
||||
|
||||
ds_equalize = ds_equalize.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_equalize):
|
||||
if idx == 0:
|
||||
images_equalize = image.asnumpy()
|
||||
else:
|
||||
images_equalize = np.append(images_equalize,
|
||||
image.asnumpy(),
|
||||
axis=0)
|
||||
if plot:
|
||||
visualize_list(images_original, images_equalize)
|
||||
|
||||
num_samples = images_original.shape[0]
|
||||
mse = np.zeros(num_samples)
|
||||
for i in range(num_samples):
|
||||
mse[i] = diff_mse(images_equalize[i], images_original[i])
|
||||
logger.info("MSE= {}".format(str(np.mean(mse))))
|
||||
|
||||
|
||||
def test_equalize_py_c(plot=False):
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test C++ op and Python op
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test Equalize cpp and python op")
|
||||
|
||||
# equalize Images in cpp
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
data_set = data_set.map(operations=[C.Decode(), C.Resize((224, 224))], input_columns=["image"])
|
||||
|
||||
ds_c_equalize = data_set.map(operations=C.Equalize(), input_columns="image")
|
||||
|
||||
ds_c_equalize = ds_c_equalize.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_c_equalize):
|
||||
if idx == 0:
|
||||
images_c_equalize = image.asnumpy()
|
||||
else:
|
||||
images_c_equalize = np.append(images_c_equalize,
|
||||
image.asnumpy(),
|
||||
axis=0)
|
||||
|
||||
# Equalize images in python
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
data_set = data_set.map(operations=[C.Decode(), C.Resize((224, 224))], input_columns=["image"])
|
||||
|
||||
transforms_p_equalize = mindspore.dataset.transforms.py_transforms.Compose([lambda img: img.astype(np.uint8),
|
||||
F.ToPIL(),
|
||||
F.Equalize(),
|
||||
np.array])
|
||||
|
||||
ds_p_equalize = data_set.map(operations=transforms_p_equalize, input_columns="image")
|
||||
|
||||
ds_p_equalize = ds_p_equalize.batch(512)
|
||||
|
||||
for idx, (image, _) in enumerate(ds_p_equalize):
|
||||
if idx == 0:
|
||||
images_p_equalize = image.asnumpy()
|
||||
else:
|
||||
images_p_equalize = np.append(images_p_equalize,
|
||||
image.asnumpy(),
|
||||
axis=0)
|
||||
|
||||
num_samples = images_c_equalize.shape[0]
|
||||
mse = np.zeros(num_samples)
|
||||
for i in range(num_samples):
|
||||
mse[i] = diff_mse(images_p_equalize[i], images_c_equalize[i])
|
||||
logger.info("MSE= {}".format(str(np.mean(mse))))
|
||||
|
||||
if plot:
|
||||
visualize_list(images_c_equalize, images_p_equalize, visualize_mode=2)
|
||||
|
||||
|
||||
def test_equalize_one_channel():
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test Equalize cpp op with one channel images
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("Test Equalize C++ op With One Channel Images")
|
||||
|
||||
c_op = C.Equalize()
|
||||
|
||||
try:
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
data_set = data_set.map(operations=[C.Decode(), C.Resize((224, 224)),
|
||||
lambda img: np.array(img[:, :, 0])], input_columns=["image"])
|
||||
|
||||
data_set.map(operations=c_op, input_columns="image")
|
||||
|
||||
except RuntimeError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "The shape" in str(e)
|
||||
|
||||
|
||||
def test_equalize_mnist_c(plot=False):
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test Equalize C++ op with MNIST dataset (Grayscale images)
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("Test Equalize C++ op With MNIST Images")
|
||||
data_set = ds.MnistDataset(dataset_dir=MNIST_DATA_DIR, num_samples=2, shuffle=False)
|
||||
ds_equalize_c = data_set.map(operations=C.Equalize(), input_columns="image")
|
||||
ds_orig = ds.MnistDataset(dataset_dir=MNIST_DATA_DIR, num_samples=2, shuffle=False)
|
||||
|
||||
images = []
|
||||
images_trans = []
|
||||
labels = []
|
||||
for _, (data_orig, data_trans) in enumerate(zip(ds_orig, ds_equalize_c)):
|
||||
image_orig, label_orig = data_orig
|
||||
image_trans, _ = data_trans
|
||||
images.append(image_orig.asnumpy())
|
||||
labels.append(label_orig.asnumpy())
|
||||
images_trans.append(image_trans.asnumpy())
|
||||
|
||||
# Compare with expected md5 from images
|
||||
filename = "equalize_mnist_result_c.npz"
|
||||
save_and_check_md5(ds_equalize_c, filename, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
if plot:
|
||||
visualize_one_channel_dataset(images, images_trans, labels)
|
||||
|
||||
|
||||
def test_equalize_md5_py():
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test Python op with md5 check
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("Test Equalize")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
transforms = mindspore.dataset.transforms.py_transforms.Compose([F.Decode(),
|
||||
F.Equalize(),
|
||||
F.ToTensor()])
|
||||
|
||||
data1 = data1.map(operations=transforms, input_columns="image")
|
||||
# Compare with expected md5 from images
|
||||
filename = "equalize_01_result.npz"
|
||||
save_and_check_md5(data1, filename, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
def test_equalize_md5_c():
|
||||
"""
|
||||
Feature: Equalize Op
|
||||
Description: Test C++ op with md5 check
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("Test Equalize cpp op with md5 check")
|
||||
|
||||
# Generate dataset
|
||||
data_set = ds.ImageFolderDataset(dataset_dir=DATA_DIR, shuffle=False)
|
||||
|
||||
transforms_equalize = [C.Decode(),
|
||||
C.Resize(size=[224, 224]),
|
||||
C.Equalize(),
|
||||
F.ToTensor()]
|
||||
|
||||
data = data_set.map(operations=transforms_equalize, input_columns="image")
|
||||
# Compare with expected md5 from images
|
||||
filename = "equalize_01_result_c.npz"
|
||||
save_and_check_md5(data, filename, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_equalize_callable()
|
||||
test_equalize_py(plot=False)
|
||||
test_equalize_c(plot=False)
|
||||
test_equalize_py_c(plot=False)
|
||||
test_equalize_mnist_c(plot=True)
|
||||
test_equalize_one_channel()
|
||||
test_equalize_md5_py()
|
||||
test_equalize_md5_c()
|
|
@ -0,0 +1,125 @@
|
|||
# Copyright 2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
import pytest
|
||||
import mindspore.dataset as ds
|
||||
from mindspore.dataset.transforms import c_transforms
|
||||
from mindspore.dataset.transforms import py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
|
||||
DATA_DIR = "../data/dataset/testPK/data"
|
||||
|
||||
|
||||
def test_map_c_transform_exception():
|
||||
"""
|
||||
Feature: test c error op def
|
||||
Description: op defined like c_vision.HWC2CHW
|
||||
Expectation: success
|
||||
"""
|
||||
data_set = ds.ImageFolderDataset(DATA_DIR, num_parallel_workers=1, shuffle=True)
|
||||
|
||||
train_image_size = 224
|
||||
mean = [0.485 * 255, 0.456 * 255, 0.406 * 255]
|
||||
std = [0.229 * 255, 0.224 * 255, 0.225 * 255]
|
||||
|
||||
# define map operations
|
||||
random_crop_decode_resize_op = c_vision.RandomCropDecodeResize(train_image_size,
|
||||
scale=(0.08, 1.0),
|
||||
ratio=(0.75, 1.333))
|
||||
random_horizontal_flip_op = c_vision.RandomHorizontalFlip(prob=0.5)
|
||||
normalize_op = c_vision.Normalize(mean=mean, std=std)
|
||||
hwc2chw_op = c_vision.HWC2CHW # exception
|
||||
|
||||
data_set = data_set.map(operations=random_crop_decode_resize_op, input_columns="image", num_parallel_workers=1)
|
||||
data_set = data_set.map(operations=random_horizontal_flip_op, input_columns="image", num_parallel_workers=1)
|
||||
data_set = data_set.map(operations=normalize_op, input_columns="image", num_parallel_workers=1)
|
||||
with pytest.raises(ValueError) as info:
|
||||
data_set = data_set.map(operations=hwc2chw_op, input_columns="image", num_parallel_workers=1)
|
||||
assert "Parameter operations's element of method map should be a " in str(info.value)
|
||||
|
||||
# compose exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
c_transforms.Compose([
|
||||
c_vision.RandomCropDecodeResize(train_image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
|
||||
c_vision.RandomHorizontalFlip,
|
||||
c_vision.Normalize(mean=mean, std=std),
|
||||
c_vision.HWC2CHW()])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
# randomapply exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
c_transforms.RandomApply([
|
||||
c_vision.RandomCropDecodeResize,
|
||||
c_vision.RandomHorizontalFlip(prob=0.5),
|
||||
c_vision.Normalize(mean=mean, std=std),
|
||||
c_vision.HWC2CHW()])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
# randomchoice exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
c_transforms.RandomChoice([
|
||||
c_vision.RandomCropDecodeResize(train_image_size, scale=(0.08, 1.0), ratio=(0.75, 1.333)),
|
||||
c_vision.RandomHorizontalFlip(prob=0.5),
|
||||
c_vision.Normalize,
|
||||
c_vision.HWC2CHW()])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
|
||||
def test_map_py_transform_exception():
|
||||
"""
|
||||
Feature: test python error op def
|
||||
Description: op defined like py_vision.RandomHorizontalFlip
|
||||
Expectation: success
|
||||
"""
|
||||
data_set = ds.ImageFolderDataset(DATA_DIR, num_parallel_workers=1, shuffle=True)
|
||||
|
||||
# define map operations
|
||||
decode_op = py_vision.Decode()
|
||||
random_horizontal_flip_op = py_vision.RandomHorizontalFlip # exception
|
||||
to_tensor_op = py_vision.ToTensor()
|
||||
trans = [decode_op, random_horizontal_flip_op, to_tensor_op]
|
||||
|
||||
with pytest.raises(ValueError) as info:
|
||||
data_set = data_set.map(operations=trans, input_columns="image", num_parallel_workers=1)
|
||||
assert "Parameter operations's element of method map should be a " in str(info.value)
|
||||
|
||||
# compose exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
py_transforms.Compose([
|
||||
py_vision.Decode,
|
||||
py_vision.RandomHorizontalFlip(),
|
||||
py_vision.ToTensor()])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
# randomapply exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
py_transforms.RandomApply([
|
||||
py_vision.Decode(),
|
||||
py_vision.RandomHorizontalFlip,
|
||||
py_vision.ToTensor()])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
# randomchoice exception
|
||||
with pytest.raises(ValueError) as info:
|
||||
py_transforms.RandomChoice([
|
||||
py_vision.Decode(),
|
||||
py_vision.RandomHorizontalFlip(),
|
||||
py_vision.ToTensor])
|
||||
assert " should be a " in str(info.value)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_map_c_transform_exception()
|
||||
test_map_py_transform_exception()
|
|
@ -0,0 +1,171 @@
|
|||
# Copyright 2019-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
import numpy as np
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.c_transforms as c
|
||||
import mindspore.dataset.transforms.py_transforms as f
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
from mindspore import log as logger
|
||||
|
||||
DATA_DIR = "../data/dataset/testImageNetData/train"
|
||||
DATA_DIR_2 = "../data/dataset/testImageNetData2/train"
|
||||
|
||||
|
||||
def test_one_hot_op():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test Python op, one hot encoding with smoothing_rate
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
|
||||
logger.info("Test one hot encoding op")
|
||||
|
||||
# define map operations
|
||||
dataset = ds.ImageFolderDataset(DATA_DIR)
|
||||
num_classes = 2
|
||||
epsilon_para = 0.1
|
||||
|
||||
transforms = [f.OneHotOp(num_classes=num_classes, smoothing_rate=epsilon_para)]
|
||||
transform_label = f.Compose(transforms)
|
||||
dataset = dataset.map(operations=transform_label, input_columns=["label"])
|
||||
|
||||
golden_label = np.ones(num_classes) * epsilon_para / num_classes
|
||||
golden_label[1] = 1 - epsilon_para / num_classes
|
||||
|
||||
for data in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
label = data["label"]
|
||||
logger.info("label is {}".format(label))
|
||||
logger.info("golden_label is {}".format(golden_label))
|
||||
assert label.all() == golden_label.all()
|
||||
logger.info("====test one hot op ok====")
|
||||
|
||||
|
||||
def test_mix_up_single():
|
||||
"""
|
||||
Feature: MixUp Op
|
||||
Description: Test Python op, single batch mix up scenario
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test single batch mix up op")
|
||||
|
||||
resize_height = 224
|
||||
resize_width = 224
|
||||
|
||||
# Create dataset and define map operations
|
||||
ds1 = ds.ImageFolderDataset(DATA_DIR_2)
|
||||
|
||||
num_classes = 10
|
||||
decode_op = c_vision.Decode()
|
||||
resize_op = c_vision.Resize((resize_height, resize_width), c_vision.Inter.LINEAR)
|
||||
one_hot_encode = c.OneHot(num_classes) # num_classes is input argument
|
||||
|
||||
ds1 = ds1.map(operations=decode_op, input_columns=["image"])
|
||||
ds1 = ds1.map(operations=resize_op, input_columns=["image"])
|
||||
ds1 = ds1.map(operations=one_hot_encode, input_columns=["label"])
|
||||
|
||||
# apply batch operations
|
||||
batch_size = 3
|
||||
ds1 = ds1.batch(batch_size, drop_remainder=True)
|
||||
|
||||
ds2 = ds1
|
||||
alpha = 0.2
|
||||
transforms = [py_vision.MixUp(batch_size=batch_size, alpha=alpha, is_single=True)
|
||||
]
|
||||
ds1 = ds1.map(operations=transforms, input_columns=["image", "label"])
|
||||
|
||||
for data1, data2 in zip(ds1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
ds2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image1 = data1["image"]
|
||||
label = data1["label"]
|
||||
logger.info("label is {}".format(label))
|
||||
|
||||
image2 = data2["image"]
|
||||
label2 = data2["label"]
|
||||
logger.info("label2 is {}".format(label2))
|
||||
|
||||
lam = np.abs(label - label2)
|
||||
for index in range(batch_size - 1):
|
||||
if np.square(lam[index]).mean() != 0:
|
||||
lam_value = 1 - np.sum(lam[index]) / 2
|
||||
img_golden = lam_value * image2[index] + (1 - lam_value) * image2[index + 1]
|
||||
assert image1[index].all() == img_golden.all()
|
||||
logger.info("====test single batch mixup ok====")
|
||||
|
||||
|
||||
def test_mix_up_multi():
|
||||
"""
|
||||
Feature: MixUp Op
|
||||
Description: Test Python op, multiple batch mix up scenario
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test several batch mix up op")
|
||||
|
||||
resize_height = 224
|
||||
resize_width = 224
|
||||
|
||||
# Create dataset and define map operations
|
||||
ds1 = ds.ImageFolderDataset(DATA_DIR_2)
|
||||
|
||||
num_classes = 3
|
||||
decode_op = c_vision.Decode()
|
||||
resize_op = c_vision.Resize((resize_height, resize_width), c_vision.Inter.LINEAR)
|
||||
one_hot_encode = c.OneHot(num_classes) # num_classes is input argument
|
||||
ds1 = ds1.map(operations=[decode_op, resize_op], input_columns=["image"])
|
||||
ds1 = ds1.map(operations=one_hot_encode, input_columns=["label"])
|
||||
|
||||
# apply batch operations
|
||||
batch_size = 3
|
||||
ds1 = ds1.batch(batch_size, drop_remainder=True)
|
||||
|
||||
ds2 = ds1
|
||||
alpha = 0.2
|
||||
transforms = [py_vision.MixUp(batch_size=batch_size, alpha=alpha, is_single=False)
|
||||
]
|
||||
ds1 = ds1.map(operations=transforms, input_columns=["image", "label"])
|
||||
num_iter = 0
|
||||
batch1_image1 = 0
|
||||
for data1, data2 in zip(ds1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
ds2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image1 = data1["image"]
|
||||
label1 = data1["label"]
|
||||
logger.info("label: {}".format(label1))
|
||||
|
||||
image2 = data2["image"]
|
||||
label2 = data2["label"]
|
||||
logger.info("label2: {}".format(label2))
|
||||
|
||||
if num_iter == 0:
|
||||
batch1_image1 = image1
|
||||
|
||||
if num_iter == 1:
|
||||
lam = np.abs(label2 - label1)
|
||||
logger.info("lam value in multi: {}".format(lam))
|
||||
for index in range(batch_size):
|
||||
if np.square(lam[index]).mean() != 0:
|
||||
lam_value = 1 - np.sum(lam[index]) / 2
|
||||
img_golden = lam_value * image2[index] + (1 - lam_value) * batch1_image1[index]
|
||||
assert image1[index].all() == img_golden.all()
|
||||
logger.info("====test several batch mixup ok====")
|
||||
break
|
||||
num_iter += 1
|
||||
assert num_iter == 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_one_hot_op()
|
||||
test_mix_up_single()
|
||||
test_mix_up_multi()
|
|
@ -0,0 +1,359 @@
|
|||
# Copyright 2019-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing Normalize op in DE
|
||||
"""
|
||||
import numpy as np
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
from mindspore import log as logger
|
||||
from ..dataset.util import diff_mse, save_and_check_md5, visualize_image
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
GENERATE_GOLDEN = False
|
||||
|
||||
|
||||
def normalize_np(image, mean, std):
|
||||
"""
|
||||
Apply the Normalization
|
||||
"""
|
||||
# DE decodes the image in RGB by default, hence
|
||||
# the values here are in RGB
|
||||
image = np.array(image, np.float32)
|
||||
image = image - np.array(mean)
|
||||
image = image * (1.0 / np.array(std))
|
||||
return image
|
||||
|
||||
|
||||
def util_test_normalize(mean, std, op_type):
|
||||
"""
|
||||
Utility function for testing Normalize. Input arguments are given by other tests
|
||||
"""
|
||||
if op_type == "cpp":
|
||||
# define map operations
|
||||
decode_op = c_vision.Decode()
|
||||
normalize_op = c_vision.Normalize(mean, std)
|
||||
# Generate dataset
|
||||
data = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data = data.map(operations=decode_op, input_columns=["image"])
|
||||
data = data.map(operations=normalize_op, input_columns=["image"])
|
||||
elif op_type == "python":
|
||||
# define map operations
|
||||
transforms = [
|
||||
py_vision.Decode(),
|
||||
py_vision.ToTensor(),
|
||||
py_vision.Normalize(mean, std)
|
||||
]
|
||||
transform = mindspore.dataset.transforms.py_transforms.Compose(transforms)
|
||||
# Generate dataset
|
||||
data = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data = data.map(operations=transform, input_columns=["image"])
|
||||
else:
|
||||
raise ValueError("Wrong parameter value")
|
||||
return data
|
||||
|
||||
|
||||
def util_test_normalize_grayscale(num_output_channels, mean, std):
|
||||
"""
|
||||
Utility function for testing Normalize. Input arguments are given by other tests
|
||||
"""
|
||||
transforms = [
|
||||
py_vision.Decode(),
|
||||
py_vision.Grayscale(num_output_channels),
|
||||
py_vision.ToTensor(),
|
||||
py_vision.Normalize(mean, std)
|
||||
]
|
||||
transform = mindspore.dataset.transforms.py_transforms.Compose(transforms)
|
||||
# Generate dataset
|
||||
data = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data = data.map(operations=transform, input_columns=["image"])
|
||||
return data
|
||||
|
||||
|
||||
def test_normalize_op_c(plot=False):
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test C++ op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test Normalize in cpp")
|
||||
mean = [121.0, 115.0, 100.0]
|
||||
std = [70.0, 68.0, 71.0]
|
||||
# define map operations
|
||||
decode_op = c_vision.Decode()
|
||||
normalize_op = c_vision.Normalize(mean, std)
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data1 = data1.map(operations=decode_op, input_columns=["image"])
|
||||
data1 = data1.map(operations=normalize_op, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data2 = data2.map(operations=decode_op, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image_de_normalized = item1["image"]
|
||||
image_original = item2["image"]
|
||||
image_np_normalized = normalize_np(image_original, mean, std)
|
||||
mse = diff_mse(image_de_normalized, image_np_normalized)
|
||||
logger.info("image_{}, mse: {}".format(num_iter + 1, mse))
|
||||
assert mse < 0.01
|
||||
if plot:
|
||||
visualize_image(image_original, image_de_normalized, mse, image_np_normalized)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_normalize_op_py(plot=False):
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Python op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test Normalize in python")
|
||||
mean = [0.475, 0.45, 0.392]
|
||||
std = [0.275, 0.267, 0.278]
|
||||
# define map operations
|
||||
transforms = [
|
||||
py_vision.Decode(),
|
||||
py_vision.ToTensor()
|
||||
]
|
||||
transform = mindspore.dataset.transforms.py_transforms.Compose(transforms)
|
||||
normalize_op = py_vision.Normalize(mean, std)
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data1 = data1.map(operations=transform, input_columns=["image"])
|
||||
data1 = data1.map(operations=normalize_op, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data2 = data2.map(operations=transform, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image_de_normalized = (item1["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
image_np_normalized = (normalize_np(item2["image"].transpose(1, 2, 0), mean, std) * 255).astype(np.uint8)
|
||||
image_original = (item2["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
mse = diff_mse(image_de_normalized, image_np_normalized)
|
||||
logger.info("image_{}, mse: {}".format(num_iter + 1, mse))
|
||||
assert mse < 0.01
|
||||
if plot:
|
||||
visualize_image(image_original, image_de_normalized, mse, image_np_normalized)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_normalize_md5_01():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test C++ op and Python op in same dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("test_normalize_md5_01")
|
||||
data_c = util_test_normalize([121.0, 115.0, 100.0], [70.0, 68.0, 71.0], "cpp")
|
||||
data_py = util_test_normalize([0.475, 0.45, 0.392], [0.275, 0.267, 0.278], "python")
|
||||
|
||||
# check results with md5 comparison
|
||||
filename1 = "normalize_01_c_result.npz"
|
||||
filename2 = "normalize_01_py_result.npz"
|
||||
save_and_check_md5(data_c, filename1, generate_golden=GENERATE_GOLDEN)
|
||||
save_and_check_md5(data_py, filename2, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
def test_normalize_md5_02():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Python op with len(mean)=len(std)=1 and RGB images
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("test_normalize_md5_02")
|
||||
data_py = util_test_normalize([0.475], [0.275], "python")
|
||||
|
||||
# check results with md5 comparison
|
||||
filename2 = "normalize_02_py_result.npz"
|
||||
save_and_check_md5(data_py, filename2, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
def test_normalize_exception_unequal_size_c():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize C++ op with error input: len(mean) != len(std)
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_unequal_size_c")
|
||||
try:
|
||||
_ = c_vision.Normalize([100, 250, 125], [50, 50, 75, 75])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "Length of mean and std must be equal."
|
||||
|
||||
|
||||
def test_normalize_exception_out_of_range_c():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize Python op with error input: value is not in range [0,255]
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_out_of_range_c")
|
||||
try:
|
||||
_ = c_vision.Normalize([256, 250, 125], [50, 75, 75])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "not within the required interval" in str(e)
|
||||
try:
|
||||
_ = c_vision.Normalize([255, 250, 125], [0, 75, 75])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "not within the required interval" in str(e)
|
||||
|
||||
|
||||
def test_normalize_exception_unequal_size_py():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize Python op with error input: len(mean) != len(std)
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_unequal_size_py")
|
||||
try:
|
||||
_ = py_vision.Normalize([0.50, 0.30, 0.75], [0.18, 0.32, 0.71, 0.72])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "Length of mean and std must be equal."
|
||||
|
||||
|
||||
def test_normalize_exception_invalid_size_py():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize Python op with error input: len(mean)=len(std)=2
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_invalid_size_py")
|
||||
data = util_test_normalize([0.75, 0.25], [0.18, 0.32], "python")
|
||||
try:
|
||||
_ = data.create_dict_iterator(num_epochs=1).__next__()
|
||||
except RuntimeError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "Length of mean and std must both be 1 or" in str(e)
|
||||
|
||||
|
||||
def test_normalize_exception_invalid_range_py():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize Python op with error input: value is not in range [0,1]
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_invalid_range_py")
|
||||
try:
|
||||
_ = py_vision.Normalize([0.75, 1.25, 0.5], [0.1, 0.18, 1.32])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "Input mean_value is not within the required interval of [0.0, 1.0]." in str(e)
|
||||
|
||||
|
||||
def test_normalize_grayscale_md5_01():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Python op with len(mean)=len(std)=1 and 1 channel grayscale images
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("test_normalize_grayscale_md5_01")
|
||||
data = util_test_normalize_grayscale(1, [0.5], [0.175])
|
||||
# check results with md5 comparison
|
||||
filename = "normalize_03_py_result.npz"
|
||||
save_and_check_md5(data, filename, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
def test_normalize_grayscale_md5_02():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Python op with len(mean)=len(std)=1 and 3 channel grayscale images
|
||||
Expectation: Dataset pipeline runs successfully and md5 results are verified
|
||||
"""
|
||||
logger.info("test_normalize_grayscale_md5_02")
|
||||
data = util_test_normalize_grayscale(3, [0.5, 0.5, 0.5], [0.175, 0.235, 0.512])
|
||||
# check results with md5 comparison
|
||||
filename = "normalize_04_py_result.npz"
|
||||
save_and_check_md5(data, filename, generate_golden=GENERATE_GOLDEN)
|
||||
|
||||
|
||||
def test_normalize_grayscale_exception():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test Normalize Python op with error input: len(mean)=len(std)=3 with 1 channel grayscale images
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_grayscale_exception")
|
||||
try:
|
||||
_ = util_test_normalize_grayscale(1, [0.5, 0.5, 0.5], [0.175, 0.235, 0.512])
|
||||
except RuntimeError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "Input is not within the required range" in str(e)
|
||||
|
||||
|
||||
def test_multiple_channels():
|
||||
"""
|
||||
Feature: Normalize Op
|
||||
Description: Test C++ op with multiple channels
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("test_multiple_channels")
|
||||
|
||||
def util_test(item, mean, std):
|
||||
data = ds.NumpySlicesDataset([item], shuffle=False)
|
||||
data = data.map(c_vision.Normalize(mean, std))
|
||||
for d in data.create_tuple_iterator(num_epochs=1, output_numpy=True):
|
||||
actual = d[0]
|
||||
mean = np.array(mean, dtype=item.dtype)
|
||||
std = np.array(std, dtype=item.dtype)
|
||||
expected = item
|
||||
if len(item.shape) != 1 and len(mean) == 1:
|
||||
mean = [mean[0]] * expected.shape[-1]
|
||||
std = [std[0]] * expected.shape[-1]
|
||||
if len(item.shape) == 2:
|
||||
expected = np.expand_dims(expected, 2)
|
||||
for c in range(expected.shape[-1]):
|
||||
expected[:, :, c] = (expected[:, :, c] - mean[c]) / std[c]
|
||||
expected = expected.squeeze()
|
||||
|
||||
np.testing.assert_almost_equal(actual, expected, decimal=6)
|
||||
|
||||
util_test(np.ones(shape=[2, 2, 3]), mean=[0.5, 0.6, 0.7], std=[0.1, 0.2, 0.3])
|
||||
util_test(np.ones(shape=[20, 45, 3]) * 1.3, mean=[0.5, 0.6, 0.7], std=[0.1, 0.2, 0.3])
|
||||
util_test(np.ones(shape=[20, 45, 4]) * 1.3, mean=[0.5, 0.6, 0.7, 0.8], std=[0.1, 0.2, 0.3, 0.4])
|
||||
util_test(np.ones(shape=[2, 2]), mean=[0.5], std=[0.1])
|
||||
util_test(np.ones(shape=[2, 2, 5]), mean=[0.5], std=[0.1])
|
||||
util_test(np.ones(shape=[6, 6, 129]), mean=[0.5] * 129, std=[0.1] * 129)
|
||||
util_test(np.ones(shape=[6, 6, 129]), mean=[0.5], std=[0.1])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_normalize_op_c(plot=True)
|
||||
test_normalize_op_py(plot=True)
|
||||
test_normalize_md5_01()
|
||||
test_normalize_md5_02()
|
||||
test_normalize_exception_unequal_size_c()
|
||||
test_normalize_exception_unequal_size_py()
|
||||
test_normalize_exception_invalid_size_py()
|
||||
test_normalize_exception_invalid_range_py()
|
||||
test_normalize_grayscale_md5_01()
|
||||
test_normalize_grayscale_md5_02()
|
||||
test_normalize_grayscale_exception()
|
|
@ -0,0 +1,219 @@
|
|||
# Copyright 2020-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing NormalizePad op in DE
|
||||
"""
|
||||
import numpy as np
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
from mindspore import log as logger
|
||||
from ..dataset.util import diff_mse, visualize_image
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
GENERATE_GOLDEN = False
|
||||
|
||||
|
||||
def normalizepad_np(image, mean, std):
|
||||
"""
|
||||
Apply the normalize+pad
|
||||
"""
|
||||
# DE decodes the image in RGB by default, hence
|
||||
# the values here are in RGB
|
||||
image = np.array(image, np.float32)
|
||||
image = image - np.array(mean)
|
||||
image = image * (1.0 / np.array(std))
|
||||
zeros = np.zeros([image.shape[0], image.shape[1], 1], dtype=np.float32)
|
||||
output = np.concatenate((image, zeros), axis=2)
|
||||
return output
|
||||
|
||||
|
||||
def test_normalizepad_op_c(plot=False):
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test C++ op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test NormalizePad in cpp")
|
||||
mean = [121.0, 115.0, 100.0]
|
||||
std = [70.0, 68.0, 71.0]
|
||||
# define map operations
|
||||
decode_op = c_vision.Decode()
|
||||
normalizepad_op = c_vision.NormalizePad(mean, std)
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data1 = data1.map(operations=decode_op, input_columns=["image"])
|
||||
data1 = data1.map(operations=normalizepad_op, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data2 = data2.map(operations=decode_op, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image_de_normalized = item1["image"]
|
||||
image_original = item2["image"]
|
||||
image_np_normalized = normalizepad_np(image_original, mean, std)
|
||||
mse = diff_mse(image_de_normalized, image_np_normalized)
|
||||
logger.info("image_{}, mse: {}".format(num_iter + 1, mse))
|
||||
assert mse < 0.01
|
||||
if plot:
|
||||
visualize_image(image_original, image_de_normalized, mse, image_np_normalized)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_normalizepad_op_py(plot=False):
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test Python op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test NormalizePad in python")
|
||||
mean = [0.475, 0.45, 0.392]
|
||||
std = [0.275, 0.267, 0.278]
|
||||
# define map operations
|
||||
transforms = [
|
||||
py_vision.Decode(),
|
||||
py_vision.ToTensor()
|
||||
]
|
||||
transform = mindspore.dataset.transforms.py_transforms.Compose(transforms)
|
||||
normalizepad_op = py_vision.NormalizePad(mean, std)
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data1 = data1.map(operations=transform, input_columns=["image"])
|
||||
data1 = data1.map(operations=normalizepad_op, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
data2 = data2.map(operations=transform, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(num_epochs=1, output_numpy=True),
|
||||
data2.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
image_de_normalized = (item1["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
image_np_normalized = (normalizepad_np(item2["image"].transpose(1, 2, 0), mean, std) * 255).astype(np.uint8)
|
||||
image_original = (item2["image"].transpose(1, 2, 0) * 255).astype(np.uint8)
|
||||
mse = diff_mse(image_de_normalized, image_np_normalized)
|
||||
logger.info("image_{}, mse: {}".format(num_iter + 1, mse))
|
||||
assert mse < 0.01
|
||||
if plot:
|
||||
visualize_image(image_original, image_de_normalized, mse, image_np_normalized)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_decode_normalizepad_op():
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test Decode C++ op followed by NormalizePad op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("Test [Decode, NormalizePad] in one Map")
|
||||
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image", "label"], num_parallel_workers=1,
|
||||
shuffle=False)
|
||||
|
||||
# define map operations
|
||||
decode_op = c_vision.Decode()
|
||||
normalizepad_op = c_vision.NormalizePad([121.0, 115.0, 100.0], [70.0, 68.0, 71.0], "float16")
|
||||
|
||||
# apply map operations on images
|
||||
data1 = data1.map(operations=[decode_op, normalizepad_op], input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for item in data1.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
logger.info("Looping inside iterator {}".format(num_iter))
|
||||
assert item["image"].dtype == np.float16
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_normalizepad_exception_unequal_size_c():
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test NormalizePad C++ op with error input: len(mean) != len(std)
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalize_exception_unequal_size_c")
|
||||
try:
|
||||
_ = c_vision.NormalizePad([100, 250, 125], [50, 50, 75, 75])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "Length of mean and std must be equal."
|
||||
|
||||
try:
|
||||
_ = c_vision.NormalizePad([100, 250, 125], [50, 50, 75], 1)
|
||||
except TypeError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "dtype should be string."
|
||||
|
||||
try:
|
||||
_ = c_vision.NormalizePad([100, 250, 125], [50, 50, 75], "")
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "dtype only support float32 or float16."
|
||||
|
||||
|
||||
def test_normalizepad_exception_unequal_size_py():
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test NormalizePad Python op with error input: len(mean) != len(std)
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalizepad_exception_unequal_size_py")
|
||||
try:
|
||||
_ = py_vision.NormalizePad([0.50, 0.30, 0.75], [0.18, 0.32, 0.71, 0.72])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "Length of mean and std must be equal."
|
||||
|
||||
try:
|
||||
_ = py_vision.NormalizePad([0.50, 0.30, 0.75], [0.18, 0.32, 0.71], 1)
|
||||
except TypeError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "dtype should be string."
|
||||
|
||||
try:
|
||||
_ = py_vision.NormalizePad([0.50, 0.30, 0.75], [0.18, 0.32, 0.71], "")
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert str(e) == "dtype only support float32 or float16."
|
||||
|
||||
|
||||
def test_normalizepad_exception_invalid_range_py():
|
||||
"""
|
||||
Feature: NormalizePad Op
|
||||
Description: Test NormalizePad Python op with error input: value is not in range [0,1]
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
logger.info("test_normalizepad_exception_invalid_range_py")
|
||||
try:
|
||||
_ = py_vision.NormalizePad([0.75, 1.25, 0.5], [0.1, 0.18, 1.32])
|
||||
except ValueError as e:
|
||||
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||
assert "Input mean_value is not within the required interval of [0.0, 1.0]." in str(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_normalizepad_op_c(plot=True)
|
||||
test_normalizepad_op_py(plot=True)
|
||||
test_decode_normalizepad_op()
|
||||
test_normalizepad_exception_unequal_size_c()
|
||||
test_normalizepad_exception_unequal_size_py()
|
||||
test_normalizepad_exception_invalid_range_py()
|
|
@ -0,0 +1,245 @@
|
|||
# Copyright 2019-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing the OneHot Op
|
||||
"""
|
||||
import numpy as np
|
||||
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.c_transforms as data_trans
|
||||
import mindspore.dataset.transforms.py_transforms as py_trans
|
||||
import mindspore.dataset.vision.c_transforms as c_vision
|
||||
from mindspore import log as logger
|
||||
from ..dataset.util import dataset_equal_with_function
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
|
||||
def one_hot(index, depth):
|
||||
"""
|
||||
Apply the one_hot
|
||||
"""
|
||||
arr = np.zeros([1, depth], dtype=np.int32)
|
||||
arr[0, index] = 1
|
||||
return arr
|
||||
|
||||
|
||||
def test_one_hot():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test C++ op with One Hot Encoding
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("test_one_hot")
|
||||
depth = 10
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, shuffle=False)
|
||||
one_hot_op = data_trans.OneHot(num_classes=depth)
|
||||
data1 = data1.map(operations=one_hot_op, input_columns=["label"], column_order=["label"])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["label"], shuffle=False)
|
||||
|
||||
assert dataset_equal_with_function(data1, data2, 0, one_hot, depth)
|
||||
|
||||
|
||||
def test_one_hot_post_aug():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test C++ op with One Hot Encoding after Multiple Data Augmentation Operators
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
logger.info("test_one_hot_post_aug")
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, shuffle=False)
|
||||
|
||||
# Define data augmentation parameters
|
||||
rescale = 1.0 / 255.0
|
||||
shift = 0.0
|
||||
resize_height, resize_width = 224, 224
|
||||
|
||||
# Define map operations
|
||||
decode_op = c_vision.Decode()
|
||||
rescale_op = c_vision.Rescale(rescale, shift)
|
||||
resize_op = c_vision.Resize((resize_height, resize_width))
|
||||
|
||||
# Apply map operations on images
|
||||
data1 = data1.map(operations=decode_op, input_columns=["image"])
|
||||
data1 = data1.map(operations=rescale_op, input_columns=["image"])
|
||||
data1 = data1.map(operations=resize_op, input_columns=["image"])
|
||||
|
||||
# Apply one-hot encoding on labels
|
||||
depth = 4
|
||||
one_hot_encode = data_trans.OneHot(depth)
|
||||
data1 = data1.map(operations=one_hot_encode, input_columns=["label"])
|
||||
|
||||
# Apply datasets ops
|
||||
buffer_size = 100
|
||||
seed = 10
|
||||
batch_size = 2
|
||||
ds.config.set_seed(seed)
|
||||
data1 = data1.shuffle(buffer_size=buffer_size)
|
||||
data1 = data1.batch(batch_size, drop_remainder=True)
|
||||
|
||||
num_iter = 0
|
||||
for item in data1.create_dict_iterator(num_epochs=1):
|
||||
logger.info("image is: {}".format(item["image"]))
|
||||
logger.info("label is: {}".format(item["label"]))
|
||||
num_iter += 1
|
||||
|
||||
assert num_iter == 1
|
||||
|
||||
|
||||
def test_one_hot_success():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test Python op, with generated label using np.array(index)
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
|
||||
class GetDatasetGenerator:
|
||||
def __init__(self):
|
||||
np.random.seed(58)
|
||||
self.__data = np.random.sample((5, 2))
|
||||
self.__label = []
|
||||
for index in range(5):
|
||||
self.__label.append(np.array(index))
|
||||
|
||||
def __getitem__(self, index):
|
||||
return (self.__data[index], self.__label[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__data)
|
||||
|
||||
dataset = ds.GeneratorDataset(GetDatasetGenerator(), ["data", "label"], shuffle=False)
|
||||
|
||||
one_hot_encode = py_trans.OneHotOp(10)
|
||||
trans = py_trans.Compose([one_hot_encode])
|
||||
dataset = dataset.map(operations=trans, input_columns=["label"])
|
||||
|
||||
for index, item in enumerate(dataset.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
assert item["label"][index] == 1.0
|
||||
|
||||
|
||||
def test_one_hot_success2():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test Python op, with generated label using np.array([index])
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
|
||||
class GetDatasetGenerator:
|
||||
def __init__(self):
|
||||
np.random.seed(58)
|
||||
self.__data = np.random.sample((5, 2))
|
||||
self.__label = []
|
||||
for index in range(5):
|
||||
self.__label.append(np.array([index]))
|
||||
|
||||
def __getitem__(self, index):
|
||||
return (self.__data[index], self.__label[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__data)
|
||||
|
||||
dataset = ds.GeneratorDataset(GetDatasetGenerator(), ["data", "label"], shuffle=False)
|
||||
|
||||
one_hot_encode = py_trans.OneHotOp(10)
|
||||
trans = py_trans.Compose([one_hot_encode])
|
||||
dataset = dataset.map(operations=trans, input_columns=["label"])
|
||||
|
||||
for index, item in enumerate(dataset.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
logger.info(item)
|
||||
assert item["label"][0][index] == 1.0
|
||||
|
||||
|
||||
def test_one_hot_success3():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test Python op, with multi-dimension generated label
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
|
||||
class GetDatasetGenerator:
|
||||
def __init__(self):
|
||||
np.random.seed(58)
|
||||
self.__data = np.random.sample((5, 2))
|
||||
self.__label = []
|
||||
for _ in range(5):
|
||||
value = np.ones([10, 1], dtype=np.int32)
|
||||
for i in range(10):
|
||||
value[i][0] = i
|
||||
self.__label.append(value)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return (self.__data[index], self.__label[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__data)
|
||||
|
||||
dataset = ds.GeneratorDataset(GetDatasetGenerator(), ["data", "label"], shuffle=False)
|
||||
|
||||
one_hot_encode = py_trans.OneHotOp(10)
|
||||
trans = py_trans.Compose([one_hot_encode])
|
||||
dataset = dataset.map(operations=trans, input_columns=["label"])
|
||||
|
||||
for item in dataset.create_dict_iterator(num_epochs=1, output_numpy=True):
|
||||
logger.info(item)
|
||||
for i in range(10):
|
||||
assert item["label"][i][0][i] == 1.0
|
||||
|
||||
|
||||
def test_one_hot_type_error():
|
||||
"""
|
||||
Feature: OneHot Op
|
||||
Description: Test Python op with invalid float input type
|
||||
Expectation: Invalid input is detected
|
||||
"""
|
||||
|
||||
class GetDatasetGenerator:
|
||||
def __init__(self):
|
||||
np.random.seed(58)
|
||||
self.__data = np.random.sample((5, 2))
|
||||
self.__label = []
|
||||
for index in range(5):
|
||||
self.__label.append(np.array(float(index)))
|
||||
|
||||
def __getitem__(self, index):
|
||||
return (self.__data[index], self.__label[index])
|
||||
|
||||
def __len__(self):
|
||||
return len(self.__data)
|
||||
|
||||
dataset = ds.GeneratorDataset(GetDatasetGenerator(), ["data", "label"], shuffle=False)
|
||||
|
||||
one_hot_encode = py_trans.OneHotOp(10)
|
||||
trans = py_trans.Compose([one_hot_encode])
|
||||
dataset = dataset.map(operations=trans, input_columns=["label"])
|
||||
|
||||
try:
|
||||
for index, item in enumerate(dataset.create_dict_iterator(num_epochs=1, output_numpy=True)):
|
||||
assert item["label"][index] == 1.0
|
||||
except RuntimeError as e:
|
||||
assert "the input numpy type should be int" in str(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_one_hot()
|
||||
test_one_hot_post_aug()
|
||||
test_one_hot_success()
|
||||
test_one_hot_success2()
|
||||
test_one_hot_success3()
|
||||
test_one_hot_type_error()
|
|
@ -0,0 +1,193 @@
|
|||
# Copyright 2021-2022 Huawei Technologies Co., Ltd
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing RgbToBgr op in DE
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
from numpy.testing import assert_allclose
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.py_transforms
|
||||
import mindspore.dataset.vision.c_transforms as vision
|
||||
import mindspore.dataset.vision.py_transforms as py_vision
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
|
||||
def generate_numpy_random_rgb(shape):
|
||||
# Only generate floating points that are fractions like n / 256, since they
|
||||
# are RGB pixels. Some low-precision floating point types in this test can't
|
||||
# handle arbitrary precision floating points well.
|
||||
return np.random.randint(0, 256, shape) / 255.
|
||||
|
||||
|
||||
def test_rgb_bgr_hwc_py():
|
||||
"""
|
||||
Feature: RgbToBgr Op
|
||||
Description: Test Python op with HWC input shape in eager mode
|
||||
Expectation: Output image shape from op is verified
|
||||
"""
|
||||
rgb_flat = generate_numpy_random_rgb((64, 3)).astype(np.float32)
|
||||
rgb_np = rgb_flat.reshape((8, 8, 3))
|
||||
|
||||
rgb2bgr_op = py_vision.RgbToBgr(is_hwc=True)
|
||||
bgr_np_pred = rgb2bgr_op(rgb_np)
|
||||
r, g, b = rgb_np[:, :, 0], rgb_np[:, :, 1], rgb_np[:, :, 2]
|
||||
bgr_np_gt = np.stack((b, g, r), axis=2)
|
||||
assert bgr_np_pred.shape == rgb_np.shape
|
||||
assert_allclose(bgr_np_pred.flatten(),
|
||||
bgr_np_gt.flatten(),
|
||||
rtol=1e-5,
|
||||
atol=0)
|
||||
|
||||
|
||||
def test_rgb_bgr_hwc_c():
|
||||
"""
|
||||
Feature: RgbToBgr Op
|
||||
Description: Test C++ op with HWC input shape in eager mode
|
||||
Expectation: Output image shape from op is verified
|
||||
"""
|
||||
rgb_flat = generate_numpy_random_rgb((64, 3)).astype(np.float32)
|
||||
rgb_np = rgb_flat.reshape((8, 8, 3))
|
||||
|
||||
rgb2bgr_op = vision.RgbToBgr()
|
||||
bgr_np_pred = rgb2bgr_op(rgb_np)
|
||||
r, g, b = rgb_np[:, :, 0], rgb_np[:, :, 1], rgb_np[:, :, 2]
|
||||
bgr_np_gt = np.stack((b, g, r), axis=2)
|
||||
assert bgr_np_pred.shape == rgb_np.shape
|
||||
assert_allclose(bgr_np_pred.flatten(),
|
||||
bgr_np_gt.flatten(),
|
||||
rtol=1e-5,
|
||||
atol=0)
|
||||
|
||||
|
||||
def test_rgb_bgr_chw_py():
|
||||
"""
|
||||
Feature: RgbToBgr Op
|
||||
Description: Test Python op in with CHW input shape eager mode
|
||||
Expectation: Output image shape from op is verified
|
||||
"""
|
||||
rgb_flat = generate_numpy_random_rgb((64, 3)).astype(np.float32)
|
||||
rgb_np = rgb_flat.reshape((3, 8, 8))
|
||||
|
||||
rgb2bgr_op = py_vision.RgbToBgr(is_hwc=False)
|
||||
rgb_np_pred = rgb2bgr_op(rgb_np)
|
||||
rgb_np_gt = rgb_np[::-1, :, :]
|
||||
assert rgb_np_pred.shape == rgb_np.shape
|
||||
assert_allclose(rgb_np_pred.flatten(),
|
||||
rgb_np_gt.flatten(),
|
||||
rtol=1e-5,
|
||||
atol=0)
|
||||
|
||||
|
||||
def test_rgb_bgr_pipeline_py():
|
||||
"""
|
||||
Feature: RgbToBgr Op
|
||||
Description: Test Python op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
# First dataset
|
||||
transforms1_list = [py_vision.Decode(), py_vision.Resize([64, 64]), py_vision.ToTensor()]
|
||||
transforms1 = mindspore.dataset.transforms.py_transforms.Compose(
|
||||
transforms1_list)
|
||||
ds1 = ds.TFRecordDataset(DATA_DIR,
|
||||
SCHEMA_DIR,
|
||||
columns_list=["image"],
|
||||
shuffle=False)
|
||||
ds1 = ds1.map(operations=transforms1, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
transforms2 = [
|
||||
py_vision.Decode(),
|
||||
py_vision.Resize([64, 64]),
|
||||
py_vision.ToTensor(),
|
||||
py_vision.RgbToBgr()
|
||||
]
|
||||
transforms2 = mindspore.dataset.transforms.py_transforms.Compose(
|
||||
transforms2)
|
||||
ds2 = ds.TFRecordDataset(DATA_DIR,
|
||||
SCHEMA_DIR,
|
||||
columns_list=["image"],
|
||||
shuffle=False)
|
||||
ds2 = ds2.map(operations=transforms2, input_columns=["image"])
|
||||
|
||||
num_iter = 0
|
||||
for data1, data2 in zip(ds1.create_dict_iterator(num_epochs=1),
|
||||
ds2.create_dict_iterator(num_epochs=1)):
|
||||
num_iter += 1
|
||||
ori_img = data1["image"].asnumpy()
|
||||
cvt_img = data2["image"].asnumpy()
|
||||
cvt_img_gt = ori_img[::-1, :, :]
|
||||
assert_allclose(cvt_img_gt.flatten(),
|
||||
cvt_img.flatten(),
|
||||
rtol=1e-5,
|
||||
atol=0)
|
||||
assert ori_img.shape == cvt_img.shape
|
||||
assert num_iter == 3
|
||||
|
||||
|
||||
def test_rgb_bgr_pipeline_c():
|
||||
"""
|
||||
Feature: RgbToBgr Op
|
||||
Description: Test C++ op in dataset pipeline
|
||||
Expectation: Dataset pipeline runs successfully and results are verified
|
||||
"""
|
||||
# First dataset
|
||||
transforms1 = [
|
||||
# Set Decode(rbg=True) for test coverage of deprecated rgb arg
|
||||
vision.Decode(rgb=True),
|
||||
vision.Resize([60, 60])
|
||||
]
|
||||
transforms1 = mindspore.dataset.transforms.py_transforms.Compose(
|
||||
transforms1)
|
||||
ds1 = ds.TFRecordDataset(DATA_DIR,
|
||||
SCHEMA_DIR,
|
||||
columns_list=["image"],
|
||||
shuffle=False)
|
||||
ds1 = ds1.map(operations=transforms1, input_columns=["image"])
|
||||
|
||||
# Second dataset
|
||||
transforms2_list = [
|
||||
# Set Decode(True) for test coverage of deprecated rgb arg
|
||||
vision.Decode(True),
|
||||
vision.Resize([60, 60]),
|
||||
vision.RgbToBgr()
|
||||
]
|
||||
transforms2 = mindspore.dataset.transforms.py_transforms.Compose(transforms2_list)
|
||||
ds2 = ds.TFRecordDataset(DATA_DIR,
|
||||
SCHEMA_DIR,
|
||||
columns_list=["image"],
|
||||
shuffle=False)
|
||||
ds2 = ds2.map(operations=transforms2, input_columns=["image"])
|
||||
|
||||
for data1, data2 in zip(ds1.create_dict_iterator(num_epochs=1),
|
||||
ds2.create_dict_iterator(num_epochs=1)):
|
||||
ori_img = data1["image"].asnumpy()
|
||||
cvt_img = data2["image"].asnumpy()
|
||||
cvt_img_gt = ori_img[:, :, ::-1]
|
||||
assert_allclose(cvt_img_gt.flatten(),
|
||||
cvt_img.flatten(),
|
||||
rtol=1e-5,
|
||||
atol=0)
|
||||
assert ori_img.shape == cvt_img.shape
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_rgb_bgr_hwc_py()
|
||||
test_rgb_bgr_hwc_c()
|
||||
test_rgb_bgr_chw_py()
|
||||
test_rgb_bgr_pipeline_py()
|
||||
test_rgb_bgr_pipeline_c()
|
Loading…
Reference in New Issue