From 465a69a70a7d032cf9979ff889a543c5c5eafeac Mon Sep 17 00:00:00 2001 From: Eric Date: Thu, 23 Jul 2020 11:35:58 -0400 Subject: [PATCH] Added crop signature, wip Added input check Added SwapRedBlue --- .../ccsrc/minddata/dataset/api/transforms.cc | 62 +++++++++++++++ .../minddata/dataset/include/transforms.h | 40 ++++++++++ .../dataset/kernels/image/CMakeLists.txt | 2 + .../minddata/dataset/kernels/image/crop_op.cc | 45 +++++++++++ .../minddata/dataset/kernels/image/crop_op.h | 63 +++++++++++++++ .../dataset/kernels/image/swap_red_blue_op.cc | 29 +++++++ .../dataset/kernels/image/swap_red_blue_op.h | 57 ++++++++++++++ .../minddata/dataset/kernels/tensor_op.h | 2 + tests/ut/cpp/dataset/CMakeLists.txt | 3 +- tests/ut/cpp/dataset/crop_op_test.cc | 77 +++++++++++++++++++ tests/ut/cpp/dataset/swap_red_blue_test.cc | 46 +++++++++++ 11 files changed, 425 insertions(+), 1 deletion(-) create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h create mode 100644 tests/ut/cpp/dataset/crop_op_test.cc create mode 100644 tests/ut/cpp/dataset/swap_red_blue_test.cc diff --git a/mindspore/ccsrc/minddata/dataset/api/transforms.cc b/mindspore/ccsrc/minddata/dataset/api/transforms.cc index 5b9bc70839..a68fc7747f 100644 --- a/mindspore/ccsrc/minddata/dataset/api/transforms.cc +++ b/mindspore/ccsrc/minddata/dataset/api/transforms.cc @@ -18,6 +18,7 @@ #include "minddata/dataset/kernels/image/image_utils.h" #include "minddata/dataset/kernels/image/center_crop_op.h" +#include "minddata/dataset/kernels/image/crop_op.h" #include "minddata/dataset/kernels/image/cut_out_op.h" #include "minddata/dataset/kernels/image/decode_op.h" #include "minddata/dataset/kernels/image/normalize_op.h" @@ -28,6 +29,7 @@ #include "minddata/dataset/kernels/image/random_rotation_op.h" #include "minddata/dataset/kernels/image/random_vertical_flip_op.h" #include "minddata/dataset/kernels/image/resize_op.h" +#include "minddata/dataset/kernels/image/swap_red_blue_op.h" #include "minddata/dataset/kernels/image/uniform_aug_op.h" namespace mindspore { @@ -49,6 +51,16 @@ std::shared_ptr CenterCrop(std::vector size) { return op; } +// Function to create CropOperation. +std::shared_ptr Crop(std::vector coordinates, std::vector size) { + auto op = std::make_shared(coordinates, size); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + // Function to create CutOutOp. std::shared_ptr CutOut(int32_t length, int32_t num_patches) { auto op = std::make_shared(length, num_patches); @@ -155,6 +167,16 @@ std::shared_ptr Resize(std::vector size, Interpolation return op; } +// Function to create SwapRedBlueOperation. +std::shared_ptr SwapRedBlue() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + // Function to create UniformAugOperation. std::shared_ptr UniformAugment(std::vector> transforms, int32_t num_ops) { @@ -192,6 +214,36 @@ std::shared_ptr CenterCropOperation::Build() { return tensor_op; } +// CropOperation. +CropOperation::CropOperation(std::vector coordinates, std::vector size) + : coordinates_(coordinates), size_(size) {} + +bool CropOperation::ValidateParams() { + // Do some input validation. + if (coordinates_.empty() || coordinates_.size() > 2) { + MS_LOG(ERROR) << "Crop: coordinates must be a vector of one or two values"; + return false; + } + if (size_.empty() || size_.size() > 2) { + MS_LOG(ERROR) << "Crop: size must be a vector of one or two values"; + return false; + } + return true; +} + +std::shared_ptr CropOperation::Build() { + int32_t x, y, height, width; + + x = coordinates_[0]; + y = coordinates_[1]; + + height = size_[0]; + width = size_[1]; + + std::shared_ptr tensor_op = std::make_shared(x, y, height, width); + return tensor_op; +} + // CutOutOperation CutOutOperation::CutOutOperation(int32_t length, int32_t num_patches) : length_(length), num_patches_(num_patches) {} @@ -472,6 +524,16 @@ std::shared_ptr ResizeOperation::Build() { return std::make_shared(height, width, interpolation_); } +// SwapRedBlueOperation. +SwapRedBlueOperation::SwapRedBlueOperation() {} + +bool SwapRedBlueOperation::ValidateParams() { return true; } + +std::shared_ptr SwapRedBlueOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + // UniformAugOperation UniformAugOperation::UniformAugOperation(std::vector> transforms, int32_t num_ops) : transforms_(transforms), num_ops_(num_ops) {} diff --git a/mindspore/ccsrc/minddata/dataset/include/transforms.h b/mindspore/ccsrc/minddata/dataset/include/transforms.h index 76bcc390f2..a8bade5396 100644 --- a/mindspore/ccsrc/minddata/dataset/include/transforms.h +++ b/mindspore/ccsrc/minddata/dataset/include/transforms.h @@ -58,6 +58,8 @@ class RandomRotationOperation; class PadOperation; class CutOutOperation; class RandomColorAdjustOperation; +class CropOperation; +class SwapRedBlueOperation; /// \brief Function to create a Normalize TensorOperation. /// \notes Normalize the input image with respect to mean and standard deviation. @@ -183,6 +185,18 @@ std::shared_ptr RandomColorAdjust(std::vector std::vector saturation = {1.0, 1.0}, std::vector hue = {0.0, 0.0}); +/// \brief Function to create a Crop TensorOp +/// \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. Must be a vector of two values, in the form of {height, width} +/// \return Shared pointer to the current TensorOp +std::shared_ptr Crop(std::vector coordinates, std::vector size); + +/// \brief Function to create a SwapRedBlue TensorOp +/// \notes Swaps the red and blue channels in image +/// \return Shared pointer to the current TensorOp +std::shared_ptr SwapRedBlue(); + /* ####################################### Derived TensorOperation classes ################################# */ class NormalizeOperation : public TensorOperation { @@ -373,6 +387,32 @@ class RandomColorAdjustOperation : public TensorOperation { std::vector saturation_; std::vector hue_; }; + +class CropOperation : public TensorOperation { + public: + CropOperation(std::vector coordinates, std::vector size); + + ~CropOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; + + private: + std::vector coordinates_; + std::vector size_; +}; + +class SwapRedBlueOperation : public TensorOperation { + public: + SwapRedBlueOperation(); + + ~SwapRedBlueOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; } // namespace vision } // namespace api } // namespace dataset diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt index a777730284..fc4a6790be 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt @@ -3,6 +3,7 @@ set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE add_library(kernels-image OBJECT auto_contrast_op.cc center_crop_op.cc + crop_op.cc cut_out_op.cc decode_op.cc equalize_op.cc @@ -28,6 +29,7 @@ add_library(kernels-image OBJECT rescale_op.cc resize_bilinear_op.cc resize_op.cc + swap_red_blue_op.cc uniform_aug_op.cc resize_with_bbox_op.cc random_resize_with_bbox_op.cc diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.cc new file mode 100644 index 0000000000..5d1853b78d --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.cc @@ -0,0 +1,45 @@ +/** + * Copyright 2020 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. + */ +#include "minddata/dataset/kernels/image/crop_op.h" + +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { + +Status CropOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + CHECK_FAIL_RETURN_UNEXPECTED(input->shape().Size() >= 2, "The shape size " + std::to_string(input->shape().Size()) + + " of input tensor is invalid"); + int32_t input_h = static_cast(input->shape()[0]); + int32_t input_w = static_cast(input->shape()[1]); + CHECK_FAIL_RETURN_UNEXPECTED(y_ + height_ <= input_h, "Crop height dimensions exceed image dimensions"); + CHECK_FAIL_RETURN_UNEXPECTED(x_ + width_ <= input_w, "Crop width dimensions exceed image dimensions"); + return Crop(input, output, x_, y_, height_, width_); +} + +Status CropOp::OutputShape(const std::vector &inputs, std::vector &outputs) { + RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs)); + outputs.clear(); + TensorShape out = TensorShape{height_, width_}; + if (inputs[0].Rank() == 2) outputs.emplace_back(out); + if (inputs[0].Rank() == 3) outputs.emplace_back(out.AppendDim(inputs[0][2])); + if (!outputs.empty()) return Status::OK(); + return Status(StatusCode::kUnexpectedError, "Input has a wrong shape"); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.h new file mode 100644 index 0000000000..35d3ebeda5 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/crop_op.h @@ -0,0 +1,63 @@ +/** + * Copyright 2020 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. + */ +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_CROP_OP_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_CROP_OP_H_ + +#include +#include +#include + +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class CropOp : public TensorOp { + public: + /// \brief Constructor to Crop Op + /// \param[in] x - the horizontal starting coordinate + /// \param[in] y - the vertical starting coordinate + /// \param[in] height - the height of the crop box + /// \param[in] width - the width of the crop box + explicit CropOp(int32_t x, int32_t y, int32_t height, int32_t width) : x_(x), y_(y), height_(height), width_(width) {} + + CropOp(const CropOp &rhs) = default; + + CropOp(CropOp &&rhs) = default; + + ~CropOp() override = default; + + void Print(std::ostream &out) const override { + out << "CropOp x: " << x_ << " y: " << y_ << " w: " << width_ << " h: " << height_; + } + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + Status OutputShape(const std::vector &inputs, std::vector &outputs) override; + + std::string Name() const override { return kCropOp; } + + protected: + int32_t x_; + int32_t y_; + int32_t height_; + int32_t width_; +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_CROP_OP_H_ diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.cc new file mode 100644 index 0000000000..cee93a323a --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.cc @@ -0,0 +1,29 @@ +/** + * Copyright 2020 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. + */ +#include "minddata/dataset/kernels/image/swap_red_blue_op.h" + +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { + +Status SwapRedBlueOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + return SwapRedAndBlue(input, output); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h new file mode 100644 index 0000000000..c42bbb80c7 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h @@ -0,0 +1,57 @@ +/** + * Copyright 2020 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. + */ +#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_SWAP_RED_BLUE_OP_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_SWAP_RED_BLUE_OP_H_ + +#include +#include +#include + +#include "minddata/dataset/core/tensor.h" +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/kernels/tensor_op.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { +class SwapRedBlueOp : public TensorOp { + public: + // SwapRedBlues the image to the output specified size. If only one value is provided, + // the it will crop the smaller size and maintains the aspect ratio. + // @param size1: the first size of output. If only this parameter is provided + // the smaller dimension will be cropd to this and then the other dimension changes + // such that the aspect ratio is maintained. + // @param size2: the second size of output. If this is also provided, the output size + // will be (size1, size2) + // @param InterpolationMode: the interpolation mode being used. + SwapRedBlueOp() {} + + SwapRedBlueOp(const SwapRedBlueOp &rhs) = default; + + SwapRedBlueOp(SwapRedBlueOp &&rhs) = default; + + ~SwapRedBlueOp() override = default; + + void Print(std::ostream &out) const override { out << "SwapRedBlueOp x"; } + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + std::string Name() const override { return kSwapRedBlueOp; } +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_SWAP_RED_BLUE_OP_H_ diff --git a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h index 1db0e7ab41..4c484369d5 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h @@ -92,6 +92,7 @@ constexpr char kBoundingBoxAugmentOp[] = "BoundingBoxAugmentOp"; constexpr char kDecodeOp[] = "DecodeOp"; constexpr char kCenterCropOp[] = "CenterCropOp"; constexpr char kCutOutOp[] = "CutOutOp"; +constexpr char kCropOp[] = "CropOp"; constexpr char kEqualizeOp[] = "EqualizeOp"; constexpr char kHwcToChwOp[] = "HwcToChwOp"; constexpr char kInvertOp[] = "InvertOp"; @@ -114,6 +115,7 @@ constexpr char kRescaleOp[] = "RescaleOp"; constexpr char kResizeBilinearOp[] = "ResizeBilinearOp"; constexpr char kResizeOp[] = "ResizeOp"; constexpr char kResizeWithBBoxOp[] = "ResizeWithBBoxOp"; +constexpr char kSwapRedBlueOp[] = "SwapRedBlueOp"; constexpr char kUniformAugOp[] = "UniformAugOp"; // text diff --git a/tests/ut/cpp/dataset/CMakeLists.txt b/tests/ut/cpp/dataset/CMakeLists.txt index 050cc79db3..9e166d110c 100644 --- a/tests/ut/cpp/dataset/CMakeLists.txt +++ b/tests/ut/cpp/dataset/CMakeLists.txt @@ -55,7 +55,7 @@ SET(DE_UT_SRCS resize_bilinear_op_test.cc resize_op_test.cc resize_with_bbox_op_test.cc - schema_test.cc + schema_test.cc shuffle_op_test.cc stand_alone_samplers_test.cc status_test.cc @@ -96,6 +96,7 @@ SET(DE_UT_SRCS sliding_window_op_test.cc epoch_ctrl_op_test.cc sentence_piece_vocab_op_test.cc + swap_red_blue_test.cc ) add_executable(de_ut_tests ${DE_UT_SRCS}) diff --git a/tests/ut/cpp/dataset/crop_op_test.cc b/tests/ut/cpp/dataset/crop_op_test.cc new file mode 100644 index 0000000000..0f365558a6 --- /dev/null +++ b/tests/ut/cpp/dataset/crop_op_test.cc @@ -0,0 +1,77 @@ +/** + * Copyright 2020 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. + */ +#include "common/common.h" +#include "common/cvop_common.h" +#include "minddata/dataset/kernels/image/crop_op.h" +#include "utils/log_adapter.h" + +using namespace mindspore::dataset; +using mindspore::MsLogLevel::INFO; +using mindspore::ExceptionType::NoExceptionType; +using mindspore::LogStream; + +class MindDataTestCropOp : public UT::CVOP::CVOpCommon { + protected: + MindDataTestCropOp() : CVOpCommon() {} + + std::shared_ptr output_tensor_; +}; + +TEST_F(MindDataTestCropOp, TestOp1) { + MS_LOG(INFO) << "Doing testCrop."; + // Crop params + int crop_height = 18; + int crop_width = 12; + std::unique_ptr op(new CropOp(0, 0, crop_height, crop_width)); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor_); + size_t actual = 0; + if (s == Status::OK()) { + actual = output_tensor_->shape()[0] * output_tensor_->shape()[1] * output_tensor_->shape()[2]; + } + EXPECT_EQ(crop_height, output_tensor_->shape()[1]); + EXPECT_EQ(actual, crop_height * crop_width * 3); + EXPECT_EQ(s, Status::OK()); +} + +TEST_F(MindDataTestCropOp, TestOp2) { + MS_LOG(INFO) << "Doing testCrop negative coordinates."; + // Crop params + unsigned int crop_height = 10; + unsigned int crop_width = 10; + + std::unique_ptr op( + new CropOp(-10, -10, crop_height, crop_width)); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor_); + EXPECT_EQ(false, s.IsOk()); + MS_LOG(INFO) << "testCrop coordinate exception end."; +} + +TEST_F(MindDataTestCropOp, TestOp3) { + MS_LOG(INFO) << "Doing testCrop size too large."; + // Crop params + unsigned int crop_height = 1200000; + unsigned int crop_width = 1200000; + + std::unique_ptr op( + new CropOp(0, 0, crop_height, crop_width)); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor_); + EXPECT_EQ(false, s.IsOk()); + MS_LOG(INFO) << "testCrop size exception end."; +} + diff --git a/tests/ut/cpp/dataset/swap_red_blue_test.cc b/tests/ut/cpp/dataset/swap_red_blue_test.cc new file mode 100644 index 0000000000..7a760ee5b1 --- /dev/null +++ b/tests/ut/cpp/dataset/swap_red_blue_test.cc @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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. + */ +#include "common/common.h" +#include "common/cvop_common.h" +#include "minddata/dataset/kernels/image/swap_red_blue_op.h" +#include "utils/log_adapter.h" + +using namespace mindspore::dataset; +using mindspore::MsLogLevel::INFO; +using mindspore::ExceptionType::NoExceptionType; +using mindspore::LogStream; + +class MindDataTestSwapRedBlueOp : public UT::CVOP::CVOpCommon { + protected: + MindDataTestSwapRedBlueOp() : CVOpCommon() {} + + std::shared_ptr output_tensor_; +}; + +TEST_F(MindDataTestSwapRedBlueOp, TestOp1) { + MS_LOG(INFO) << "Doing testSwapRedBlue."; + // SwapRedBlue params + std::unique_ptr op(new SwapRedBlueOp()); + EXPECT_TRUE(op->OneToOne()); + Status s = op->Compute(input_tensor_, &output_tensor_); + size_t actual = 0; + if (s == Status::OK()) { + actual = output_tensor_->shape()[0] * output_tensor_->shape()[1] * output_tensor_->shape()[2]; + } + EXPECT_EQ(actual, input_tensor_->shape()[0] * input_tensor_->shape()[1] * 3); + EXPECT_EQ(s, Status::OK()); +} +