Browse Source

!13279 Add resizefiller operation

From: @shenwei41
Reviewed-by: 
Signed-off-by:
tags/v1.2.0-rc1
mindspore-ci-bot Gitee 4 years ago
parent
commit
f68732c15d
18 changed files with 660 additions and 3 deletions
  1. +16
    -0
      mindspore/ccsrc/minddata/dataset/api/vision.cc
  2. +24
    -1
      mindspore/ccsrc/minddata/dataset/include/vision_lite.h
  3. +1
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt
  4. +288
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.cc
  5. +17
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.h
  6. +8
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/lite_mat.h
  7. +37
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.cc
  8. +9
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.h
  9. +39
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/resize_preserve_ar_op.cc
  10. +55
    -0
      mindspore/ccsrc/minddata/dataset/kernels/image/resize_preserve_ar_op.h
  11. +20
    -0
      mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc
  12. +21
    -0
      mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h
  13. +1
    -0
      mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h
  14. +23
    -0
      mindspore/ccsrc/minddata/dataset/liteapi/include/vision_lite.h
  15. +3
    -0
      mindspore/lite/minddata/CMakeLists.txt
  16. +13
    -2
      mindspore/lite/minddata/example/CMakeLists.txt
  17. +68
    -0
      mindspore/lite/minddata/example/testresize.cpp
  18. +17
    -0
      tests/ut/cpp/dataset/image_process_test.cc

+ 16
- 0
mindspore/ccsrc/minddata/dataset/api/vision.cc View File

@@ -735,6 +735,22 @@ std::shared_ptr<TensorOperation> Resize::Parse(const MapTargetDevice &env) {
return std::make_shared<ResizeOperation>(data_->size_, data_->interpolation_); return std::make_shared<ResizeOperation>(data_->size_, data_->interpolation_);
} }


// ResizePreserveAR Transform Operation.
struct ResizePreserveAR::Data {
Data(int32_t height, int32_t width, int32_t img_orientation)
: height_(height), width_(width), img_orientation_(img_orientation) {}
int32_t height_;
int32_t width_;
int32_t img_orientation_;
};

ResizePreserveAR::ResizePreserveAR(int32_t height, int32_t width, int32_t img_orientation)
: data_(std::make_shared<Data>(height, width, img_orientation)) {}

std::shared_ptr<TensorOperation> ResizePreserveAR::Parse() {
return std::make_shared<ResizePreserveAROperation>(data_->height_, data_->width_, data_->img_orientation_);
}

#ifdef ENABLE_ANDROID #ifdef ENABLE_ANDROID
// Rotate Transform Operation. // Rotate Transform Operation.
Rotate::Rotate() {} Rotate::Rotate() {}


+ 24
- 1
mindspore/ccsrc/minddata/dataset/include/vision_lite.h View File

@@ -93,7 +93,7 @@ class CenterCrop final : public TensorTransform {


/// \brief RGB2GRAY TensorTransform. /// \brief RGB2GRAY TensorTransform.
/// \notes Convert RGB image or color image to grayscale image /// \notes Convert RGB image or color image to grayscale image
class RGB2GRAY : public TensorTransform {
class RGB2GRAY final : public TensorTransform {
public: public:
/// \brief Constructor. /// \brief Constructor.
RGB2GRAY() = default; RGB2GRAY() = default;
@@ -244,6 +244,29 @@ class Resize final : public TensorTransform {
std::shared_ptr<Data> data_; std::shared_ptr<Data> data_;
}; };


/// \brief ResizePreserveAR TensorTransform.
/// \notes Keep the original picture ratio and fill the rest.
class ResizePreserveAR final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] height The height of image output value after resizing.
/// \param[in] width The width of image output value after resizing.
/// \param[in] img_orientation Angle method of image rotation.
ResizePreserveAR(int32_t height, int32_t width, int32_t img_orientation = 0);

/// \brief Destructor.
~ResizePreserveAR() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief Rotate TensorTransform. /// \brief Rotate TensorTransform.
/// \notes Rotate the input image using a specified angle id. /// \notes Rotate the input image using a specified angle id.
class Rotate final : public TensorTransform { class Rotate final : public TensorTransform {


+ 1
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/CMakeLists.txt View File

@@ -44,6 +44,7 @@ add_library(kernels-image OBJECT
random_sharpness_op.cc random_sharpness_op.cc
rescale_op.cc rescale_op.cc
resize_op.cc resize_op.cc
resize_preserve_ar_op.cc
rgb_to_gray_op.cc rgb_to_gray_op.cc
rgba_to_bgr_op.cc rgba_to_bgr_op.cc
rgba_to_rgb_op.cc rgba_to_rgb_op.cc


+ 288
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.cc View File

@@ -1692,5 +1692,293 @@ bool ConvertRgbToGray(const LiteMat &src, LDataType data_type, int w, int h, Lit
return true; return true;
} }


void UpdateOrientationAfineMat(const LiteMat &src, int *rotationDstWidth, int *rotationDstHeight, float (*varM)[2][3],
int img_orientation) {
int srcOrientation = img_orientation;
if (IM_TOOL_EXIF_ORIENTATION_0_DEG_MIRROR == srcOrientation) {
(*varM)[0][0] *= -1;
(*varM)[0][2] += *rotationDstWidth - 1;
} else if ((IM_TOOL_EXIF_ORIENTATION_180_DEG == srcOrientation) ||
(IM_TOOL_EXIF_ORIENTATION_180_DEG_MIRROR == srcOrientation)) {
// 0, 1, 2 is the matrix index of varM
(*varM)[0][0] = -1;
(*varM)[0][1] = 0;
(*varM)[0][2] = *rotationDstWidth - 1;
(*varM)[1][0] = 0;
(*varM)[1][1] = -1;
(*varM)[1][2] = *rotationDstWidth - 1;
if (IM_TOOL_EXIF_ORIENTATION_180_DEG_MIRROR == srcOrientation) {
/* with (*varM)irror */
(*varM)[0][0] *= -1;
(*varM)[0][2] -= *rotationDstWidth - 1;
}
} else if ((IM_TOOL_EXIF_ORIENTATION_90_DEG_MIRROR == srcOrientation) ||
(IM_TOOL_EXIF_ORIENTATION_90_DEG == srcOrientation)) {
/* 90 Deg rotation */
*rotationDstWidth = src.height_;
*rotationDstHeight = src.width_;
(*varM)[0][0] = 0;
(*varM)[0][1] = -1;
(*varM)[0][2] = *rotationDstWidth - 1;
(*varM)[1][0] = 1;
(*varM)[1][1] = 0;
(*varM)[1][2] = 0;
if (IM_TOOL_EXIF_ORIENTATION_90_DEG_MIRROR == srcOrientation) {
/* with Mirror */
(*varM)[0][1] *= -1;
(*varM)[0][2] -= *rotationDstWidth - 1;
}
} else if ((IM_TOOL_EXIF_ORIENTATION_270_DEG_MIRROR == srcOrientation) ||
(IM_TOOL_EXIF_ORIENTATION_270_DEG == srcOrientation)) {
/* 270 Deg rotation */
*rotationDstWidth = src.height_;
*rotationDstHeight = src.width_;
(*varM)[0][0] = 0;
(*varM)[0][1] = 1;
(*varM)[0][2] = 0;
(*varM)[1][0] = -1;
(*varM)[1][1] = 0;
(*varM)[1][2] = *rotationDstWidth - 1;
if (IM_TOOL_EXIF_ORIENTATION_270_DEG_MIRROR == srcOrientation) {
/* with Mirror */
(*varM)[0][1] *= -1;
(*varM)[0][2] += *rotationDstWidth - 1;
}
}
}

void ImageToolsConvertImage(const LiteMat &src, const LiteMat &dst, imageToolsImage_t *imageIn,
imageToolsImage_t *imageOut) {
imageIn->image_buff = src.data_ptr_;
imageIn->h = src.height_;
imageIn->w = src.width_;
imageIn->stride = src.width_;
imageIn->dataType = IM_TOOL_DATA_TYPE_UINT8;

imageOut->image_buff = dst.data_ptr_;
imageOut->h = dst.height_;
imageOut->w = dst.width_;
imageOut->stride = dst.width_;
imageOut->dataType = IM_TOOL_DATA_TYPE_FLOAT;
}

void InvAffine2x3(float M[2][3], float invM[][3]) {
float inv_det = M[0][0] * M[1][1] - M[1][0] * M[0][1];
invM[1][1] = M[0][0] / inv_det;
invM[0][1] = -M[0][1] / inv_det;
invM[1][0] = -M[1][0] / inv_det;
invM[0][0] = M[1][1] / inv_det;
invM[0][2] = (M[0][1] * M[1][2] - M[1][1] * M[0][2]) / inv_det;
invM[1][2] = -(M[0][0] * M[1][2] - M[1][0] * M[0][2]) / inv_det;
}

static float *CalDst(float *dst, float v1, float v2, float v3) {
*dst++ = v1;
*dst++ = v2;
*dst++ = v3;
return dst;
}

static void ImageWarpAffineHWCFloat(imageToolsImage_t image, imageToolsImage_t warped_image, float invM[2][3]) {
// 3 is r, g, b
warped_image.stride *= 3;
image.stride *= 3;

float *warped_image_buff = reinterpret_cast<float *>(warped_image.image_buff);

float *image_buff = reinterpret_cast<float *>(image.image_buff);
for (int y0 = 0; y0 < warped_image.h; y0++) {
// Init pointers to start of rows
float *dst = warped_image_buff + y0 * warped_image.stride;

for (int x0 = 0; x0 < warped_image.w; x0++) {
// number 0, 1, 2 is the index of MATRIX 'invM'
float fPosx = (static_cast<float>(x0) * invM[0][0]) + (static_cast<float>(y0) * invM[0][1]) + invM[0][2];
float fPosy = (static_cast<float>(x0) * invM[1][0]) + (static_cast<float>(y0) * invM[1][1]) + invM[1][2];
int iPosy = static_cast<int>(fPosy + 2) - 2; // for floor like result until -2.
int iPosx = static_cast<int>(fPosx + 2) - 2; // for floor like result until -2.
if ((iPosx < -1) || (iPosx >= image.w) || (iPosy < -1) || (iPosy >= image.h)) {
dst = CalDst(dst, 0.0f, 0.0f, 0.0f);
continue;
}
float fRsiduy = fPosy - iPosy;
float fRsidux = fPosx - iPosx;
float fOut0 = 0;
float fOut1 = 0;
float fOut2 = 0;
float *fTopeLeft = image_buff + iPosy * image.stride + iPosx * 3;
float fCoeff = 1 - fRsidux - fRsiduy + fRsidux * fRsiduy;
if ((iPosx >= 0) && (iPosy >= 0)) {
// number 0, 1, 2 is the index of MATRIX 'fTopeLeft'
fOut0 += fCoeff * fTopeLeft[0];
fOut1 += fCoeff * fTopeLeft[1];
fOut2 += fCoeff * fTopeLeft[2];
}
float fSum = fCoeff;
fCoeff = fRsiduy - fRsidux * fRsiduy;
if ((iPosx >= 0) && (iPosy < image.h - 1)) {
// Image channel G and B could be accessed by adding number of 1, 2
fOut0 += fCoeff * fTopeLeft[image.stride];
fOut1 += fCoeff * fTopeLeft[image.stride + 1];
fOut2 += fCoeff * fTopeLeft[image.stride + 2];
}
fSum += fCoeff;
fCoeff = fRsidux - fRsidux * fRsiduy;
if ((iPosx < image.w - 1) && (iPosy >= 0)) {
// Image channel G and B could be accessed by adding number of 1, 2
fOut0 += fCoeff * fTopeLeft[3];
fOut1 += fCoeff * fTopeLeft[3 + 1];
fOut2 += fCoeff * fTopeLeft[3 + 2];
}
fSum += fCoeff;
if ((iPosx < image.w - 1) && (iPosy < image.h - 1)) {
// Image channel G and B could be accessed by adding number of 1, 2
fOut0 += (1 - fSum) * fTopeLeft[image.stride + 3];
fOut1 += (1 - fSum) * fTopeLeft[image.stride + 3 + 1];
fOut2 += (1 - fSum) * fTopeLeft[image.stride + 3 + 2];
}
dst = CalDst(dst, fOut0, fOut1, fOut2);
}
}
}

static void ImageWarpAffineHWCUint8(imageToolsImage_t image, imageToolsImage_t warped_image, float invM[2][3]) {
// 3 is r, g, b
warped_image.stride *= 3;
image.stride *= 3;
float *warped_image_buff = reinterpret_cast<float *>(warped_image.image_buff);

uint8_t *image_buff = reinterpret_cast<uint8_t *>(image.image_buff);
for (int y0 = 0; y0 < warped_image.h; y0++) {
// Init pointers to start of rows
float *dst = warped_image_buff + y0 * warped_image.stride;

for (int x0 = 0; x0 < warped_image.w; x0++) {
float fPosx = (static_cast<float>(x0) * invM[0][0]) + (static_cast<float>(y0) * invM[0][1]) + invM[0][2];
float fPosy = (static_cast<float>(x0) * invM[1][0]) + (static_cast<float>(y0) * invM[1][1]) + invM[1][2];

int iPosy = static_cast<int>(fPosy + 2) - 2; // for floor like result until -2.
int iPosx = static_cast<int>(fPosx + 2) - 2; // for floor like result until -2.
if ((iPosx < -1) || (iPosx >= image.w) || (iPosy < -1) || (iPosy >= image.h)) {
dst = CalDst(dst, 0.0f, 0.0f, 0.0f);
continue;
}
float fRsiduy = fPosy - iPosy;
float fRsidux = fPosx - iPosx;
float fOut0 = 0;
float fOut1 = 0;
float fOut2 = 0;
uint8_t *uiTopeLeft = image_buff + iPosy * image.stride + iPosx * 3;
float fCoeff = 1 - fRsidux - fRsiduy + fRsidux * fRsiduy;
if ((iPosx >= 0) && (iPosy >= 0)) {
// number 0, 1, 2 is the index of MATRIX round.
fOut0 += fCoeff * static_cast<float>(uiTopeLeft[0]);
fOut1 += fCoeff * static_cast<float>(uiTopeLeft[1]);
fOut2 += fCoeff * static_cast<float>(uiTopeLeft[2]);
}
float fSum = fCoeff;
fCoeff = fRsiduy - fRsidux * fRsiduy;
if ((iPosx >= 0) && (iPosy < image.h - 1)) {
fOut0 += fCoeff * static_cast<float>(uiTopeLeft[image.stride]);
fOut1 += fCoeff * static_cast<float>(uiTopeLeft[image.stride + 1]);
fOut2 += fCoeff * static_cast<float>(uiTopeLeft[image.stride + 2]);
}
fSum += fCoeff;
fCoeff = fRsidux - fRsidux * fRsiduy;
if ((iPosx < image.w - 1) && (iPosy >= 0)) {
fOut0 += fCoeff * static_cast<float>(uiTopeLeft[3]);
fOut1 += fCoeff * static_cast<float>(uiTopeLeft[3 + 1]);
fOut2 += fCoeff * static_cast<float>(uiTopeLeft[3 + 2]);
}
fSum += fCoeff;
if ((iPosx < image.w - 1) && (iPosy < image.h - 1)) {
fOut0 += (1 - fSum) * static_cast<float>(uiTopeLeft[image.stride + 3]);
fOut1 += (1 - fSum) * static_cast<float>(uiTopeLeft[image.stride + 3 + 1]);
fOut2 += (1 - fSum) * static_cast<float>(uiTopeLeft[image.stride + 3 + 2]);
}
dst = CalDst(dst, fOut0, fOut1, fOut2);
}
}
}

int ImageWarpAffineHWC(imageToolsImage_t image, imageToolsImage_t warped_image, float M[2][3], bool bIsMInv) {
if ((IM_TOOL_DATA_TYPE_FLOAT != warped_image.dataType) ||
((IM_TOOL_DATA_TYPE_FLOAT != image.dataType) && (IM_TOOL_DATA_TYPE_UINT8 != image.dataType))) {
return IM_TOOL_RETURN_STATUS_INVALID_INPUT;
}
float invM[2][3];
if (bIsMInv) {
for (int iy = 0; iy < 2; iy++) {
for (int ix = 0; ix < 3; ix++) {
invM[iy][ix] = M[iy][ix];
}
}
} else {
InvAffine2x3(M, invM);
}

if (IM_TOOL_DATA_TYPE_FLOAT == image.dataType) {
ImageWarpAffineHWCFloat(image, warped_image, invM);
} else {
ImageWarpAffineHWCUint8(image, warped_image, invM);
}
return IM_TOOL_RETURN_STATUS_SUCCESS;
}

bool ResizePreserveARWithFiller(LiteMat &src, LiteMat &dst, int h, int w, float (*ratioShiftWShiftH)[3],
float (*invM)[2][3], int img_orientation) {
if (dst.IsEmpty()) {
dst.Init(w, h, src.channel_, LDataType::FLOAT32);
}
// uint8_t *dst_ptr = dst;
float varM[2][3] = {{1.0, 0, 0}, {0, 1.0, 0}};
float divisor = 2.0;
int rotationDstWidth = src.width_;
int rotationDstHeight = src.height_;
if (img_orientation > IM_TOOL_EXIF_ORIENTATION_0_DEG) {
UpdateOrientationAfineMat(src, &rotationDstWidth, &rotationDstHeight, &varM, img_orientation);
}

/* Resize after orientation fix */
float srcAR = static_cast<float>(rotationDstWidth) / static_cast<float>(rotationDstHeight);
float dstAR = static_cast<float>(dst.width_) / static_cast<float>(dst.height_);
auto dstActiveWidth = static_cast<float>(dst.width_);
auto dstActiveHeight = static_cast<float>(dst.height_);
float ratio, shiftW, shiftH;
if (srcAR < dstAR) {
ratio = static_cast<float>(dst.height_) / static_cast<float>(rotationDstHeight);
dstActiveWidth = static_cast<float>(rotationDstWidth) * ratio;
} else {
ratio = static_cast<float>(dst.width_) / static_cast<float>(rotationDstWidth);
dstActiveHeight = static_cast<float>(rotationDstHeight) * ratio;
}
shiftW = (static_cast<float>(dst.width_) - dstActiveWidth) / divisor;
shiftH = (static_cast<float>(dst.height_) - dstActiveHeight) / divisor;
for (auto &iy : varM) {
for (float &ix : iy) {
// cppcheck-suppress useStlAlgorithm
ix *= ratio;
}
}

varM[0][2] += shiftW;
varM[1][2] += shiftH;
/* Resize and shift by affine transform */
imageToolsImage_t imageIn, imageOut;
ImageToolsConvertImage(src, dst, &imageIn, &imageOut);
InvAffine2x3(varM, *invM);
int retVal = ImageWarpAffineHWC(imageIn, imageOut, *invM, true);
if (retVal != 0) {
return false;
}

// 0, 1, 2 is the index of corresponding elem in ratioShiftWShiftH
(*ratioShiftWShiftH)[0] = ratio;
(*ratioShiftWShiftH)[1] = shiftW;
(*ratioShiftWShiftH)[2] = shiftH;

return true;
}

} // namespace dataset } // namespace dataset
} // namespace mindspore } // namespace mindspore

+ 17
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.h View File

@@ -28,6 +28,19 @@ namespace mindspore {
namespace dataset { namespace dataset {


#define CV_PI 3.1415926535897932384626433832795 #define CV_PI 3.1415926535897932384626433832795
#define IM_TOOL_EXIF_ORIENTATION_0_DEG 1
#define IM_TOOL_EXIF_ORIENTATION_0_DEG_MIRROR 2
#define IM_TOOL_EXIF_ORIENTATION_180_DEG 3
#define IM_TOOL_EXIF_ORIENTATION_180_DEG_MIRROR 4
#define IM_TOOL_EXIF_ORIENTATION_90_DEG_MIRROR 5
#define IM_TOOL_EXIF_ORIENTATION_90_DEG 6
#define IM_TOOL_EXIF_ORIENTATION_270_DEG_MIRROR 7
#define IM_TOOL_EXIF_ORIENTATION_270_DEG 8
#define NUM_OF_RGB_CHANNELS 9
#define IM_TOOL_DATA_TYPE_FLOAT (1)
#define IM_TOOL_DATA_TYPE_UINT8 (2)
#define IM_TOOL_RETURN_STATUS_SUCCESS (0)
#define IM_TOOL_RETURN_STATUS_INVALID_INPUT (1)


#define INT16_CAST(X) \ #define INT16_CAST(X) \
static_cast<int16_t>(::std::min(::std::max(static_cast<int>(X + (X >= 0.f ? 0.5f : -0.5f)), -32768), 32767)); static_cast<int16_t>(::std::min(::std::max(static_cast<int>(X + (X >= 0.f ? 0.5f : -0.5f)), -32768), 32767));
@@ -140,6 +153,10 @@ bool Sobel(const LiteMat &src, LiteMat &dst, int flag_x, int flag_y, int ksize,
/// \brief Convert RGB image or color image to grayscale image /// \brief Convert RGB image or color image to grayscale image
bool ConvertRgbToGray(const LiteMat &src, LDataType data_type, int w, int h, LiteMat &mat); bool ConvertRgbToGray(const LiteMat &src, LDataType data_type, int w, int h, LiteMat &mat);


/// \brief Resize preserve AR with filler
bool ResizePreserveARWithFiller(LiteMat &src, LiteMat &dst, int h, int w, float (*ratioShiftWShiftH)[3],
float (*invM)[2][3], int img_orientation);

} // namespace dataset } // namespace dataset
} // namespace mindspore } // namespace mindspore
#endif // IMAGE_PROCESS_H_ #endif // IMAGE_PROCESS_H_

+ 8
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/lite_mat.h View File

@@ -63,6 +63,14 @@ struct Point {
Point(float _x, float _y) : x(_x), y(_y) {} Point(float _x, float _y) : x(_x), y(_y) {}
}; };


typedef struct imageToolsImage {
int w;
int h;
int stride;
int dataType;
void *image_buff;
} imageToolsImage_t;

using BOOL_C1 = Chn1<bool>; using BOOL_C1 = Chn1<bool>;
using BOOL_C2 = Chn2<bool>; using BOOL_C2 = Chn2<bool>;
using BOOL_C3 = Chn3<bool>; using BOOL_C3 = Chn3<bool>;


+ 37
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.cc View File

@@ -421,6 +421,43 @@ Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
return Status::OK(); return Status::OK();
} }


Status ResizePreserve(const TensorRow &inputs, int32_t height, int32_t width, int32_t img_orientation,
TensorRow *outputs) {
outputs->resize(3);
std::shared_ptr<Tensor> input = inputs[0];
LiteMat lite_mat_src(input->shape()[1], input->shape()[0], input->shape()[2],
const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())),
GetLiteCVDataType(input->type()));

LiteMat lite_mat_dst;
std::shared_ptr<Tensor> image_tensor;
TensorShape new_shape = TensorShape({height, width, input->shape()[2]});
RETURN_IF_NOT_OK(Tensor::CreateEmpty(new_shape, DataType(DataType::DE_FLOAT32), &image_tensor));
uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*image_tensor->begin<uint8_t>()));
lite_mat_dst.Init(width, height, input->shape()[2], reinterpret_cast<void *>(buffer), LDataType::FLOAT32);

float ratioShiftWShiftH[3] = {0};
float invM[2][3] = {{0, 0, 0}, {0, 0, 0}};
bool ret =
ResizePreserveARWithFiller(lite_mat_src, lite_mat_dst, height, width, &ratioShiftWShiftH, &invM, img_orientation);
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Resize: bilinear resize failed.");

std::shared_ptr<Tensor> ratio_tensor;
TensorShape ratio_shape = TensorShape({3});
RETURN_IF_NOT_OK(Tensor::CreateFromMemory(ratio_shape, DataType(DataType::DE_FLOAT32),
reinterpret_cast<uint8_t *>(&ratioShiftWShiftH), &ratio_tensor));

std::shared_ptr<Tensor> invM_tensor;
TensorShape invM_shape = TensorShape({2, 3});
RETURN_IF_NOT_OK(Tensor::CreateFromMemory(invM_shape, DataType(DataType::DE_FLOAT32),
reinterpret_cast<uint8_t *>(&invM), &invM_tensor));

(*outputs)[0] = image_tensor;
(*outputs)[1] = ratio_tensor;
(*outputs)[2] = invM_tensor;
return Status::OK();
}

Status RgbToGray(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) { Status RgbToGray(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
if (input->Rank() != 3) { if (input->Rank() != 3) {
RETURN_STATUS_UNEXPECTED("RgbToGray: input image is not in shape of <H,W,C>"); RETURN_STATUS_UNEXPECTED("RgbToGray: input image is not in shape of <H,W,C>");


+ 9
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.h View File

@@ -95,6 +95,15 @@ Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
int32_t output_width, double fx = 0.0, double fy = 0.0, int32_t output_width, double fx = 0.0, double fy = 0.0,
InterpolationMode mode = InterpolationMode::kLinear); InterpolationMode mode = InterpolationMode::kLinear);


/// \brief Returns Resized image.
/// \param[in] inputs input TensorRow
/// \param[in] height Height of output
/// \param[in] width Width of output
/// \param[in] img_orientation Angle method of image rotation
/// \param[out] outputs Resized image of shape <height,width,C> and same type as input
Status ResizePreserve(const TensorRow &inputs, int32_t height, int32_t width, int32_t img_orientation,
TensorRow *outputs);

/// \brief Take in a 3 channel image in RBG to GRAY /// \brief Take in a 3 channel image in RBG to GRAY
/// \param[in] input The input image /// \param[in] input The input image
/// \param[out] output The output image /// \param[out] output The output image


+ 39
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/resize_preserve_ar_op.cc View File

@@ -0,0 +1,39 @@
/**
* Copyright 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.
* 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/resize_preserve_ar_op.h"

#ifdef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/lite_image_utils.h"
#endif
#include "minddata/dataset/util/status.h"

namespace mindspore {
namespace dataset {
const int32_t ResizePreserveAROp::kDefImgorientation = 0;

ResizePreserveAROp::ResizePreserveAROp(int32_t height, int32_t width, int32_t img_orientation)
: height_(height), width_(width), img_orientation_(img_orientation) {}

Status ResizePreserveAROp::Compute(const TensorRow &inputs, TensorRow *outputs) {
IO_CHECK_VECTOR(inputs, outputs);
#ifdef ENABLE_ANDROID
return ResizePreserve(inputs, height_, width_, img_orientation_, outputs);
#endif
return Status::OK();
}

} // namespace dataset
} // namespace mindspore

+ 55
- 0
mindspore/ccsrc/minddata/dataset/kernels/image/resize_preserve_ar_op.h View File

@@ -0,0 +1,55 @@
/**
* Copyright 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.
* 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_RESIZE_PRESERVE_AR_OP_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_RESIZE_PRESERVE_AR_OP_H_

#include <memory>
#include <vector>
#include <string>

#include "minddata/dataset/core/tensor.h"
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/image_utils.h"
#else
#include "minddata/dataset/kernels/image/lite_image_utils.h"
#endif
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"

namespace mindspore {
namespace dataset {
class ResizePreserveAROp : public TensorOp {
public:
// Default values, also used by python_bindings.cc
static const int32_t kDefImgorientation;

ResizePreserveAROp(int32_t height, int32_t width, int32_t img_orientation = kDefImgorientation);

~ResizePreserveAROp() override = default;

Status Compute(const TensorRow &input, TensorRow *output) override;

std::string Name() const override { return kResizePreserveAROp; }

protected:
int32_t height_;
int32_t width_;
int32_t img_orientation_;
};
} // namespace dataset
} // namespace mindspore

#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_RESIZE_PRESERVE_AR_OP_H_

+ 20
- 0
mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.cc View File

@@ -72,6 +72,7 @@
#include "minddata/dataset/kernels/image/rgba_to_bgr_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/rgba_to_rgb_op.h"
#endif #endif
#include "minddata/dataset/kernels/image/resize_preserve_ar_op.h"
#include "minddata/dataset/kernels/image/rgb_to_gray_op.h" #include "minddata/dataset/kernels/image/rgb_to_gray_op.h"
#include "minddata/dataset/kernels/image/rotate_op.h" #include "minddata/dataset/kernels/image/rotate_op.h"
#ifndef ENABLE_ANDROID #ifndef ENABLE_ANDROID
@@ -1421,6 +1422,25 @@ Status ResizeOperation::to_json(nlohmann::json *out_json) {
return Status::OK(); return Status::OK();
} }


// ResizePreserveAROperation
ResizePreserveAROperation::ResizePreserveAROperation(int32_t height, int32_t width, int32_t img_orientation)
: height_(height), width_(width), img_orientation_(img_orientation) {}

Status ResizePreserveAROperation::ValidateParams() { return Status::OK(); }

std::shared_ptr<TensorOp> ResizePreserveAROperation::Build() {
return std::make_shared<ResizePreserveAROp>(height_, width_, img_orientation_);
}

Status ResizePreserveAROperation::to_json(nlohmann::json *out_json) {
nlohmann::json args;
args["height"] = height_;
args["width"] = width_;
args["img_orientation"] = img_orientation_;
*out_json = args;
return Status::OK();
}

// RotateOperation // RotateOperation
RotateOperation::RotateOperation() { rotate_op = std::make_shared<RotateOp>(0); } RotateOperation::RotateOperation() { rotate_op = std::make_shared<RotateOp>(0); }




+ 21
- 0
mindspore/ccsrc/minddata/dataset/kernels/ir/vision/vision_ir.h View File

@@ -71,6 +71,7 @@ constexpr char kRandomVerticalFlipOperation[] = "RandomVerticalFlip";
constexpr char kRandomVerticalFlipWithBBoxOperation[] = "RandomVerticalFlipWithBBox"; constexpr char kRandomVerticalFlipWithBBoxOperation[] = "RandomVerticalFlipWithBBox";
constexpr char kRescaleOperation[] = "Rescale"; constexpr char kRescaleOperation[] = "Rescale";
constexpr char kResizeOperation[] = "Resize"; constexpr char kResizeOperation[] = "Resize";
constexpr char kResizePreserveAROperation[] = "ResizePreserveAR";
constexpr char kResizeWithBBoxOperation[] = "ResizeWithBBox"; constexpr char kResizeWithBBoxOperation[] = "ResizeWithBBox";
constexpr char kRgbaToBgrOperation[] = "RgbaToBgr"; constexpr char kRgbaToBgrOperation[] = "RgbaToBgr";
constexpr char kRgbaToRgbOperation[] = "RgbaToRgb"; constexpr char kRgbaToRgbOperation[] = "RgbaToRgb";
@@ -781,6 +782,26 @@ class ResizeOperation : public TensorOperation {
InterpolationMode interpolation_; InterpolationMode interpolation_;
}; };


class ResizePreserveAROperation : public TensorOperation {
public:
ResizePreserveAROperation(int32_t height, int32_t width, int32_t img_orientation);

~ResizePreserveAROperation() = default;

std::shared_ptr<TensorOp> Build() override;

Status ValidateParams() override;

std::string Name() const override { return kResizePreserveAROperation; }

Status to_json(nlohmann::json *out_json) override;

private:
int32_t height_;
int32_t width_;
int32_t img_orientation_;
};

class ResizeWithBBoxOperation : public TensorOperation { class ResizeWithBBoxOperation : public TensorOperation {
public: public:
explicit ResizeWithBBoxOperation(std::vector<int32_t> size, InterpolationMode interpolation_mode); explicit ResizeWithBBoxOperation(std::vector<int32_t> size, InterpolationMode interpolation_mode);


+ 1
- 0
mindspore/ccsrc/minddata/dataset/kernels/tensor_op.h View File

@@ -94,6 +94,7 @@ constexpr char kRandomVerticalFlipWithBBoxOp[] = "RandomVerticalFlipWithBBoxOp";
constexpr char kRescaleOp[] = "RescaleOp"; constexpr char kRescaleOp[] = "RescaleOp";
constexpr char kResizeBilinearOp[] = "ResizeBilinearOp"; constexpr char kResizeBilinearOp[] = "ResizeBilinearOp";
constexpr char kResizeOp[] = "ResizeOp"; constexpr char kResizeOp[] = "ResizeOp";
constexpr char kResizePreserveAROp[] = "ResizePreserveAROp";
constexpr char kResizeWithBBoxOp[] = "ResizeWithBBoxOp"; constexpr char kResizeWithBBoxOp[] = "ResizeWithBBoxOp";
constexpr char kRgbaToBgrOp[] = "RgbaToBgrOp"; constexpr char kRgbaToBgrOp[] = "RgbaToBgrOp";
constexpr char kRgbaToRgbOp[] = "RgbaToRgbOp"; constexpr char kRgbaToRgbOp[] = "RgbaToRgbOp";


+ 23
- 0
mindspore/ccsrc/minddata/dataset/liteapi/include/vision_lite.h View File

@@ -91,6 +91,29 @@ class CenterCrop final : public TensorTransform {
std::shared_ptr<Data> data_; std::shared_ptr<Data> data_;
}; };


/// \brief ResizePreserveAR TensorTransform.
/// \notes Keep the original picture ratio and fill the rest.
class ResizePreserveAR final : public TensorTransform {
public:
/// \brief Constructor.
/// \param[in] height The height of image output value after resizing.
/// \param[in] width The width of image output value after resizing.
/// \param[in] img_orientation Angle method of image rotation.
ResizePreserveAR(int32_t height, int32_t width, int32_t img_orientation = 0);

/// \brief Destructor.
~ResizePreserveAR() = default;

protected:
/// \brief Function to convert TensorTransform object into a TensorOperation object.
/// \return Shared pointer to TensorOperation object.
std::shared_ptr<TensorOperation> Parse() override;

private:
struct Data;
std::shared_ptr<Data> data_;
};

/// \brief RGB2GRAY TensorTransform. /// \brief RGB2GRAY TensorTransform.
/// \notes Convert RGB image or color image to grayscale image /// \notes Convert RGB image or color image to grayscale image
class RGB2GRAY : public TensorTransform { class RGB2GRAY : public TensorTransform {


+ 3
- 0
mindspore/lite/minddata/CMakeLists.txt View File

@@ -199,6 +199,7 @@ if(BUILD_MINDDATA STREQUAL "full")
${MINDDATA_DIR}/kernels/image/decode_op.cc ${MINDDATA_DIR}/kernels/image/decode_op.cc
${MINDDATA_DIR}/kernels/image/normalize_op.cc ${MINDDATA_DIR}/kernels/image/normalize_op.cc
${MINDDATA_DIR}/kernels/image/resize_op.cc ${MINDDATA_DIR}/kernels/image/resize_op.cc
${MINDDATA_DIR}/kernels/image/resize_preserve_ar_op.cc
${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc ${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc
${MINDDATA_DIR}/kernels/image/rotate_op.cc ${MINDDATA_DIR}/kernels/image/rotate_op.cc
${MINDDATA_DIR}/kernels/image/random_affine_op.cc ${MINDDATA_DIR}/kernels/image/random_affine_op.cc
@@ -282,6 +283,7 @@ elseif(BUILD_MINDDATA STREQUAL "wrapper")
${MINDDATA_DIR}/kernels/image/crop_op.cc ${MINDDATA_DIR}/kernels/image/crop_op.cc
${MINDDATA_DIR}/kernels/image/normalize_op.cc ${MINDDATA_DIR}/kernels/image/normalize_op.cc
${MINDDATA_DIR}/kernels/image/resize_op.cc ${MINDDATA_DIR}/kernels/image/resize_op.cc
${MINDDATA_DIR}/kernels/image/resize_preserve_ar_op.cc.cc
${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc ${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc
${MINDDATA_DIR}/kernels/image/rotate_op.cc ${MINDDATA_DIR}/kernels/image/rotate_op.cc
${MINDDATA_DIR}/kernels/data/compose_op.cc ${MINDDATA_DIR}/kernels/data/compose_op.cc
@@ -381,6 +383,7 @@ elseif(BUILD_MINDDATA STREQUAL "lite")
"${MINDDATA_DIR}/kernels/image/random_vertical_flip_with_bbox_op.cc" "${MINDDATA_DIR}/kernels/image/random_vertical_flip_with_bbox_op.cc"
"${MINDDATA_DIR}/kernels/image/random_sharpness_op.cc" "${MINDDATA_DIR}/kernels/image/random_sharpness_op.cc"
"${MINDDATA_DIR}/kernels/image/rescale_op.cc" "${MINDDATA_DIR}/kernels/image/rescale_op.cc"
"${MINDDATA_DIR}/kernels/image/resize_preserve_ar_op.cc"
"${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc" "${MINDDATA_DIR}/kernels/image/rgb_to_gray_op.cc"
"${MINDDATA_DIR}/kernels/image/rgba_to_bgr_op.cc" "${MINDDATA_DIR}/kernels/image/rgba_to_bgr_op.cc"
"${MINDDATA_DIR}/kernels/image/rgba_to_rgb_op.cc" "${MINDDATA_DIR}/kernels/image/rgba_to_rgb_op.cc"


+ 13
- 2
mindspore/lite/minddata/example/CMakeLists.txt View File

@@ -4,8 +4,8 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror -Wall -fPIC -std=c++17")


set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-compare")


set(MD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mindspore-lite-1.1.0-inference-linux-x64/minddata")
set(MS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mindspore-lite-1.1.0-inference-linux-x64/")
set(MD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mindspore-lite-1.2.0-inference-linux-x64/minddata")
set(MS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/mindspore-lite-1.2.0-inference-linux-x64/")


include_directories(${MD_DIR}) include_directories(${MD_DIR})
include_directories(${MS_DIR}) include_directories(${MS_DIR})
@@ -16,6 +16,17 @@ add_executable(testlenet
) )


target_link_libraries(testlenet target_link_libraries(testlenet
${MD_DIR}/lib/libminddata-lite.so
${MD_DIR}/third_party/libjpeg-turbo/lib/libjpeg.so.62
${MD_DIR}/third_party/libjpeg-turbo/lib/libturbojpeg.so.0
${MS_DIR}/lib/libmindspore-lite.so
pthread)

add_executable(testresize
${CMAKE_CURRENT_SOURCE_DIR}/testresize.cpp
)

target_link_libraries(testresize
${MD_DIR}/lib/libminddata-lite.so ${MD_DIR}/lib/libminddata-lite.so
${MD_DIR}/third_party/libjpeg-turbo/lib/libjpeg.so.62 ${MD_DIR}/third_party/libjpeg-turbo/lib/libjpeg.so.62
${MD_DIR}/third_party/libjpeg-turbo/lib/libturbojpeg.so.0 ${MD_DIR}/third_party/libjpeg-turbo/lib/libturbojpeg.so.0


+ 68
- 0
mindspore/lite/minddata/example/testresize.cpp View File

@@ -0,0 +1,68 @@
/**
* Copyright 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.
* 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 <sys/stat.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

#include "include/datasets.h"
#include "include/iterator.h"
#include "include/vision_lite.h"
#include "include/transforms.h"
#include "include/api/types.h"

using mindspore::dataset::Album;
using mindspore::dataset::Dataset;
using mindspore::dataset::Iterator;
using mindspore::dataset::SequentialSampler;
using mindspore::dataset::TensorTransform;
using mindspore::dataset::vision::ResizePreserveAR;


int main(int argc, char **argv) {
std::string folder_path = "./testAlbum/images";
std::string schema_file = "./testAlbum/datasetSchema.json";
std::vector<std::string> column_names = {"image", "label", "id"};

// Create a Album Dataset
std::shared_ptr<Dataset> ds =
Album(folder_path, schema_file, column_names, true, std::make_shared<SequentialSampler>(0, 1));
ds = ds->SetNumWorkers(1);

std::shared_ptr<TensorTransform> resize(new ResizePreserveAR(1000, 1000));
ds = ds->Map({resize}, {"image"}, {"image", "ratio", "invM"});

std::shared_ptr<Iterator> iter = ds->CreateIterator();

std::unordered_map<std::string, mindspore::MSTensor> row;
iter->GetNextRow(&row);

uint64_t i = 0;
while (row.size() != 0) {
i++;
iter->GetNextRow(&row);
}

iter->Stop();
}

+ 17
- 0
tests/ut/cpp/dataset/image_process_test.cc View File

@@ -1736,3 +1736,20 @@ TEST_F(MindDataImageProcess, testConvertRgbToGray) {
cv::imwrite("./mindspore_image.jpg", dst_image); cv::imwrite("./mindspore_image.jpg", dst_image);
CompareMat(rgb_mat, lite_mat_gray); CompareMat(rgb_mat, lite_mat_gray);
} }

TEST_F(MindDataImageProcess, testResizePreserveARWithFillerv) {
std::string filename = "data/dataset/apple.jpg";
cv::Mat image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR);

LiteMat lite_mat_rgb;
lite_mat_rgb.Init(image.cols, image.rows, image.channels(), image.data, LDataType::UINT8);
LiteMat lite_mat_resize;
float ratioShiftWShiftH[3] = {0};
float invM[2][3] = {{0, 0, 0}, {0, 0, 0}};
int h = 1000;
int w = 1000;
bool ret = ResizePreserveARWithFiller(lite_mat_rgb, lite_mat_resize, h, w, &ratioShiftWShiftH, &invM, 0);
ASSERT_TRUE(ret == true);
cv::Mat dst_image(lite_mat_resize.height_, lite_mat_resize.width_, CV_32FC3, lite_mat_resize.data_ptr_);
cv::imwrite("./mindspore_image.jpg", dst_image);
}

Loading…
Cancel
Save