!12355 dataset: Create C++ API classes for vision transform ops

From: @cathwong
Reviewed-by: 
Signed-off-by:
pull/12355/MERGE
mindspore-ci-bot 4 years ago committed by Gitee
commit 3805f0dfeb

@ -33,6 +33,7 @@
namespace mindspore {
namespace dataset {
// FIXME - Temporarily overload Execute to support both TensorOperation and TensorTransform
Execute::Execute(std::shared_ptr<TensorOperation> op, std::string deviceType) {
ops_.emplace_back(std::move(op));
device_type_ = deviceType;
@ -49,6 +50,63 @@ Execute::Execute(std::shared_ptr<TensorOperation> op, std::string deviceType) {
#endif
}
Execute::Execute(std::shared_ptr<TensorTransform> op, std::string deviceType) {
// Convert op from TensorTransform to TensorOperation
std::shared_ptr<TensorOperation> operation = op->Parse();
ops_.emplace_back(std::move(operation));
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
/*
Execute::Execute(TensorTransform op, std::string deviceType) {
// Convert op from TensorTransform to TensorOperation
std::shared_ptr<TensorOperation> operation = op.Parse();
ops_.emplace_back(std::move(operation));
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
*/
// Execute function for the example case: auto decode(new vision::Decode());
Execute::Execute(TensorTransform *op, std::string deviceType) {
// Convert op from TensorTransform to TensorOperation
std::shared_ptr<TensorOperation> operation = op->Parse();
ops_.emplace_back(std::move(operation));
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string deviceType)
: ops_(std::move(ops)), device_type_(deviceType) {
MS_LOG(INFO) << "Running Device: " << device_type_;
@ -64,6 +122,64 @@ Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string
#endif
}
Execute::Execute(std::vector<std::shared_ptr<TensorTransform>> ops, std::string deviceType) {
// Convert ops from TensorTransform to TensorOperation
(void)std::transform(
ops.begin(), ops.end(), std::back_inserter(ops_),
[](std::shared_ptr<TensorTransform> operation) -> std::shared_ptr<TensorOperation> { return operation->Parse(); });
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
Execute::Execute(const std::vector<std::reference_wrapper<TensorTransform>> ops, std::string deviceType) {
// Convert ops from TensorTransform to TensorOperation
(void)std::transform(
ops.begin(), ops.end(), std::back_inserter(ops_),
[](TensorTransform &operation) -> std::shared_ptr<TensorOperation> { return operation.Parse(); });
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
// Execute function for the example vector case: auto decode(new vision::Decode());
Execute::Execute(std::vector<TensorTransform *> ops, std::string deviceType) {
// Convert ops from TensorTransform to TensorOperation
(void)std::transform(
ops.begin(), ops.end(), std::back_inserter(ops_),
[](TensorTransform *operation) -> std::shared_ptr<TensorOperation> { return operation->Parse(); });
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
device_resource_ = std::make_shared<AscendResource>();
Status rc = device_resource_->InitResource();
if (!rc.IsOk()) {
device_resource_ = nullptr;
MS_LOG(ERROR) << "Initialize Ascend310 resource fail";
}
}
#endif
}
Execute::~Execute() {
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {

File diff suppressed because it is too large Load Diff

@ -33,9 +33,16 @@ namespace dataset {
class Execute {
public:
/// \brief Constructor
// FIXME - Temporarily overload Execute to support both TensorOperation and TensorTransform
explicit Execute(std::shared_ptr<TensorOperation> op, std::string deviceType = "CPU");
explicit Execute(std::shared_ptr<TensorTransform> op, std::string deviceType = "CPU");
// explicit Execute(TensorTransform op, std::string deviceType = "CPU");
explicit Execute(TensorTransform *op, std::string deviceType = "CPU");
explicit Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string deviceType = "CPU");
explicit Execute(std::vector<std::shared_ptr<TensorTransform>> ops, std::string deviceType = "CPU");
explicit Execute(const std::vector<std::reference_wrapper<TensorTransform>> ops, std::string deviceType = "CPU");
explicit Execute(std::vector<TensorTransform *> ops, std::string deviceType = "CPU");
/// \brief Destructor
~Execute();

@ -31,6 +31,8 @@
namespace mindspore {
namespace dataset {
// Abstract class to represent a tensor transform operation in the data pipeline.
/// \class TensorTransform transforms.h
/// \brief A base class to represent a tensor transform operation in the data pipeline.
class TensorTransform : public std::enable_shared_from_this<TensorTransform> {
public:
/// \brief Constructor

File diff suppressed because it is too large Load Diff

@ -26,69 +26,141 @@
#include "minddata/dataset/include/constants.h"
#include "minddata/dataset/include/transforms.h"
// FIXME - This internal IR header will be removed when external API classes are provided
#include "minddata/dataset/kernels/ir/vision/vision_ir.h"
namespace mindspore {
namespace dataset {
// Transform operations for performing computer vision.
namespace vision {
// Transform Op classes (in alphabetical order)
class CenterCropOperation;
class CropOperation;
class DecodeOperation;
class NormalizeOperation;
class ResizeOperation;
// Forward Declarations
class RotateOperation;
/// \brief Function to create a CenterCrop TensorOperation.
/// \brief CenterCrop TensorTransform.
/// \notes Crops the input image at the center to the given size.
/// \param[in] size A vector representing the output size of the cropped image.
/// If size is a single value, a square crop of size (size, size) is returned.
/// If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<CenterCropOperation> CenterCrop(std::vector<int32_t> size);
class CenterCrop : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] size A vector representing the output size of the cropped image.
/// If size is a single value, a square crop of size (size, size) is returned.
/// If size has 2 values, it should be (height, width).
explicit CenterCrop(std::vector<int32_t> size);
/// \brief Destructor.
~CenterCrop() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
/// \brief Function to create a Crop TensorOp
private:
std::vector<int32_t> size_;
};
/// \brief Crop TensorTransform.
/// \notes Crop an image based on location and crop size
/// \param[in] coordinates Starting location of crop. Must be a vector of two values, in the form of {x_coor, y_coor}
/// \param[in] size Size of the cropped area.
/// If size is a single value, a square crop of size (size, size) is returned.
/// If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOp
std::shared_ptr<CropOperation> Crop(std::vector<int32_t> coordinates, std::vector<int32_t> size);
/// \brief Function to create a Decode TensorOperation.
class Crop : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] coordinates Starting location of crop. Must be a vector of two values, in the form of {x_coor, y_coor}
/// \param[in] size Size of the cropped area.
/// If size is a single value, a square crop of size (size, size) is returned.
/// If size has 2 values, it should be (height, width).
Crop(std::vector<int32_t> coordinates, std::vector<int32_t> size);
/// \brief Destructor.
~Crop() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
std::vector<int32_t> coordinates_;
std::vector<int32_t> size_;
};
/// \brief Decode TensorTransform.
/// \notes Decode the input image in RGB mode.
/// \param[in] rgb A boolean of whether to decode in RGB mode or not.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DecodeOperation> Decode(bool rgb = true);
class Decode : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] rgb A boolean of whether to decode in RGB mode or not.
explicit Decode(bool rgb = true);
/// \brief Destructor.
~Decode() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
bool rgb_;
};
/// \brief Function to create a Normalize TensorOperation.
/// \brief Normalize TensorTransform.
/// \notes Normalize the input image with respect to mean and standard deviation.
/// \param[in] mean A vector of mean values for each channel, w.r.t channel order.
/// The mean values must be in range [0.0, 255.0].
/// \param[in] std A vector of standard deviations for each channel, w.r.t. channel order.
/// The standard deviation values must be in range (0.0, 255.0]
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<NormalizeOperation> Normalize(std::vector<float> mean, std::vector<float> std);
/// \brief Function to create a Resize TensorOperation.
class Normalize : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] mean A vector of mean values for each channel, w.r.t channel order.
/// The mean values must be in range [0.0, 255.0].
/// \param[in] std A vector of standard deviations for each channel, w.r.t. channel order.
/// The standard deviation values must be in range (0.0, 255.0]
Normalize(std::vector<float> mean, std::vector<float> std);
/// \brief Destructor.
~Normalize() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
std::vector<float> mean_;
std::vector<float> std_;
};
/// \brief Resize TensorTransform.
/// \notes Resize the input image to the given size.
/// \param[in] size A vector representing the output size of the resized image.
/// If size is a single value, the image will be resized to this value with
/// the same image aspect ratio. If size has 2 values, it should be (height, width).
/// \param[in] interpolation An enum for the mode of interpolation
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<ResizeOperation> Resize(std::vector<int32_t> size,
InterpolationMode interpolation = InterpolationMode::kLinear);
/// \brief Applies an rotate transformation to an image.
class Resize : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] size A vector representing the output size of the resized image.
/// If size is a single value, the image will be resized to this value with
/// the same image aspect ratio. If size has 2 values, it should be (height, width).
/// \param[in] interpolation An enum for the mode of interpolation
explicit Resize(std::vector<int32_t> size, InterpolationMode interpolation = InterpolationMode::kLinear);
/// \brief Destructor.
~Resize() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
std::vector<int32_t> size_;
InterpolationMode interpolation_;
};
/// \brief Rotate TensorTransform.
/// \notes Rotate the input image using a specified angle id.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<RotateOperation> Rotate();
class Rotate : public TensorTransform {
public:
/// \brief Constructor.
Rotate();
/// \brief Destructor.
~Rotate() = default;
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;
private:
std::shared_ptr<RotateOperation> op_;
};
} // namespace vision
} // namespace dataset

@ -542,6 +542,11 @@ Status RandomColorOperation::ValidateParams() {
return Status::OK();
}
std::shared_ptr<TensorOp> RandomColorOperation::Build() {
std::shared_ptr<RandomColorOp> tensor_op = std::make_shared<RandomColorOp>(t_lb_, t_ub_);
return tensor_op;
}
Status RandomColorOperation::to_json(nlohmann::json *out_json) {
(*out_json)["degrees"] = std::vector<float>{t_lb_, t_ub_};
return Status::OK();

@ -79,51 +79,6 @@ constexpr char kSoftDvppDecodeResizeJpegOperation[] = "SoftDvppDecodeResizeJpeg"
constexpr char kSwapRedBlueOperation[] = "SwapRedBlue";
constexpr char kUniformAugOperation[] = "UniformAug";
// Transform Op classes (in alphabetical order)
class AutoContrastOperation;
class BoundingBoxAugmentOperation;
class CenterCropOperation;
class CropOperation;
class CutMixBatchOperation;
class CutOutOperation;
class DecodeOperation;
class EqualizeOperation;
class HwcToChwOperation;
class InvertOperation;
class MixUpBatchOperation;
class NormalizeOperation;
class NormalizePadOperation;
class PadOperation;
class RandomAffineOperation;
class RandomColorAdjustOperation;
class RandomColorOperation;
class RandomCropDecodeResizeOperation;
class RandomCropOperation;
class RandomCropWithBBoxOperation;
class RandomHorizontalFlipOperation;
class RandomHorizontalFlipWithBBoxOperation;
class RandomPosterizeOperation;
class RandomResizedCropOperation;
class RandomResizedCropWithBBoxOperation;
class RandomResizeOperation;
class RandomResizeWithBBoxOperation;
class RandomRotationOperation;
class RandomSelectSubpolicyOperation;
class RandomSharpnessOperation;
class RandomSolarizeOperation;
class RandomVerticalFlipOperation;
class RandomVerticalFlipWithBBoxOperation;
class RescaleOperation;
class ResizeOperation;
class ResizeWithBBoxOperation;
class RgbaToBgrOperation;
class RgbaToRgbOperation;
class RotateOperation;
class SoftDvppDecodeRandomCropResizeJpegOperation;
class SoftDvppDecodeResizeJpegOperation;
class SwapRedBlueOperation;
class UniformAugOperation;
/* ####################################### Derived TensorOperation classes ################################# */
class AutoContrastOperation : public TensorOperation {

@ -18,6 +18,7 @@
#include "common/common_test.h"
#include "include/api/types.h"
#include "minddata/dataset/include/execute.h"
#include "minddata/dataset/include/transforms.h"
#include "minddata/dataset/include/vision.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/include/vision_ascend.h"
@ -28,6 +29,7 @@
#include "include/api/context.h"
using namespace mindspore;
using namespace mindspore::dataset;
using namespace mindspore::dataset::vision;
class TestDE : public ST::Common {
@ -42,9 +44,13 @@ TEST_F(TestDE, TestResNetPreprocess) {
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform operations
mindspore::dataset::Execute Transform(
{Decode(), Resize({224, 224}),
Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}), HWC2CHW()});
auto decode(new vision::Decode());
auto resize(new vision::Resize({224, 224}));
auto normalize(
new vision::Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}));
auto hwc2chw(new vision::HWC2CHW());
mindspore::dataset::Execute Transform({decode, resize, normalize, hwc2chw});
// Apply transform on images
Status rc = Transform(image, &image);

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2020-2021 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.
@ -61,7 +61,7 @@ TEST_F(MindDataTestCacheOp, DISABLED_TestCacheCApiNestedCache) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> decode_op = vision::Decode();
std::shared_ptr<TensorTransform> decode_op = std::make_shared<vision::Decode>();
EXPECT_NE(decode_op, nullptr);
// Create a Map operation on ds

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2020-2021 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.
@ -587,10 +587,10 @@ TEST_F(MindDataTestPipeline, TestFilterSuccess1) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> decode_op = vision::Decode(true);
std::shared_ptr<TensorTransform> decode_op = std::make_shared<vision::Decode>(true);
EXPECT_NE(decode_op, nullptr);
std::shared_ptr<TensorOperation> resize_op = vision::Resize({64, 64});
std::shared_ptr<TensorTransform> resize_op(new vision::Resize({64, 64}));
EXPECT_NE(resize_op, nullptr);
// Create a Map operation on ds
@ -888,7 +888,7 @@ TEST_F(MindDataTestPipeline, TestProjectMap) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_vertical_flip_op = vision::RandomVerticalFlip(0.5);
std::shared_ptr<TensorTransform> random_vertical_flip_op = std::make_shared<vision::RandomVerticalFlip>(0.5);
EXPECT_NE(random_vertical_flip_op, nullptr);
// Create a Map operation on ds
@ -937,7 +937,7 @@ TEST_F(MindDataTestPipeline, TestProjectDuplicateColumnFail) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_vertical_flip_op = vision::RandomVerticalFlip(0.5);
std::shared_ptr<TensorTransform> random_vertical_flip_op = std::make_shared<vision::RandomVerticalFlip>(0.5);
EXPECT_NE(random_vertical_flip_op, nullptr);
// Create a Map operation on ds
@ -966,7 +966,7 @@ TEST_F(MindDataTestPipeline, TestMapDuplicateColumnFail) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_vertical_flip_op = vision::RandomVerticalFlip(0.5);
std::shared_ptr<TensorTransform> random_vertical_flip_op = std::make_shared<vision::RandomVerticalFlip>(0.5);
EXPECT_NE(random_vertical_flip_op, nullptr);
// Create a Map operation on ds
@ -1011,7 +1011,7 @@ TEST_F(MindDataTestPipeline, TestProjectMapAutoInjection) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> resize_op = vision::Resize({30, 30});
std::shared_ptr<TensorTransform> resize_op(new vision::Resize({30, 30}));
EXPECT_NE(resize_op, nullptr);
// Create a Map operation on ds
@ -1586,10 +1586,10 @@ TEST_F(MindDataTestPipeline, TestTensorOpsAndMap) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> resize_op = vision::Resize({30, 30});
std::shared_ptr<TensorTransform> resize_op(new vision::Resize({30, 30}));
EXPECT_NE(resize_op, nullptr);
std::shared_ptr<TensorOperation> center_crop_op = vision::CenterCrop({16, 16});
std::shared_ptr<TensorTransform> center_crop_op(new vision::CenterCrop({16, 16}));
EXPECT_NE(center_crop_op, nullptr);
// Create a Map operation on ds

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2020-2021 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.
@ -43,7 +43,7 @@ TEST_F(MindDataTestPipeline, TestTFRecordDatasetBasic) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_horizontal_flip_op = vision::RandomHorizontalFlip(0.5);
std::shared_ptr<TensorTransform> random_horizontal_flip_op = std::make_shared<vision::RandomHorizontalFlip>(0.5);
EXPECT_NE(random_horizontal_flip_op, nullptr);
// Create a Map operation on ds
@ -98,7 +98,7 @@ TEST_F(MindDataTestPipeline, TestTFRecordDatasetBasicGetters) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_horizontal_flip_op = vision::RandomHorizontalFlip(0.5);
std::shared_ptr<TensorTransform> random_horizontal_flip_op = std::make_shared<vision::RandomHorizontalFlip>(0.5);
EXPECT_NE(random_horizontal_flip_op, nullptr);
// Create a Map operation on ds

@ -35,7 +35,7 @@ TEST_F(MindDataTestPipeline, TestComposeSuccess) {
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, false, RandomSampler(false, 3));
EXPECT_NE(ds, nullptr);
/* FIXME - Disable until proper external API for Compose is provided
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> compose = transforms::Compose({vision::Decode(), vision::Resize({777, 777})});
EXPECT_NE(compose, nullptr);
@ -69,11 +69,12 @@ TEST_F(MindDataTestPipeline, TestComposeSuccess) {
// Manually terminate the pipeline
iter->Stop();
*/
}
TEST_F(MindDataTestPipeline, TestComposeFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestComposeFail with invalid transform.";
/* FIXME - Disable until proper external API for Compose is provided
// Resize: Non-positive size value: -1 at element: 0
// Compose: transform ops must not be null
std::shared_ptr<TensorOperation> compose1 = transforms::Compose({vision::Decode(), vision::Resize({-1})});
@ -86,6 +87,7 @@ TEST_F(MindDataTestPipeline, TestComposeFail) {
// Compose: transform list must not be empty
std::shared_ptr<TensorOperation> compose3 = transforms::Compose({});
EXPECT_EQ(compose3, nullptr);
*/
}
TEST_F(MindDataTestPipeline, TestDuplicateSuccess) {
@ -137,7 +139,7 @@ TEST_F(MindDataTestPipeline, TestOneHotSuccess1) {
EXPECT_NE(ds, nullptr);
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> hwc_to_chw = vision::HWC2CHW();
std::shared_ptr<TensorTransform> hwc_to_chw = std::make_shared<vision::HWC2CHW>();
EXPECT_NE(hwc_to_chw, nullptr);
// Create a Map operation on ds
@ -157,8 +159,8 @@ TEST_F(MindDataTestPipeline, TestOneHotSuccess1) {
ds = ds->Map({one_hot_op}, {"label"});
EXPECT_NE(ds, nullptr);
std::shared_ptr<TensorOperation> cutmix_batch_op =
vision::CutMixBatch(mindspore::dataset::ImageBatchFormat::kNCHW, 1.0, 1.0);
std::shared_ptr<TensorTransform> cutmix_batch_op =
std::make_shared<vision::CutMixBatch>(mindspore::dataset::ImageBatchFormat::kNCHW, 1.0, 1.0);
EXPECT_NE(cutmix_batch_op, nullptr);
// Create a Map operation on ds
@ -215,7 +217,7 @@ TEST_F(MindDataTestPipeline, TestOneHotSuccess2) {
ds = ds->Map({one_hot_op}, {"label"});
EXPECT_NE(ds, nullptr);
std::shared_ptr<TensorOperation> mixup_batch_op = vision::MixUpBatch(2.0);
std::shared_ptr<TensorTransform> mixup_batch_op = std::make_shared<vision::MixUpBatch>(2.0);
EXPECT_NE(mixup_batch_op, nullptr);
// Create a Map operation on ds
@ -294,7 +296,7 @@ TEST_F(MindDataTestPipeline, TestRandomApplySuccess) {
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 5));
EXPECT_NE(ds, nullptr);
/* FIXME - Disable until proper external API for RandomApply is provided
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_apply = transforms::RandomApply({vision::Resize({777, 777})}, 0.8);
EXPECT_NE(random_apply, nullptr);
@ -326,11 +328,12 @@ TEST_F(MindDataTestPipeline, TestRandomApplySuccess) {
// Manually terminate the pipeline
iter->Stop();
*/
}
TEST_F(MindDataTestPipeline, TestRandomApplyFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomApplyFail with invalid transform.";
/* FIXME - Disable until proper external API for RandomApply is provided
// Resize: Non-positive size value: -1 at element: 0
// RandomApply: transform ops must not be null
std::shared_ptr<TensorOperation> random_apply1 = transforms::RandomApply({vision::Decode(), vision::Resize({-1})});
@ -347,6 +350,7 @@ TEST_F(MindDataTestPipeline, TestRandomApplyFail) {
// RandomApply: Probability has to be between 0 and 1
std::shared_ptr<TensorOperation> random_apply4 = transforms::RandomApply({vision::Resize({100})}, -1);
EXPECT_EQ(random_apply4, nullptr);
*/
}
TEST_F(MindDataTestPipeline, TestRandomChoiceSuccess) {
@ -356,7 +360,7 @@ TEST_F(MindDataTestPipeline, TestRandomChoiceSuccess) {
std::string folder_path = datasets_root_path_ + "/testPK/data/";
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, true, RandomSampler(false, 3));
EXPECT_NE(ds, nullptr);
/* FIXME - Disable until proper external API for RandomChoice is provided
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> random_choice =
transforms::RandomChoice({vision::Resize({777, 777}), vision::Resize({888, 888})});
@ -389,11 +393,12 @@ TEST_F(MindDataTestPipeline, TestRandomChoiceSuccess) {
// Manually terminate the pipeline
iter->Stop();
*/
}
TEST_F(MindDataTestPipeline, TestRandomChoiceFail) {
MS_LOG(INFO) << "Doing MindDataTestPipeline-TestRandomChoiceFail with invalid transform.";
/* FIXME - Disable until proper external API for RandomChoice is provided
// Resize: Non-positive size value: -1 at element: 0
// RandomChoice: transform ops must not be null
std::shared_ptr<TensorOperation> random_choice1 = transforms::RandomChoice({vision::Decode(), vision::Resize({-1})});
@ -406,6 +411,7 @@ TEST_F(MindDataTestPipeline, TestRandomChoiceFail) {
// RandomChoice: transform list must not be empty
std::shared_ptr<TensorOperation> random_choice3 = transforms::RandomChoice({});
EXPECT_EQ(random_choice3, nullptr);
*/
}
TEST_F(MindDataTestPipeline, TestTypeCastSuccess) {

File diff suppressed because it is too large Load Diff

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2020-2021 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.
@ -22,9 +22,9 @@
#include "utils/log_adapter.h"
using namespace mindspore::dataset;
using mindspore::MsLogLevel::INFO;
using mindspore::ExceptionType::NoExceptionType;
using mindspore::LogStream;
using mindspore::ExceptionType::NoExceptionType;
using mindspore::MsLogLevel::INFO;
class MindDataTestExecute : public UT::CVOP::CVOpCommon {
protected:
@ -41,9 +41,9 @@ TEST_F(MindDataTestExecute, TestComposeTransforms) {
auto image = mindspore::MSTensor(std::make_shared<DETensor>(de_tensor));
// Transform params
std::shared_ptr<TensorOperation> decode = vision::Decode();
std::shared_ptr<TensorOperation> center_crop = vision::CenterCrop({30});
std::shared_ptr<TensorOperation> rescale = vision::Rescale(1./3, 0.5);
std::shared_ptr<TensorTransform> decode = std::make_shared<vision::Decode>();
std::shared_ptr<TensorTransform> center_crop(new vision::CenterCrop({30}));
std::shared_ptr<TensorTransform> rescale = std::make_shared<vision::Rescale>(1. / 3, 0.5);
auto transform = Execute({decode, center_crop, rescale});
Status rc = transform(image, &image);
@ -52,3 +52,132 @@ TEST_F(MindDataTestExecute, TestComposeTransforms) {
EXPECT_EQ(30, image.Shape()[0]);
EXPECT_EQ(30, image.Shape()[1]);
}
TEST_F(MindDataTestExecute, TestTransformInput1) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestTransformInput1.";
// Test Execute with transform op input using API constructors, with std::shared_ptr<TensorTransform pointers,
// instantiated via mix of make_shared and new
// Read images
std::shared_ptr<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("data/dataset/apple.jpg", &de_tensor);
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform operations
std::shared_ptr<TensorTransform> decode = std::make_shared<vision::Decode>();
std::shared_ptr<TensorTransform> resize(new vision::Resize({224, 224}));
std::shared_ptr<TensorTransform> normalize(
new vision::Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}));
std::shared_ptr<TensorTransform> hwc2chw = std::make_shared<vision::HWC2CHW>();
mindspore::dataset::Execute Transform({decode, resize, normalize, hwc2chw});
// Apply transform on image
Status rc = Transform(image, &image);
// Check image info
ASSERT_TRUE(rc.IsOk());
ASSERT_EQ(image.Shape().size(), 3);
ASSERT_EQ(image.Shape()[0], 3);
ASSERT_EQ(image.Shape()[1], 224);
ASSERT_EQ(image.Shape()[2], 224);
}
TEST_F(MindDataTestExecute, TestTransformInput2) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestTransformInput2.";
// Test Execute with transform op input using API constructors, with std::shared_ptr<TensorTransform pointers,
// instantiated via new
// Read images
std::shared_ptr<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("data/dataset/apple.jpg", &de_tensor);
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform operations
std::shared_ptr<TensorTransform> decode(new vision::Decode());
std::shared_ptr<TensorTransform> resize(new vision::Resize({224, 224}));
std::shared_ptr<TensorTransform> normalize(
new vision::Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}));
std::shared_ptr<TensorTransform> hwc2chw(new vision::HWC2CHW());
mindspore::dataset::Execute Transform({decode, resize, normalize, hwc2chw});
// Apply transform on image
Status rc = Transform(image, &image);
// Check image info
ASSERT_TRUE(rc.IsOk());
ASSERT_EQ(image.Shape().size(), 3);
ASSERT_EQ(image.Shape()[0], 3);
ASSERT_EQ(image.Shape()[1], 224);
ASSERT_EQ(image.Shape()[2], 224);
}
TEST_F(MindDataTestExecute, TestTransformInput3) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestTransformInput3.";
// Test Execute with transform op input using API constructors, with auto pointers
// Read image
std::shared_ptr<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("data/dataset/apple.jpg", &de_tensor);
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform operations
auto decode(new vision::Decode()); // auto will create raw pointer to Decode class
auto resize(new vision::Resize({224, 224}));
auto normalize(
new vision::Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}));
auto hwc2chw(new vision::HWC2CHW());
std::vector<TensorTransform *> op_list = {decode, resize, normalize, hwc2chw};
mindspore::dataset::Execute Transform(op_list);
// Apply transform on image
Status rc = Transform(image, &image);
// Check image info
ASSERT_TRUE(rc.IsOk());
ASSERT_EQ(image.Shape().size(), 3);
ASSERT_EQ(image.Shape()[0], 3);
ASSERT_EQ(image.Shape()[1], 224);
ASSERT_EQ(image.Shape()[2], 224);
}
TEST_F(MindDataTestExecute, TestTransformInputSequential) {
MS_LOG(INFO) << "Doing MindDataTestExecute-TestTransformInputSequential.";
// Test Execute with transform op input using API constructors, with auto pointers;
// Apply 2 transformations sequentially, including single non-vector Transform op input
// Read images
std::shared_ptr<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("data/dataset/apple.jpg", &de_tensor);
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform#1 operations
auto decode(new vision::Decode()); // auto will create raw pointer to Decode class
auto resize(new vision::Resize({224, 224}));
auto normalize(
new vision::Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}));
std::vector<TensorTransform *> op_list = {decode, resize, normalize};
mindspore::dataset::Execute Transform(op_list);
// Apply transform#1 on image
Status rc = Transform(image, &image);
// Define transform#2 operations
auto hwc2chw(new vision::HWC2CHW());
TensorTransform *op_single = hwc2chw;
mindspore::dataset::Execute Transform2(op_single);
// Apply transform#2 on image
rc = Transform2(image, &image);
// Check image info
ASSERT_TRUE(rc.IsOk());
ASSERT_EQ(image.Shape().size(), 3);
ASSERT_EQ(image.Shape()[0], 3);
ASSERT_EQ(image.Shape()[1], 224);
ASSERT_EQ(image.Shape()[2], 224);
}

@ -39,8 +39,8 @@ TEST_F(MindDataTestTensorOpFusionPass, RandomCropDecodeResizeDisabled) {
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, false, SequentialSampler(0, 11));
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> decode = vision::Decode();
std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5});
std::shared_ptr<TensorTransform> decode(new vision::Decode());
std::shared_ptr<TensorTransform> random_resized_crop(new vision::RandomResizedCrop({5}));
ds = ds->Map({decode, random_resized_crop}, {"image"});
std::shared_ptr<DatasetNode> node = ds->IRNode();
@ -70,8 +70,8 @@ TEST_F(MindDataTestTensorOpFusionPass, RandomCropDecodeResizeEnabled) {
std::shared_ptr<Dataset> ds = ImageFolder(folder_path, false, SequentialSampler(0, 11));
// Create objects for the tensor ops
std::shared_ptr<TensorOperation> decode = vision::Decode();
std::shared_ptr<TensorOperation> random_resized_crop = vision::RandomResizedCrop({5});
std::shared_ptr<TensorTransform> decode(new vision::Decode());
std::shared_ptr<TensorTransform> random_resized_crop(new vision::RandomResizedCrop({5}));
ds = ds->Map({decode, random_resized_crop}, {"image"});
std::shared_ptr<DatasetNode> node = ds->IRNode();

@ -1,5 +1,5 @@
/**
* Copyright 2020 Huawei Technologies Co., Ltd
* Copyright 2020-2021 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.
@ -34,41 +34,44 @@ using mindspore::MsLogLevel::INFO;
class MindDataTestOptimizationPass : public UT::DatasetOpTesting {};
// TEST_F(MindDataTestOptimizationPass, MindDataTestAutoWorkerPass) {
// MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestAutoWorkerPass.";
//
// std::shared_ptr<SchemaObj> schema = std::make_shared<SchemaObj>();
// ASSERT_TRUE(schema->add_column("label", "uint32", {}));
// std::shared_ptr<Dataset> map_leaf = ImageFolder("dir")->SetNumWorkers(0);
// std::shared_ptr<Dataset> nonmap_leaf = RandomData(44, schema)->SetNumWorkers(0);
// std::shared_ptr<Dataset> batch = Zip({map_leaf, nonmap_leaf})->Batch(1)->SetNumWorkers(0);
// std::shared_ptr<Dataset> map = batch->Map({})->SetNumWorkers(0);
// // {ImageFolder, RandomData} -> zip -> batch
// EXPECT_EQ(map_leaf->IRNode()->num_workers(), 0);
// EXPECT_EQ(nonmap_leaf->IRNode()->num_workers(), 0);
// EXPECT_EQ(batch->IRNode()->num_workers(), 0);
// EXPECT_EQ(map->IRNode()->num_workers(), 0);
//
// std::unique_ptr<IRPass> pass = std::make_unique<AutoWorkerPass>();
// bool m = false;
// ASSERT_OK(pass->Run(map->IRNode(), &m));
//
// // checking that after this pass, num_workers are set correctly (aka a positive number)
// // It is hard to test a exact value because num_threads are different for different machine
// // however, this will for sure succeed bc regardless of the total threads on cpu, this would always be >= 1
// EXPECT_NE(map_leaf->IRNode()->num_workers(), 0);
// EXPECT_NE(nonmap_leaf->IRNode()->num_workers(), 0);
// EXPECT_NE(batch->IRNode()->num_workers(), 0);
// EXPECT_NE(map->IRNode()->num_workers(), 0);
// MS_LOG(DEBUG) << map_leaf->IRNode()->Name() << ": num_worker=" << map_leaf->IRNode()->num_workers();
// MS_LOG(DEBUG) << nonmap_leaf->IRNode()->Name() << ": num_worker=" << nonmap_leaf->IRNode()->num_workers();
// MS_LOG(DEBUG) << batch->IRNode()->Name() << ": num_worker=" << batch->IRNode()->num_workers();
// MS_LOG(DEBUG) << map->IRNode()->Name() << ": num_worker=" << map->IRNode()->num_workers();
//}
TEST_F(MindDataTestOptimizationPass, MindDataTestAutoWorkerPass) {
MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestAutoWorkerPass.";
std::shared_ptr<SchemaObj> schema = std::make_shared<SchemaObj>();
ASSERT_TRUE(schema->add_column("label", "uint32", {}));
std::shared_ptr<Dataset> map_leaf = ImageFolder("dir")->SetNumWorkers(0);
std::shared_ptr<Dataset> nonmap_leaf = RandomData(44, schema)->SetNumWorkers(0);
std::shared_ptr<Dataset> batch = Zip({map_leaf, nonmap_leaf})->Batch(1)->SetNumWorkers(0);
/* FIXME - Will uncomment out when full external API support is provided
std::shared_ptr<Dataset> map = batch->Map({})->SetNumWorkers(0);
// {ImageFolder, RandomData} -> zip -> batch
EXPECT_EQ(map_leaf->IRNode()->num_workers(), 0);
EXPECT_EQ(nonmap_leaf->IRNode()->num_workers(), 0);
EXPECT_EQ(batch->IRNode()->num_workers(), 0);
EXPECT_EQ(map->IRNode()->num_workers(), 0);
std::unique_ptr<IRPass> pass = std::make_unique<AutoWorkerPass>();
bool m = false;
ASSERT_OK(pass->Run(map->IRNode(), &m));
// checking that after this pass, num_workers are set correctly (aka a positive number)
// It is hard to test a exact value because num_threads are different for different machine
// however, this will for sure succeed bc regardless of the total threads on cpu, this would always be >= 1
EXPECT_NE(map_leaf->IRNode()->num_workers(), 0);
EXPECT_NE(nonmap_leaf->IRNode()->num_workers(), 0);
EXPECT_NE(batch->IRNode()->num_workers(), 0);
EXPECT_NE(map->IRNode()->num_workers(), 0);
MS_LOG(DEBUG) << map_leaf->IRNode()->Name() << ": num_worker=" << map_leaf->IRNode()->num_workers();
MS_LOG(DEBUG) << nonmap_leaf->IRNode()->Name() << ": num_worker=" << nonmap_leaf->IRNode()->num_workers();
MS_LOG(DEBUG) << batch->IRNode()->Name() << ": num_worker=" << batch->IRNode()->num_workers();
MS_LOG(DEBUG) << map->IRNode()->Name() << ": num_worker=" << map->IRNode()->num_workers();
*/
}
TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPass) {
MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestTensorFusionPass.";
std::string folder_path = datasets_root_path_ + "/testPK/data/";
/* FIXME - Will uncomment out when full external API support is provided
std::shared_ptr<Dataset> root =
ImageFolder(folder_path, false)->Map({vision::Decode(), vision::RandomResizedCrop({100})}, {"image"});
@ -82,11 +85,13 @@ TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPass) {
auto fused_ops = map_node->operations();
ASSERT_EQ(fused_ops.size(), 1);
ASSERT_EQ(fused_ops[0]->Name(), vision::kRandomCropDecodeResizeOperation);
*/
}
TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPassPreBuiltTensorOperation) {
MS_LOG(INFO) << "Doing MindDataTestOptimizationPass-MindDataTestTensorFusionPassPreBuiltTensorOperation.";
std::string folder_path = datasets_root_path_ + "/testPK/data/";
/* FIXME - Will uncomment out when full external API support is provided
// make prebuilt tensor operation
auto decode = std::make_shared<transforms::PreBuiltOperation>(vision::Decode()->Build());
auto resize = std::make_shared<transforms::PreBuiltOperation>(vision::RandomResizedCrop({100})->Build());
@ -102,4 +107,5 @@ TEST_F(MindDataTestOptimizationPass, MindDataTestTensorFusionPassPreBuiltTensorO
auto fused_ops = map_node->operations();
ASSERT_EQ(fused_ops.size(), 1);
ASSERT_EQ(fused_ops[0]->Name(), kRandomCropDecodeResizeOp);
*/
}

Loading…
Cancel
Save