From 6a41b44724e113aec9ba0e997a3793dc29b1bff1 Mon Sep 17 00:00:00 2001 From: eric Date: Tue, 11 Aug 2020 21:55:36 -0400 Subject: [PATCH] Added wrapper around color change function --- .../ccsrc/minddata/dataset/api/transforms.cc | 42 +++ .../minddata/dataset/include/transforms.h | 46 ++- .../dataset/kernels/image/CMakeLists.txt | 2 + .../dataset/kernels/image/image_utils.cc | 38 +++ .../dataset/kernels/image/image_utils.h | 319 +++++++++--------- .../dataset/kernels/image/rgba_to_bgr_op.cc | 29 ++ .../dataset/kernels/image/rgba_to_bgr_op.h | 43 +++ .../dataset/kernels/image/rgba_to_rgb_op.cc | 29 ++ .../dataset/kernels/image/rgba_to_rgb_op.h | 43 +++ .../dataset/kernels/image/swap_red_blue_op.h | 11 +- .../minddata/dataset/kernels/tensor_op.h | 4 +- tests/ut/cpp/dataset/CMakeLists.txt | 4 +- tests/ut/cpp/dataset/rgba_to_bgr_op_test.cc | 62 ++++ tests/ut/cpp/dataset/rgba_to_rgb_op_test.cc | 62 ++++ 14 files changed, 564 insertions(+), 170 deletions(-) create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.h create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.cc create mode 100644 mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.h create mode 100644 tests/ut/cpp/dataset/rgba_to_bgr_op_test.cc create mode 100644 tests/ut/cpp/dataset/rgba_to_rgb_op_test.cc diff --git a/mindspore/ccsrc/minddata/dataset/api/transforms.cc b/mindspore/ccsrc/minddata/dataset/api/transforms.cc index 3cab794933..ddb9cb564a 100644 --- a/mindspore/ccsrc/minddata/dataset/api/transforms.cc +++ b/mindspore/ccsrc/minddata/dataset/api/transforms.cc @@ -35,6 +35,8 @@ #include "minddata/dataset/kernels/image/random_solarize_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/rgba_to_bgr_op.h" +#include "minddata/dataset/kernels/image/rgba_to_rgb_op.h" #include "minddata/dataset/kernels/image/swap_red_blue_op.h" #include "minddata/dataset/kernels/image/uniform_aug_op.h" @@ -240,6 +242,26 @@ std::shared_ptr Resize(std::vector size, Interpolation return op; } +// Function to create RgbaToBgrOperation. +std::shared_ptr RGBA2BGR() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + +// Function to create RgbaToRgbOperation. +std::shared_ptr RGBA2RGB() { + auto op = std::make_shared(); + // Input validation + if (!op->ValidateParams()) { + return nullptr; + } + return op; +} + // Function to create SwapRedBlueOperation. std::shared_ptr SwapRedBlue() { auto op = std::make_shared(); @@ -743,6 +765,26 @@ std::shared_ptr ResizeOperation::Build() { return std::make_shared(height, width, interpolation_); } +// RgbaToBgrOperation. +RgbaToBgrOperation::RgbaToBgrOperation() {} + +bool RgbaToBgrOperation::ValidateParams() { return true; } + +std::shared_ptr RgbaToBgrOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + +// RgbaToRgbOperation. +RgbaToRgbOperation::RgbaToRgbOperation() {} + +bool RgbaToRgbOperation::ValidateParams() { return true; } + +std::shared_ptr RgbaToRgbOperation::Build() { + std::shared_ptr tensor_op = std::make_shared(); + return tensor_op; +} + // SwapRedBlueOperation. SwapRedBlueOperation::SwapRedBlueOperation() {} diff --git a/mindspore/ccsrc/minddata/dataset/include/transforms.h b/mindspore/ccsrc/minddata/dataset/include/transforms.h index 861cfdd0b6..fdf4e45f17 100644 --- a/mindspore/ccsrc/minddata/dataset/include/transforms.h +++ b/mindspore/ccsrc/minddata/dataset/include/transforms.h @@ -65,14 +65,16 @@ class RandomSharpnessOperation; class RandomSolarizeOperation; class RandomVerticalFlipOperation; class ResizeOperation; +class RgbaToBgrOperation; +class RgbaToRgbOperation; class SwapRedBlueOperation; class UniformAugOperation; /// \brief Function to create a CenterCrop TensorOperation. /// \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). +/// 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 CenterCrop(std::vector size); @@ -103,15 +105,15 @@ std::shared_ptr HWC2CHW(); /// \brief Function to create a MixUpBatch TensorOperation. /// \notes Apply MixUp transformation on an input batch of images and labels. The labels must be in one-hot format and -/// Batch must be called before calling this function. +/// Batch must be called before calling this function. /// \param[in] alpha hyperparameter of beta distribution (default = 1.0) /// \return Shared pointer to the current TensorOperation. std::shared_ptr MixUpBatch(float alpha = 1); /// \brief Function to create a Normalize TensorOperation. /// \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. -/// \param[in] std - a vector of standard deviations for each channel, w.r.t. channel order. +/// \param[in] mean A vector of mean values for each channel, w.r.t channel order. +/// \param[in] std A vector of standard deviations for each channel, w.r.t. channel order. /// \return Shared pointer to the current TensorOperation. std::shared_ptr Normalize(std::vector mean, std::vector std); @@ -230,8 +232,18 @@ std::shared_ptr RandomSolarize(uint8_t threshold_min = /// \return Shared pointer to the current TensorOperation. std::shared_ptr RandomVerticalFlip(float prob = 0.5); +/// \brief Function to create a RgbaToBgr TensorOperation. +/// \notes Changes the input 4 channel RGBA tensor to 3 channel BGR. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RGBA2BGR(); + +/// \brief Function to create a RgbaToRgb TensorOperation. +/// \notes Changes the input 4 channel RGBA tensor to 3 channel RGB. +/// \return Shared pointer to the current TensorOperation. +std::shared_ptr RGBA2RGB(); + /// \brief Function to create a Resize TensorOperation. -/// \notes Resize the input image to the given size.. +/// \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). @@ -520,6 +532,28 @@ class ResizeOperation : public TensorOperation { InterpolationMode interpolation_; }; +class RgbaToBgrOperation : public TensorOperation { + public: + RgbaToBgrOperation(); + + ~RgbaToBgrOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + +class RgbaToRgbOperation : public TensorOperation { + public: + RgbaToRgbOperation(); + + ~RgbaToRgbOperation() = default; + + std::shared_ptr Build() override; + + bool ValidateParams() override; +}; + class UniformAugOperation : public TensorOperation { public: explicit UniformAugOperation(std::vector> transforms, int32_t num_ops = 2); diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt b/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt index ffb1e22987..727067c9af 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt @@ -36,6 +36,8 @@ add_library(kernels-image OBJECT rescale_op.cc resize_bilinear_op.cc resize_op.cc + rgba_to_bgr_op.cc + rgba_to_rgb_op.cc sharpness_op.cc solarize_op.cc swap_red_blue_op.cc diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc index f9e0c75b3e..5beaf81fc9 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.cc @@ -856,6 +856,44 @@ Status Pad(const std::shared_ptr &input, std::shared_ptr *output RETURN_STATUS_UNEXPECTED("Unexpected error in pad"); } } + +Status RgbaToRgb(const std::shared_ptr &input, std::shared_ptr *output) { + try { + std::shared_ptr input_cv = CVTensor::AsCVTensor(std::move(input)); + int num_channels = input_cv->shape()[2]; + if (input_cv->shape().Size() != 3 || num_channels != 4) { + std::string err_msg = "Number of channels does not equal 4, got : " + std::to_string(num_channels); + RETURN_STATUS_UNEXPECTED(err_msg); + } + TensorShape out_shape = TensorShape({input_cv->shape()[0], input_cv->shape()[1], 3}); + std::shared_ptr output_cv; + RETURN_IF_NOT_OK(CVTensor::CreateEmpty(out_shape, input_cv->type(), &output_cv)); + cv::cvtColor(input_cv->mat(), output_cv->mat(), static_cast(cv::COLOR_RGBA2RGB)); + *output = std::static_pointer_cast(output_cv); + return Status::OK(); + } catch (const cv::Exception &e) { + RETURN_STATUS_UNEXPECTED("Unexpected error in RgbaToRgb."); + } +} + +Status RgbaToBgr(const std::shared_ptr &input, std::shared_ptr *output) { + try { + std::shared_ptr input_cv = CVTensor::AsCVTensor(std::move(input)); + int num_channels = input_cv->shape()[2]; + if (input_cv->shape().Size() != 3 || num_channels != 4) { + std::string err_msg = "Number of channels does not equal 4, got : " + std::to_string(num_channels); + RETURN_STATUS_UNEXPECTED(err_msg); + } + TensorShape out_shape = TensorShape({input_cv->shape()[0], input_cv->shape()[1], 3}); + std::shared_ptr output_cv; + RETURN_IF_NOT_OK(CVTensor::CreateEmpty(out_shape, input_cv->type(), &output_cv)); + cv::cvtColor(input_cv->mat(), output_cv->mat(), static_cast(cv::COLOR_RGBA2BGR)); + *output = std::static_pointer_cast(output_cv); + return Status::OK(); + } catch (const cv::Exception &e) { + RETURN_STATUS_UNEXPECTED("Unexpected error in RgbaToBgr."); + } +} // -------- BBOX OPERATIONS -------- // Status UpdateBBoxesForCrop(std::shared_ptr *bboxList, size_t *bboxCount, int CB_Xmin, int CB_Ymin, int CB_Xmax, int CB_Ymax) { diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h index f82c4d442f..b736f3854e 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/image_utils.h @@ -44,50 +44,50 @@ struct JpegErrorManagerCustom { jmp_buf setjmp_buffer; }; -// Returns the interpolation mode in openCV format -// @param mode: interpolation mode in DE format +/// \brief Returns the interpolation mode in openCV format +/// \param[in] mode Interpolation mode in DE format int GetCVInterpolationMode(InterpolationMode mode); -// Returns the openCV equivalent of the border type used for padding. -// @param type -// @return +/// \brief Returns the openCV equivalent of the border type used for padding. +/// \param type +/// \return Status code int GetCVBorderType(BorderType type); -// Returns flipped image -// @param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param flip_code: 1 for Horizontal (around y-axis), 0 for Vertical (around x-axis), -1 for both -// The flipping happens in place. +/// \brief Returns flipped image +/// \param[in] input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param flip_code: 1 for Horizontal (around y-axis), 0 for Vertical (around x-axis), -1 for both +/// The flipping happens in place. Status Flip(std::shared_ptr input, std::shared_ptr *output, int flip_code); -// Returns Horizontally flipped image -// @param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// The flipping happens in place. +/// \brief Returns Horizontally flipped image +/// \param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// The flipping happens in place. Status HorizontalFlip(std::shared_ptr input, std::shared_ptr *output); -// Returns Vertically flipped image -// @param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// The flipping happens in place. +/// \brief Returns Vertically flipped image +/// \param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \note The flipping happens in place. Status VerticalFlip(std::shared_ptr input, std::shared_ptr *output); -// Returns Resized image. -// @param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param output_height: height of output -// @param output_width: width of output -// @param fx: horizontal scale -// @param fy: vertical scale -// @param InterpolationMode: the interpolation mode -// @param output: Resized image of shape or -// and same type as input +/// \brief Returns Resized image. +/// \param input/output: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param output_height: height of output +/// \param output_width: width of output +/// \param fx: horizontal scale +/// \param fy: vertical scale +/// \param InterpolationMode: the interpolation mode +/// \param output: Resized image of shape or +/// and same type as input Status Resize(const std::shared_ptr &input, std::shared_ptr *output, int32_t output_height, int32_t output_width, double fx = 0.0, double fy = 0.0, InterpolationMode mode = InterpolationMode::kLinear); -// Returns Decoded image -// Supported images: -// BMP JPEG JPG PNG TIFF -// supported by opencv, if user need more image analysis capabilities, please compile opencv particularlly. -// @param input: CVTensor containing the not decoded image 1D bytes -// @param output: Decoded image Tensor of shape and type DE_UINT8. Pixel order is RGB +/// \brief Returns Decoded image +/// Supported images: +/// BMP JPEG JPG PNG TIFF +/// supported by opencv, if user need more image analysis capabilities, please compile opencv particularlly. +/// \param input: CVTensor containing the not decoded image 1D bytes +/// \param output: Decoded image Tensor of shape and type DE_UINT8. Pixel order is RGB Status Decode(const std::shared_ptr &input, std::shared_ptr *output); Status DecodeCv(const std::shared_ptr &input, std::shared_ptr *output); @@ -98,106 +98,107 @@ void JpegSetSource(j_decompress_ptr c_info, const void *data, int64_t data_size) Status JpegCropAndDecode(const std::shared_ptr &input, std::shared_ptr *output, int x = 0, int y = 0, int w = 0, int h = 0); -// Returns Rescaled image -// @param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param rescale: rescale parameter -// @param shift: shift parameter -// @param output: Rescaled image Tensor of same input shape and type DE_FLOAT32 + +/// \brief Returns Rescaled image +/// \param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param rescale: rescale parameter +/// \param shift: shift parameter +/// \param output: Rescaled image Tensor of same input shape and type DE_FLOAT32 Status Rescale(const std::shared_ptr &input, std::shared_ptr *output, float rescale, float shift); -// Returns cropped ROI of an image -// @param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param x: starting horizontal position of ROI -// @param y: starting vertical position of ROI -// @param w: width of the ROI -// @param h: height of the ROI -// @param output: Cropped image Tensor of shape or and same input type. +/// \brief Returns cropped ROI of an image +/// \param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param x: starting horizontal position of ROI +/// \param y: starting vertical position of ROI +/// \param w: width of the ROI +/// \param h: height of the ROI +/// \param output: Cropped image Tensor of shape or and same input type. Status Crop(const std::shared_ptr &input, std::shared_ptr *output, int x, int y, int w, int h); -// Swaps the channels in the image, i.e. converts HWC to CHW -// @param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param output: Tensor of shape or and same input type. +/// \brief Swaps the channels in the image, i.e. converts HWC to CHW +/// \param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param output: Tensor of shape or and same input type. Status HwcToChw(std::shared_ptr input, std::shared_ptr *output); -// Swap the red and blue pixels (RGB <-> BGR) -// @param input: Tensor of shape and any OpenCv compatible type, see CVTensor. -// @param output: Swapped image of same shape and type +/// \brief Swap the red and blue pixels (RGB <-> BGR) +/// \param input: Tensor of shape and any OpenCv compatible type, see CVTensor. +/// \param output: Swapped image of same shape and type Status SwapRedAndBlue(std::shared_ptr input, std::shared_ptr *output); -// Crops and resizes the image -// @param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param x: horizontal start point -// @param y: vertical start point -// @param crop_height: height of the cropped ROI -// @param crop_width: width of the cropped ROI -// @param target_width: width of the final resized image -// @param target_height: height of the final resized image -// @param InterpolationMode: the interpolation used in resize operation -// @param output: Tensor of shape or -// and same type as input +/// \brief Crops and resizes the image +/// \param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param x: horizontal start point +/// \param y: vertical start point +/// \param crop_height: height of the cropped ROI +/// \param crop_width: width of the cropped ROI +/// \param target_width: width of the final resized image +/// \param target_height: height of the final resized image +/// \param InterpolationMode: the interpolation used in resize operation +/// \param output: Tensor of shape or +/// and same type as input Status CropAndResize(const std::shared_ptr &input, std::shared_ptr *output, int x, int y, int crop_height, int crop_width, int target_height, int target_width, InterpolationMode mode); -// Returns rotated image -// @param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. -// @param fx: rotation center x coordinate -// @param fy: rotation center y coordinate -// @param degree: degree to rotate -// @param expand: if reshape is necessary -// @param output: rotated image of same input type. +/// \brief Returns rotated image +/// \param input: Tensor of shape or and any OpenCv compatible type, see CVTensor. +/// \param fx: rotation center x coordinate +/// \param fy: rotation center y coordinate +/// \param degree: degree to rotate +/// \param expand: if reshape is necessary +/// \param output: rotated image of same input type. Status Rotate(const std::shared_ptr &input, std::shared_ptr *output, float fx, float fy, float degree, InterpolationMode interpolation = InterpolationMode::kNearestNeighbour, bool expand = false, uint8_t fill_r = 0, uint8_t fill_g = 0, uint8_t fill_b = 0); -// Returns Normalized image -// @param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. -// @param mean: Tensor of shape <3> and type DE_FLOAT32 which are mean of each channel in RGB order -// @param std: Tensor of shape <3> and type DE_FLOAT32 which are std of each channel in RGB order -// @param output: Normalized image Tensor of same input shape and type DE_FLOAT32 +/// \brief Returns Normalized image +/// \param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. +/// \param mean: Tensor of shape <3> and type DE_FLOAT32 which are mean of each channel in RGB order +/// \param std: Tensor of shape <3> and type DE_FLOAT32 which are std of each channel in RGB order +/// \param output: Normalized image Tensor of same input shape and type DE_FLOAT32 Status Normalize(const std::shared_ptr &input, std::shared_ptr *output, const std::shared_ptr &mean, const std::shared_ptr &std); -// Returns image with adjusted brightness. -// @param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. -// @param alpha: Alpha value to adjust brightness by. Should be a positive number. -// If user input one value in python, the range is [1 - value, 1 + value]. -// This will output original image multiplied by alpha. 0 gives a black image, 1 gives the -// original image while 2 increases the brightness by a factor of 2. -// @param output: Adjusted image of same shape and type. +/// \brief Returns image with adjusted brightness. +/// \param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. +/// \param alpha: Alpha value to adjust brightness by. Should be a positive number. +/// If user input one value in python, the range is [1 - value, 1 + value]. +/// This will output original image multiplied by alpha. 0 gives a black image, 1 gives the +/// original image while 2 increases the brightness by a factor of 2. +/// \param output: Adjusted image of same shape and type. Status AdjustBrightness(const std::shared_ptr &input, std::shared_ptr *output, const float &alpha); -// Returns image with adjusted contrast. -// @param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. -// @param alpha: Alpha value to adjust contrast by. Should be a positive number. -// If user input one value in python, the range is [1 - value, 1 + value]. -// 0 gives a solid gray image, 1 gives the original image while 2 increases -// the contrast by a factor of 2. -// @param output: Adjusted image of same shape and type. +/// \brief Returns image with adjusted contrast. +/// \param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. +/// \param alpha: Alpha value to adjust contrast by. Should be a positive number. +/// If user input one value in python, the range is [1 - value, 1 + value]. +/// 0 gives a solid gray image, 1 gives the original image while 2 increases +/// the contrast by a factor of 2. +/// \param output: Adjusted image of same shape and type. Status AdjustContrast(const std::shared_ptr &input, std::shared_ptr *output, const float &alpha); -// Returns image with contrast maximized. -// @param input: Tensor of shape // in RGB/Grayscale and any OpenCv compatible type, see CVTensor. -// @param cutoff: Cutoff percentage of how many pixels are to be removed (high pixels change to 255 and low change to 0) -// from the high and low ends of the histogram. -// @param ignore: Pixel values to be ignored in the algorithm. +/// \brief Returns image with contrast maximized. +/// \param input: Tensor of shape // in RGB/Grayscale and any OpenCv compatible type, see CVTensor. +/// \param cutoff: Cutoff percentage of how many pixels are to be removed (high pixels change to 255 and low change +/// to 0) from the high and low ends of the histogram. +/// \param ignore: Pixel values to be ignored in the algorithm. Status AutoContrast(const std::shared_ptr &input, std::shared_ptr *output, const float &cutoff, const std::vector &ignore); -// Returns image with adjusted saturation. -// @param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. -// @param alpha: Alpha value to adjust saturation by. Should be a positive number. -// If user input one value in python, the range is [1 - value, 1 + value]. -// 0 will give a black and white image, 1 will give the original image while -// 2 will enhance the saturation by a factor of 2. -// @param output: Adjusted image of same shape and type. +/// \brief Returns image with adjusted saturation. +/// \param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. +/// \param alpha: Alpha value to adjust saturation by. Should be a positive number. +/// If user input one value in python, the range is [1 - value, 1 + value]. +/// 0 will give a black and white image, 1 will give the original image while +/// 2 will enhance the saturation by a factor of 2. +/// \param output: Adjusted image of same shape and type. Status AdjustSaturation(const std::shared_ptr &input, std::shared_ptr *output, const float &alpha); -// Returns image with adjusted hue. -// @param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. -// @param hue: Hue value to adjust by, should be within range [-0.5, 0.5]. 0.5 and - 0.5 will reverse the hue channel -// completely. -// If user input one value in python, the range is [-value, value]. -// @param output: Adjusted image of same shape and type. +/// \brief Returns image with adjusted hue. +/// \param input: Tensor of shape in RGB order and any OpenCv compatible type, see CVTensor. +/// \param hue: Hue value to adjust by, should be within range [-0.5, 0.5]. 0.5 and - 0.5 will reverse the hue channel +/// completely. +/// If user input one value in python, the range is [-value, value]. +/// \param output: Adjusted image of same shape and type. Status AdjustHue(const std::shared_ptr &input, std::shared_ptr *output, const float &hue); /// \brief Returns image with equalized histogram. @@ -206,72 +207,84 @@ Status AdjustHue(const std::shared_ptr &input, std::shared_ptr * /// \param[out] output: Equalized image of same shape and type. Status Equalize(const std::shared_ptr &input, std::shared_ptr *output); -// Masks out a random section from the image with set dimension -// @param input: input Tensor -// @param output: cutOut Tensor -// @param box_height: height of the cropped box -// @param box_width: width of the cropped box -// @param num_patches: number of boxes to cut out from the image -// @param bounded: boolean flag to toggle between random erasing and cutout -// @param random_color: whether or not random fill value should be used -// @param fill_r: red fill value for erase -// @param fill_g: green fill value for erase -// @param fill_b: blue fill value for erase. +/// \brief Masks out a random section from the image with set dimension +/// \param input: input Tensor +/// \param output: cutOut Tensor +/// \param box_height: height of the cropped box +/// \param box_width: width of the cropped box +/// \param num_patches: number of boxes to cut out from the image +/// \param bounded: boolean flag to toggle between random erasing and cutout +/// \param random_color: whether or not random fill value should be used +/// \param fill_r: red fill value for erase +/// \param fill_g: green fill value for erase +/// \param fill_b: blue fill value for erase. Status Erase(const std::shared_ptr &input, std::shared_ptr *output, int32_t box_height, int32_t box_width, int32_t num_patches, bool bounded, bool random_color, std::mt19937 *rnd, uint8_t fill_r = 0, uint8_t fill_g = 0, uint8_t fill_b = 0); -// Pads the input image and puts the padded image in the output -// @param input: input Tensor -// @param output: padded Tensor -// @param pad_top: amount of padding done in top -// @param pad_bottom: amount of padding done in bottom -// @param pad_left: amount of padding done in left -// @param pad_right: amount of padding done in right -// @param border_types: the interpolation to be done in the border -// @param fill_r: red fill value for pad -// @param fill_g: green fill value for pad -// @param fill_b: blue fill value for pad. +/// \brief Pads the input image and puts the padded image in the output +/// \param input: input Tensor +/// \param output: padded Tensor +/// \param pad_top: amount of padding done in top +/// \param pad_bottom: amount of padding done in bottom +/// \param pad_left: amount of padding done in left +/// \param pad_right: amount of padding done in right +/// \param border_types: the interpolation to be done in the border +/// \param fill_r: red fill value for pad +/// \param fill_g: green fill value for pad +/// \param fill_b: blue fill value for pad. Status Pad(const std::shared_ptr &input, std::shared_ptr *output, const int32_t &pad_top, const int32_t &pad_bottom, const int32_t &pad_left, const int32_t &pad_right, const BorderType &border_types, uint8_t fill_r = 0, uint8_t fill_g = 0, uint8_t fill_b = 0); -// -------- BBOX OPERATIONS -------- // -// Updates and checks bounding boxes for new cropped region of image -// @param bboxList: A tensor contaning bounding box tensors -// @param bboxCount: total Number of bounding boxes - required within caller function to run update loop -// @param CB_Xmin: Image's CropBox Xmin coordinate -// @param CB_Xmin: Image's CropBox Ymin coordinate -// @param CB_Xmax: Image's CropBox Xmax coordinate - (Xmin + width) -// @param CB_Xmax: Image's CropBox Ymax coordinate - (Ymin + height) +/// \brief Take in a 4 channel image in RBGA to RGB +/// \param[in] input The input image +/// \param[out] output The output image +/// \return Status code +Status RgbaToRgb(const std::shared_ptr &input, std::shared_ptr *output); + +/// \brief Take in a 4 channel image in RBGA to BGR +/// \param[in] input The input image +/// \param[out] output The output image +/// \return Status code +Status RgbaToBgr(const std::shared_ptr &input, std::shared_ptr *output); + +/// -------- BBOX OPERATIONS -------- /// +/// \brief Updates and checks bounding boxes for new cropped region of image +/// \param bboxList: A tensor contaning bounding box tensors +/// \param bboxCount: total Number of bounding boxes - required within caller function to run update loop +/// \param CB_Xmin: Image's CropBox Xmin coordinate +/// \param CB_Xmin: Image's CropBox Ymin coordinate +/// \param CB_Xmax: Image's CropBox Xmax coordinate - (Xmin + width) +/// \param CB_Xmax: Image's CropBox Ymax coordinate - (Ymin + height) Status UpdateBBoxesForCrop(std::shared_ptr *bboxList, size_t *bboxCount, int CB_Xmin, int CB_Ymin, int CB_Xmax, int CB_Ymax); -// Updates bounding boxes with required Top and Left padding -// Top and Left padding amounts required to adjust bboxs min X,Y values according to padding 'push' -// Top/Left since images 0,0 coordinate is taken from top left -// @param bboxList: A tensor contaning bounding box tensors -// @param bboxCount: total Number of bounding boxes - required within caller function to run update loop -// @param pad_top: Total amount of padding applied to image top -// @param pad_left: Total amount of padding applied to image left side +/// \brief Updates bounding boxes with required Top and Left padding +/// \note Top and Left padding amounts required to adjust bboxs min X,Y values according to padding 'push' +/// Top/Left since images 0,0 coordinate is taken from top left +/// \param bboxList: A tensor contaning bounding box tensors +/// \param bboxCount: total Number of bounding boxes - required within caller function to run update loop +/// \param pad_top: Total amount of padding applied to image top +/// \param pad_left: Total amount of padding applied to image left side Status PadBBoxes(const std::shared_ptr *bboxList, const size_t &bboxCount, int32_t pad_top, int32_t pad_left); -// Updates bounding boxes for an Image Resize Operation - Takes in set of valid BBoxes -// For e.g those that remain after a crop -// @param bboxList: A tensor contaning bounding box tensors -// @param bboxCount: total Number of bounding boxes - required within caller function to run update loop -// @param bboxList: A tensor contaning bounding box tensors -// @param target_width_: required width of image post resize -// @param target_width_: required height of image post resize -// @param orig_width: current width of image pre resize -// @param orig_height: current height of image pre resize +/// \brief Updates bounding boxes for an Image Resize Operation - Takes in set of valid BBoxes +/// For e.g those that remain after a crop +/// \param bboxList: A tensor contaning bounding box tensors +/// \param bboxCount: total Number of bounding boxes - required within caller function to run update loop +/// \param bboxList: A tensor contaning bounding box tensors +/// \param target_width_: required width of image post resize +/// \param target_width_: required height of image post resize +/// \param orig_width: current width of image pre resize +/// \param orig_height: current height of image pre resize Status UpdateBBoxesForResize(const std::shared_ptr &bboxList, const size_t &bboxCount, int32_t target_width_, int32_t target_height_, int orig_width, int orig_height); -// Get jpeg image width and height -// @param input: CVTensor containing the not decoded image 1D bytes -// @param img_width: the jpeg image width -// @param img_height: the jpeg image height +/// \brief Get jpeg image width and height +/// \param input: CVTensor containing the not decoded image 1D bytes +/// \param img_width: the jpeg image width +/// \param img_height: the jpeg image height Status GetJpegImageInfo(const std::shared_ptr &input, int *img_width, int *img_height); } // namespace dataset diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.cc new file mode 100644 index 0000000000..b948fbdca1 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_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/rgba_to_bgr_op.h" + +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { + +Status RgbaToBgrOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + return RgbaToBgr(input, output); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.h new file mode 100644 index 0000000000..0502de73a7 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_bgr_op.h @@ -0,0 +1,43 @@ +/** + * 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_RGBA_TO_BGR_OP_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_RGBA_TO_BGR_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 RgbaToBgrOp : public TensorOp { + public: + RgbaToBgrOp() {} + + ~RgbaToBgrOp() override = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + std::string Name() const override { return kRgbaToBgrOp; } +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_RGBA_TO_BGR_OP_H_ diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.cc b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.cc new file mode 100644 index 0000000000..34bcef5f49 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_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/rgba_to_rgb_op.h" + +#include "minddata/dataset/kernels/image/image_utils.h" +#include "minddata/dataset/util/status.h" + +namespace mindspore { +namespace dataset { + +Status RgbaToRgbOp::Compute(const std::shared_ptr &input, std::shared_ptr *output) { + IO_CHECK(input, output); + return RgbaToRgb(input, output); +} +} // namespace dataset +} // namespace mindspore diff --git a/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.h b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.h new file mode 100644 index 0000000000..602dd4abd3 --- /dev/null +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/rgba_to_rgb_op.h @@ -0,0 +1,43 @@ +/** + * 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_RGBA_TO_RGB_OP_H_ +#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_RGBA_TO_RGB_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 RgbaToRgbOp : public TensorOp { + public: + RgbaToRgbOp() {} + + ~RgbaToRgbOp() override = default; + + Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; + + std::string Name() const override { return kRgbaToRgbOp; } +}; +} // namespace dataset +} // namespace mindspore + +#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_RGBA_TO_RGB_OP_H_ 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 index c42bbb80c7..696d00b33b 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/image/swap_red_blue_op.h @@ -29,14 +29,7 @@ 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. + /// \brief Constructor SwapRedBlueOp() {} SwapRedBlueOp(const SwapRedBlueOp &rhs) = default; @@ -45,7 +38,7 @@ class SwapRedBlueOp : public TensorOp { ~SwapRedBlueOp() override = default; - void Print(std::ostream &out) const override { out << "SwapRedBlueOp x"; } + void Print(std::ostream &out) const override { out << "SwapRedBlueOp"; } Status Compute(const std::shared_ptr &input, std::shared_ptr *output) override; diff --git a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h index 62b99777ed..1047876e32 100644 --- a/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h +++ b/mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h @@ -121,8 +121,10 @@ constexpr char kRescaleOp[] = "RescaleOp"; constexpr char kResizeBilinearOp[] = "ResizeBilinearOp"; constexpr char kResizeOp[] = "ResizeOp"; constexpr char kResizeWithBBoxOp[] = "ResizeWithBBoxOp"; -constexpr char kSolarizeOp[] = "SolarizeOp"; +constexpr char kRgbaToBgrOp[] = "RgbaToBgrOp"; +constexpr char kRgbaToRgbOp[] = "RgbaToRgbOp"; constexpr char kSharpnessOp[] = "SharpnessOp"; +constexpr char kSolarizeOp[] = "SolarizeOp"; constexpr char kSwapRedBlueOp[] = "SwapRedBlueOp"; constexpr char kUniformAugOp[] = "UniformAugOp"; constexpr char kSoftDvppDecodeRandomCropResizeJpegOp[] = "SoftDvppDecodeRandomCropResizeJpegOp"; diff --git a/tests/ut/cpp/dataset/CMakeLists.txt b/tests/ut/cpp/dataset/CMakeLists.txt index a9f876f474..7aad79bf7b 100644 --- a/tests/ut/cpp/dataset/CMakeLists.txt +++ b/tests/ut/cpp/dataset/CMakeLists.txt @@ -55,12 +55,14 @@ SET(DE_UT_SRCS random_vertical_flip_with_bbox_op_test.cc rename_op_test.cc repeat_op_test.cc - skip_op_test.cc rescale_op_test.cc resize_bilinear_op_test.cc resize_op_test.cc resize_with_bbox_op_test.cc + rgba_to_bgr_op_test.cc + rgba_to_rgb_op_test.cc schema_test.cc + skip_op_test.cc shuffle_op_test.cc stand_alone_samplers_test.cc status_test.cc diff --git a/tests/ut/cpp/dataset/rgba_to_bgr_op_test.cc b/tests/ut/cpp/dataset/rgba_to_bgr_op_test.cc new file mode 100644 index 0000000000..470e18eaee --- /dev/null +++ b/tests/ut/cpp/dataset/rgba_to_bgr_op_test.cc @@ -0,0 +1,62 @@ +/** + * 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 +#include "common/common.h" +#include "common/cvop_common.h" +#include "minddata/dataset/kernels/image/rgba_to_bgr_op.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "utils/log_adapter.h" + +using namespace mindspore::dataset; +using mindspore::MsLogLevel::INFO; +using mindspore::ExceptionType::NoExceptionType; +using mindspore::LogStream; + +class MindDataTestRgbaToBgrOp : public UT::CVOP::CVOpCommon { + protected: + MindDataTestRgbaToBgrOp() : CVOpCommon() {} + + std::shared_ptr output_tensor_; +}; + +TEST_F(MindDataTestRgbaToBgrOp, TestOp1) { + MS_LOG(INFO) << "Doing testRGBA2BGR."; + std::unique_ptr op(new RgbaToBgrOp()); + EXPECT_TRUE(op->OneToOne()); + // prepare 4 channel image + cv::Mat rgba_image; + // First create the image with alpha channel + cv::cvtColor(raw_cv_image_, rgba_image, cv::COLOR_BGR2RGBA); + std::vectorchannels(4); + cv::split(rgba_image, channels); + channels[3] = cv::Mat::zeros(rgba_image.rows, rgba_image.cols, CV_8UC1); + cv::merge(channels, rgba_image); + // create new tensor to test conversion + std::shared_ptr rgba_input; + std::shared_ptr input_cv_tensor; + CVTensor::CreateFromMat(rgba_image, &input_cv_tensor); + rgba_input = std::dynamic_pointer_cast(input_cv_tensor); + + Status s = op->Compute(rgba_input, &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()); +} + diff --git a/tests/ut/cpp/dataset/rgba_to_rgb_op_test.cc b/tests/ut/cpp/dataset/rgba_to_rgb_op_test.cc new file mode 100644 index 0000000000..a50c8047a0 --- /dev/null +++ b/tests/ut/cpp/dataset/rgba_to_rgb_op_test.cc @@ -0,0 +1,62 @@ +/** + * 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 +#include "common/common.h" +#include "common/cvop_common.h" +#include "minddata/dataset/kernels/image/rgba_to_rgb_op.h" +#include "minddata/dataset/core/cv_tensor.h" +#include "utils/log_adapter.h" + +using namespace mindspore::dataset; +using mindspore::MsLogLevel::INFO; +using mindspore::ExceptionType::NoExceptionType; +using mindspore::LogStream; + +class MindDataTestRgbaToRgbOp : public UT::CVOP::CVOpCommon { + protected: + MindDataTestRgbaToRgbOp() : CVOpCommon() {} + + std::shared_ptr output_tensor_; +}; + +TEST_F(MindDataTestRgbaToRgbOp, TestOp1) { + MS_LOG(INFO) << "Doing testRGBA2RGB."; + std::unique_ptr op(new RgbaToRgbOp()); + EXPECT_TRUE(op->OneToOne()); + // prepare 4 channel image + cv::Mat rgba_image; + // First create the image with alpha channel + cv::cvtColor(raw_cv_image_, rgba_image, cv::COLOR_BGR2RGBA); + std::vectorchannels(4); + cv::split(rgba_image, channels); + channels[3] = cv::Mat::zeros(rgba_image.rows, rgba_image.cols, CV_8UC1); + cv::merge(channels, rgba_image); + // create new tensor to test conversion + std::shared_ptr rgba_input; + std::shared_ptr input_cv_tensor; + CVTensor::CreateFromMat(rgba_image, &input_cv_tensor); + rgba_input = std::dynamic_pointer_cast(input_cv_tensor); + + Status s = op->Compute(rgba_input, &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()); +} +