forked from mindspore-Ecosystem/mindspore
[misc] [assistant] [#I5EWHP] modify the operator horizontalFlip
This commit is contained in:
parent
0765c2cc3c
commit
0e0dcbfb3b
|
@ -6,4 +6,4 @@ mindspore.dataset.vision.HorizontalFlip
|
||||||
水平翻转输入图像。
|
水平翻转输入图像。
|
||||||
|
|
||||||
异常:
|
异常:
|
||||||
- **RuntimeError** - 如果输入图像的shape不是 <H, W> 或 <H, W, C>。
|
- **RuntimeError** - 如果输入图像的shape不是 <H, W> 或 <..., H, W, C>。
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2021 Huawei Technologies Co., Ltd
|
* Copyright 2021-2022 Huawei Technologies Co., Ltd
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,17 +16,38 @@
|
||||||
|
|
||||||
#include "minddata/dataset/kernels/image/horizontal_flip_op.h"
|
#include "minddata/dataset/kernels/image/horizontal_flip_op.h"
|
||||||
|
|
||||||
|
#include "minddata/dataset/kernels/data/data_utils.h"
|
||||||
#include "minddata/dataset/kernels/image/image_utils.h"
|
#include "minddata/dataset/kernels/image/image_utils.h"
|
||||||
|
|
||||||
namespace mindspore {
|
namespace mindspore {
|
||||||
namespace dataset {
|
namespace dataset {
|
||||||
Status HorizontalFlipOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
|
Status HorizontalFlipOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
|
||||||
IO_CHECK(input, output);
|
IO_CHECK(input, output);
|
||||||
|
RETURN_IF_NOT_OK(ValidateImage(input, "HorizontalFlip", {1, 2, 3, 4, 5, 6, 10, 11, 12}));
|
||||||
|
dsize_t rank = input->shape().Rank();
|
||||||
|
if (rank <= kDefaultImageRank) {
|
||||||
|
RETURN_IF_NOT_OK(HorizontalFlip(input, output));
|
||||||
|
} else {
|
||||||
|
// reshape input to nhwc
|
||||||
|
auto input_shape = input->shape();
|
||||||
|
dsize_t num_batch = input->Size() / (input_shape[-3] * input_shape[-2] * input_shape[-1]);
|
||||||
|
TensorShape new_shape({num_batch, input_shape[-3], input_shape[-2], input_shape[-1]});
|
||||||
|
RETURN_IF_NOT_OK(input->Reshape(new_shape));
|
||||||
|
|
||||||
RETURN_IF_NOT_OK(ValidateImageDtype("HorizontalFlip", input->type()));
|
// split [N, H, W, C] to N [H, W, C], and horizental flip N [H, W, C]
|
||||||
RETURN_IF_NOT_OK(ValidateImageRank("HorizontalFlip", input->Rank()));
|
std::vector<std::shared_ptr<Tensor>> input_vector_hwc, output_vector_hwc;
|
||||||
|
RETURN_IF_NOT_OK(BatchTensorToTensorVector(input, &input_vector_hwc));
|
||||||
|
for (int i = 0; i < num_batch; i++) {
|
||||||
|
std::shared_ptr<Tensor> flip;
|
||||||
|
RETURN_IF_NOT_OK(HorizontalFlip(input_vector_hwc[i], &flip));
|
||||||
|
output_vector_hwc.push_back(flip);
|
||||||
|
}
|
||||||
|
|
||||||
return HorizontalFlip(input, output);
|
// integrate N [H, W, C] to [N, H, W, C], and reshape [..., H, W, C]
|
||||||
|
RETURN_IF_NOT_OK(TensorVectorToBatchTensor(output_vector_hwc, output));
|
||||||
|
RETURN_IF_NOT_OK((*output)->Reshape(input_shape));
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
}
|
}
|
||||||
} // namespace dataset
|
} // namespace dataset
|
||||||
} // namespace mindspore
|
} // namespace mindspore
|
||||||
|
|
|
@ -686,7 +686,7 @@ class HorizontalFlip(ImageTensorOperation):
|
||||||
Flip the input image horizontally.
|
Flip the input image horizontally.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If given tensor shape is not <H, W> or <H, W, C>.
|
RuntimeError: If given tensor shape is not <H, W> or <..., H, W, C>.
|
||||||
|
|
||||||
Supported Platforms:
|
Supported Platforms:
|
||||||
``CPU``
|
``CPU``
|
||||||
|
|
|
@ -1156,7 +1156,7 @@ class HorizontalFlip(ImageTensorOperation):
|
||||||
Flip the input image horizontally.
|
Flip the input image horizontally.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
RuntimeError: If given tensor shape is not <H, W> or <H, W, C>.
|
RuntimeError: If given tensor shape is not <H, W> or <..., H, W, C>.
|
||||||
|
|
||||||
Supported Platforms:
|
Supported Platforms:
|
||||||
``CPU``
|
``CPU``
|
||||||
|
|
|
@ -89,3 +89,54 @@ TEST_F(MindDataTestHorizontalFlip, TestHorizontalFlipEager) {
|
||||||
|
|
||||||
EXPECT_EQ(rc, Status::OK());
|
EXPECT_EQ(rc, Status::OK());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Feature: HorizontalFlip op
|
||||||
|
/// Description: Test HorizontalFlip op by processing tensor with dim more than 3
|
||||||
|
/// Expectation: Output is equal to the expected output
|
||||||
|
TEST_F(MindDataTestHorizontalFlip, TestHorizontalFlipBatch) {
|
||||||
|
MS_LOG(INFO) << "Doing MindDataTestHorizontalFlip-TestHorizontalFlipBatch.";
|
||||||
|
|
||||||
|
// Create an ImageFolder Dataset
|
||||||
|
std::string folder_path = datasets_root_path_ + "/testPK/data/";
|
||||||
|
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, std::make_shared<RandomSampler>(false, 5));
|
||||||
|
EXPECT_NE(ds, nullptr);
|
||||||
|
|
||||||
|
// Create a Repeat operation on ds
|
||||||
|
int32_t repeat_num = 3;
|
||||||
|
ds = ds->Repeat(repeat_num);
|
||||||
|
EXPECT_NE(ds, nullptr);
|
||||||
|
|
||||||
|
// Create a Batch operation on ds, choose batch size 3 to test high dimension input
|
||||||
|
int32_t batch_size = 3;
|
||||||
|
ds = ds->Batch(batch_size);
|
||||||
|
EXPECT_NE(ds, nullptr);
|
||||||
|
|
||||||
|
// Create objects for the tensor ops
|
||||||
|
auto horizontal_flip = std::make_shared<vision::HorizontalFlip>();
|
||||||
|
|
||||||
|
// Create a Map operation on ds
|
||||||
|
ds = ds->Map({horizontal_flip});
|
||||||
|
EXPECT_NE(ds, nullptr);
|
||||||
|
|
||||||
|
// Create an iterator over the result of the above dataset
|
||||||
|
// This will trigger the creation of the Execution Tree and launch it.
|
||||||
|
std::shared_ptr<Iterator> iter = ds->CreateIterator();
|
||||||
|
EXPECT_NE(iter, nullptr);
|
||||||
|
|
||||||
|
// Iterate the dataset and get each row
|
||||||
|
std::unordered_map<std::string, mindspore::MSTensor> row;
|
||||||
|
ASSERT_OK(iter->GetNextRow(&row));
|
||||||
|
|
||||||
|
uint64_t i = 0;
|
||||||
|
while (row.size() != 0) {
|
||||||
|
i++;
|
||||||
|
auto image = row["image"];
|
||||||
|
MS_LOG(INFO) << "Tensor image shape: " << image.Shape();
|
||||||
|
ASSERT_OK(iter->GetNextRow(&row));
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(i, 5);
|
||||||
|
|
||||||
|
// Manually terminate the pipeline
|
||||||
|
iter->Stop();
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
Testing HorizontalFlip Python API
|
Testing HorizontalFlip Python API
|
||||||
"""
|
"""
|
||||||
import cv2
|
import cv2
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
import mindspore.dataset as ds
|
import mindspore.dataset as ds
|
||||||
import mindspore.dataset.vision as vision
|
import mindspore.dataset.vision as vision
|
||||||
|
@ -26,6 +27,14 @@ from util import visualize_image, diff_mse
|
||||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
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"
|
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||||
IMAGE_FILE = "../data/dataset/apple.jpg"
|
IMAGE_FILE = "../data/dataset/apple.jpg"
|
||||||
|
FOUR_DIM_DATA = [[[[1, 2, 3], [3, 4, 3]], [[5, 6, 3], [7, 8, 3]]],
|
||||||
|
[[[9, 10, 3], [11, 12, 3]], [[13, 14, 3], [15, 16, 3]]]]
|
||||||
|
FIVE_DIM_DATA = [[[[[1, 2, 3], [3, 4, 3]], [[5, 6, 3], [7, 8, 3]]],
|
||||||
|
[[[9, 10, 3], [11, 12, 3]], [[13, 14, 3], [15, 16, 3]]]]]
|
||||||
|
FOUR_DIM_RES = [[[[3, 4, 3], [1, 2, 3]], [[7, 8, 3], [5, 6, 3]]],
|
||||||
|
[[[11, 12, 3], [9, 10, 3]], [[15, 16, 3], [13, 14, 3]]]]
|
||||||
|
FIVE_DIM_RES = [[[[[3, 4, 3], [1, 2, 3]], [[7, 8, 3], [5, 6, 3]]],
|
||||||
|
[[[11, 12, 3], [9, 10, 3]], [[15, 16, 3], [13, 14, 3]]]]]
|
||||||
|
|
||||||
|
|
||||||
def test_horizontal_flip_pipeline(plot=False):
|
def test_horizontal_flip_pipeline(plot=False):
|
||||||
|
@ -78,6 +87,112 @@ def test_horizontal_flip_eager():
|
||||||
assert mse == 0
|
assert mse == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_flip_video_op_1d():
|
||||||
|
"""
|
||||||
|
Feature: HorizontalFlip op
|
||||||
|
Description: Test HorizontalFlip op by processing tensor with dim 1
|
||||||
|
Expectation: Error is raised as expected
|
||||||
|
"""
|
||||||
|
logger.info("Test HorizontalFlip with 1 dimension input")
|
||||||
|
data = [1]
|
||||||
|
input_mindspore = np.array(data).astype(np.uint8)
|
||||||
|
horizontal_flip_op = vision.HorizontalFlip()
|
||||||
|
try:
|
||||||
|
horizontal_flip_op(input_mindspore)
|
||||||
|
except RuntimeError as e:
|
||||||
|
logger.info("Got an exception in DE: {}".format(str(e)))
|
||||||
|
assert "HorizontalFlip: the image tensor should have at least two dimensions. You may need to perform " \
|
||||||
|
"Decode first." in str(e)
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_flip_video_op_4d():
|
||||||
|
"""
|
||||||
|
Feature: HorizontalFlip op
|
||||||
|
Description: Test HorizontalFlip op by processing tensor with dim more than 3 (dim 4)
|
||||||
|
Expectation: The dataset is processed successfully
|
||||||
|
"""
|
||||||
|
logger.info("Test HorizontalFlip with 4 dimension input")
|
||||||
|
input_4_dim = np.array(FOUR_DIM_DATA).astype(np.uint8)
|
||||||
|
input_4_shape = input_4_dim.shape
|
||||||
|
num_batch = input_4_shape[0]
|
||||||
|
out_4_list = []
|
||||||
|
batch_1d = 0
|
||||||
|
while batch_1d < num_batch:
|
||||||
|
out_4_list.append(cv2.flip(input_4_dim[batch_1d], 1))
|
||||||
|
batch_1d += 1
|
||||||
|
out_4_cv = np.array(out_4_list).astype(np.uint8)
|
||||||
|
horizontal_flip_op = vision.HorizontalFlip()
|
||||||
|
out_4_mindspore = horizontal_flip_op(input_4_dim)
|
||||||
|
|
||||||
|
mse = diff_mse(out_4_mindspore, out_4_cv)
|
||||||
|
assert mse < 0.001
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_flip_video_op_5d():
|
||||||
|
"""
|
||||||
|
Feature: HorizontalFlip op
|
||||||
|
Description: Test HorizontalFlip op by processing tensor with dim more than 3 (dim 5)
|
||||||
|
Expectation: The dataset is processed successfully
|
||||||
|
"""
|
||||||
|
logger.info("Test HorizontalFlip with 5 dimension input")
|
||||||
|
input_5_dim = np.array(FIVE_DIM_DATA).astype(np.uint8)
|
||||||
|
input_5_shape = input_5_dim.shape
|
||||||
|
num_batch_1d = input_5_shape[0]
|
||||||
|
num_batch_2d = input_5_shape[1]
|
||||||
|
out_5_list = []
|
||||||
|
batch_1d = 0
|
||||||
|
batch_2d = 0
|
||||||
|
while batch_1d < num_batch_1d:
|
||||||
|
while batch_2d < num_batch_2d:
|
||||||
|
out_5_list.append(cv2.flip(input_5_dim[batch_1d][batch_2d], 1))
|
||||||
|
batch_2d += 1
|
||||||
|
batch_1d += 1
|
||||||
|
out_5_cv = np.array(out_5_list).astype(np.uint8)
|
||||||
|
horizontal_flip_op = vision.HorizontalFlip()
|
||||||
|
out_5_mindspore = horizontal_flip_op(input_5_dim)
|
||||||
|
|
||||||
|
mse = diff_mse(out_5_mindspore, out_5_cv)
|
||||||
|
assert mse < 0.001
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_flip_video_op_precision_eager():
|
||||||
|
"""
|
||||||
|
Feature: HorizontalFlip op
|
||||||
|
Description: Test HorizontalFlip op by processing tensor with dim more than 3 (dim 4) in eager mode
|
||||||
|
Expectation: The dataset is processed successfully
|
||||||
|
"""
|
||||||
|
logger.info("Test HorizontalFlip eager with 4 dimension input")
|
||||||
|
input_mindspore = np.array(FOUR_DIM_DATA).astype(np.uint8)
|
||||||
|
|
||||||
|
horizontal_flip_op = vision.HorizontalFlip()
|
||||||
|
out_mindspore = horizontal_flip_op(input_mindspore)
|
||||||
|
mse = diff_mse(out_mindspore, np.array(FOUR_DIM_RES).astype(np.uint8))
|
||||||
|
assert mse < 0.001
|
||||||
|
|
||||||
|
|
||||||
|
def test_horizontal_flip_video_op_precision_pipeline():
|
||||||
|
"""
|
||||||
|
Feature: HorizontalFlip op
|
||||||
|
Description: Test HorizontalFlip op by processing tensor with dim more than 3 (dim 5) in pipeline mode
|
||||||
|
Expectation: The dataset is processed successfully
|
||||||
|
"""
|
||||||
|
logger.info("Test HorizontalFlip pipeline with 5 dimension input")
|
||||||
|
data = np.array(FIVE_DIM_DATA).astype(np.uint8)
|
||||||
|
expand_data = np.expand_dims(data, axis=0)
|
||||||
|
|
||||||
|
dataset = ds.NumpySlicesDataset(expand_data, column_names=["col1"], shuffle=False)
|
||||||
|
horizontal_flip_op = vision.HorizontalFlip()
|
||||||
|
dataset = dataset.map(operations=horizontal_flip_op, input_columns=["col1"])
|
||||||
|
for item in dataset.create_dict_iterator(output_numpy=True):
|
||||||
|
mse = diff_mse(item["col1"], np.array(FIVE_DIM_RES).astype(np.uint8))
|
||||||
|
assert mse < 0.001
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test_horizontal_flip_pipeline(plot=False)
|
test_horizontal_flip_pipeline(plot=False)
|
||||||
test_horizontal_flip_eager()
|
test_horizontal_flip_eager()
|
||||||
|
test_horizontal_flip_video_op_1d()
|
||||||
|
test_horizontal_flip_video_op_4d()
|
||||||
|
test_horizontal_flip_video_op_5d()
|
||||||
|
test_horizontal_flip_video_op_precision_eager()
|
||||||
|
test_horizontal_flip_video_op_precision_pipeline()
|
||||||
|
|
Loading…
Reference in New Issue