Browse Source

!9788 [MD]Memory optimization for lite

From: @xulei2020
Reviewed-by: @HilbertDavid,@liucunwei
Signed-off-by: @HilbertDavid
tags/v1.1.0
mindspore-ci-bot Gitee 5 years ago
parent
commit
841cc05b61
3 changed files with 130 additions and 45 deletions
  1. +71
    -15
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.cc
  2. +2
    -2
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/lite_mat.cc
  3. +57
    -28
      mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.cc

+ 71
- 15
mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/image_process.cc View File

@@ -222,18 +222,26 @@ bool ResizeBilinear(const LiteMat &src, LiteMat &dst, int dst_w, int dst_h) {
if (src.data_type_ != LDataType::UINT8) { if (src.data_type_ != LDataType::UINT8) {
return false; return false;
} }
if (src.channel_ != 3 && src.channel_ != 1) {
return false;
}
if (dst.IsEmpty()) {
(void)dst.Init(dst_w, dst_h, src.channel_, LDataType::UINT8);
} else if (dst.height_ != dst_h || dst.width_ != dst_w || dst.channel_ != src.channel_) {
return false;
} else if (dst.data_type_ != LDataType::UINT8) {
return false;
} else {
}

if (src.channel_ == 3) { if (src.channel_ == 3) {
(void)dst.Init(dst_w, dst_h, 3, LDataType::UINT8);
const unsigned char *src_start_p = src; const unsigned char *src_start_p = src;
unsigned char *dst_start_p = dst; unsigned char *dst_start_p = dst;
(void)ResizeBilinear3C(src_start_p, src.width_, src.height_, dst_start_p, dst_w, dst_h); (void)ResizeBilinear3C(src_start_p, src.width_, src.height_, dst_start_p, dst_w, dst_h);
} else if (src.channel_ == 1) {
(void)dst.Init(dst_w, dst_h, 1, LDataType::UINT8);
} else { // channel == 1
const unsigned char *src_start_p = src; const unsigned char *src_start_p = src;
unsigned char *dst_start_p = dst; unsigned char *dst_start_p = dst;
(void)ResizeBilinear1C(src_start_p, src.width_, src.height_, dst_start_p, dst_w, dst_h); (void)ResizeBilinear1C(src_start_p, src.width_, src.height_, dst_start_p, dst_w, dst_h);
} else {
return false;
} }
return true; return true;
} }
@@ -418,7 +426,13 @@ bool ConvertTo(const LiteMat &src, LiteMat &dst, double scale) {
if (scale < 0.0 || scale > 100) { if (scale < 0.0 || scale > 100) {
return false; return false;
} }
(void)dst.Init(src.width_, src.height_, src.channel_, LDataType::FLOAT32);
if (dst.IsEmpty()) {
(void)dst.Init(src.width_, src.height_, src.channel_, LDataType::FLOAT32);
} else if (dst.height_ != src.height_ || dst.width_ != src.width_ || dst.channel_ != src.channel_) {
return false;
} else if (dst.data_type_ != LDataType::FLOAT32) {
return false;
}
const unsigned char *src_start_p = src; const unsigned char *src_start_p = src;
float *dst_start_p = dst; float *dst_start_p = dst;
for (int h = 0; h < src.height_; h++) { for (int h = 0; h < src.height_; h++) {
@@ -433,11 +447,17 @@ bool ConvertTo(const LiteMat &src, LiteMat &dst, double scale) {
} }


template <typename T> template <typename T>
static void CropInternal(const LiteMat &src, LiteMat &dst, int x, int y, int w, int h) {
static bool CropInternal(const LiteMat &src, LiteMat &dst, int x, int y, int w, int h) {
int dst_h = h; int dst_h = h;
int dst_w = w; int dst_w = w;
int dst_c = src.channel_; int dst_c = src.channel_;
dst.Init(dst_w, dst_h, dst_c, src.data_type_);
if (dst.IsEmpty()) {
dst.Init(dst_w, dst_h, dst_c, src.data_type_);
} else if (dst.height_ != h || dst.width_ != w || dst.channel_ != src.channel_) {
return false;
} else if (dst.data_type_ != src.data_type_) {
return false;
}
const T *src_start_p = src; const T *src_start_p = src;
T *dst_start_p = dst; T *dst_start_p = dst;
for (int i_h = 0; i_h < dst_h; i_h++) { for (int i_h = 0; i_h < dst_h; i_h++) {
@@ -445,6 +465,7 @@ static void CropInternal(const LiteMat &src, LiteMat &dst, int x, int y, int w,
T *dst_index_p = dst_start_p + i_h * dst_w * dst_c; T *dst_index_p = dst_start_p + i_h * dst_w * dst_c;
(void)memcpy(dst_index_p, src_index_p, dst_w * dst_c * sizeof(T)); (void)memcpy(dst_index_p, src_index_p, dst_w * dst_c * sizeof(T));
} }
return true;
} }


bool Crop(const LiteMat &src, LiteMat &dst, int x, int y, int w, int h) { bool Crop(const LiteMat &src, LiteMat &dst, int x, int y, int w, int h) {
@@ -456,9 +477,9 @@ bool Crop(const LiteMat &src, LiteMat &dst, int x, int y, int w, int h) {
} }


if (src.data_type_ == LDataType::UINT8) { if (src.data_type_ == LDataType::UINT8) {
CropInternal<uint8_t>(src, dst, x, y, w, h);
return CropInternal<uint8_t>(src, dst, x, y, w, h);
} else if (src.data_type_ == LDataType::FLOAT32) { } else if (src.data_type_ == LDataType::FLOAT32) {
CropInternal<float>(src, dst, x, y, w, h);
return CropInternal<float>(src, dst, x, y, w, h);
} else { } else {
return false; return false;
} }
@@ -511,8 +532,13 @@ bool SubStractMeanNormalize(const LiteMat &src, LiteMat &dst, const std::vector<
if (!CheckMeanAndStd(src.channel_, mean, std)) { if (!CheckMeanAndStd(src.channel_, mean, std)) {
return false; return false;
} }

dst.Init(src.width_, src.height_, src.channel_, LDataType::FLOAT32);
if (dst.IsEmpty()) {
dst.Init(src.width_, src.height_, src.channel_, LDataType::FLOAT32);
} else if (dst.height_ != src.height_ || dst.width_ != src.width_ || dst.channel_ != src.channel_) {
return false;
} else if (dst.data_type_ != LDataType::FLOAT32) {
return false;
}


const float *src_start_p = src; const float *src_start_p = src;
float *dst_start_p = dst; float *dst_start_p = dst;
@@ -880,8 +906,14 @@ bool ImplementAffine(LiteMat &src, LiteMat &out_img, const double M[6], std::vec
double b2 = -IM[3] * IM[2] - IM[4] * IM[5]; double b2 = -IM[3] * IM[2] - IM[4] * IM[5];
IM[2] = b1; IM[2] = b1;
IM[5] = b2; IM[5] = b2;
if (out_img.IsEmpty()) {
out_img.Init(dsize[0], dsize[1], sizeof(Pixel_Type), src.data_type_);
} else if (out_img.height_ != dsize[1] || out_img.width_ != dsize[0] || out_img.channel_ != src.channel_) {
return false;
} else if (out_img.data_type_ != src.data_type_) {
return false;
}


out_img.Init(dsize[0], dsize[1], sizeof(Pixel_Type));
for (int y = 0; y < out_img.height_; y++) { for (int y = 0; y < out_img.height_; y++) {
for (int x = 0; x < out_img.width_; x++) { for (int x = 0; x < out_img.width_; x++) {
int src_x = IM[0] * x + IM[1] * y + IM[2]; int src_x = IM[0] * x + IM[1] * y + IM[2];
@@ -899,11 +931,35 @@ bool ImplementAffine(LiteMat &src, LiteMat &out_img, const double M[6], std::vec
} }


bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, UINT8_C1 borderValue) { bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, UINT8_C1 borderValue) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
if (src.channel_ == 1 && src.data_type_ == LDataType::UINT8) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
} else {
return false;
}
} }


bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, UINT8_C3 borderValue) { bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, UINT8_C3 borderValue) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
if (src.channel_ == 3 && src.data_type_ == LDataType::UINT8) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
} else {
return false;
}
}

bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, FLOAT32_C1 borderValue) {
if (src.channel_ == 1 && src.data_type_ == LDataType::FLOAT32) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
} else {
return false;
}
}

bool Affine(LiteMat &src, LiteMat &out_img, const double M[6], std::vector<size_t> dsize, FLOAT32_C3 borderValue) {
if (src.channel_ == 3 && src.data_type_ == LDataType::FLOAT32) {
return ImplementAffine(src, out_img, M, dsize, borderValue);
} else {
return false;
}
} }


} // namespace dataset } // namespace dataset


+ 2
- 2
mindspore/ccsrc/minddata/dataset/kernels/image/lite_cv/lite_mat.cc View File

@@ -229,7 +229,7 @@ void LiteMat::Init(int width, int height, int channel, void *p_data, LDataType d
ref_count_ = nullptr; ref_count_ = nullptr;
} }


bool LiteMat::IsEmpty() const { return data_ptr_ == 0 || data_ptr_ == nullptr || c_step_ * channel_ == 0; }
bool LiteMat::IsEmpty() const { return data_ptr_ == nullptr || c_step_ * channel_ == 0; }


void LiteMat::Release() { void LiteMat::Release() {
if (ref_count_ && (addRef(ref_count_, -1) == 1)) { if (ref_count_ && (addRef(ref_count_, -1) == 1)) {
@@ -240,7 +240,7 @@ void LiteMat::Release() {
delete[] ref_count_; delete[] ref_count_;
} }
} }
data_ptr_ = 0;
data_ptr_ = nullptr;
elem_size_ = 0; elem_size_ = 0;
width_ = 0; width_ = 0;
height_ = 0; height_ = 0;


+ 57
- 28
mindspore/ccsrc/minddata/dataset/kernels/image/lite_image_utils.cc View File

@@ -267,13 +267,18 @@ Status Crop(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *outpu
int num_channels = input->shape()[2]; int num_channels = input->shape()[2];
shape = shape.AppendDim(num_channels); shape = shape.AppendDim(num_channels);
} }

std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateEmpty(shape, input->type(), &output_tensor));

uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));
LiteMat lite_mat_cut; LiteMat lite_mat_cut;

lite_mat_cut.Init(w, h, lite_mat_rgb.channel_, reinterpret_cast<void *>(buffer), GetLiteCVDataType(input->type()));

bool ret = Crop(lite_mat_rgb, lite_mat_cut, x, y, w, h); bool ret = Crop(lite_mat_rgb, lite_mat_cut, x, y, w, h);
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Crop failed in lite cv"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Crop failed in lite cv");
// create output Tensor based off of lite_mat_cut
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(
Tensor::CreateFromMemory(shape, input->type(), static_cast<uchar *>(lite_mat_cut.data_ptr_), &output_tensor));

*output = output_tensor; *output = output_tensor;
return Status::OK(); return Status::OK();
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
@@ -340,6 +345,14 @@ Status Normalize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *
const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())), const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())),
GetLiteCVDataType(input->type())); GetLiteCVDataType(input->type()));


std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateEmpty(input->shape(), DataType(DataType::DE_FLOAT32), &output_tensor));

uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));

lite_mat_norm.Init(lite_mat_rgb.width_, lite_mat_rgb.height_, lite_mat_rgb.channel_,
reinterpret_cast<void *>(buffer), GetLiteCVDataType(input->type()));

if (input->type() == DataType::DE_UINT8) { if (input->type() == DataType::DE_UINT8) {
LiteMat lite_mat_float; LiteMat lite_mat_float;
// change input to float // change input to float
@@ -351,10 +364,6 @@ Status Normalize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *
} }
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Normalize in lite cv failed"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Normalize in lite cv failed");


// create output Tensor based off of lite_mat_cut
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateFromMemory(input->shape(), DataType(DataType::DE_FLOAT32),
static_cast<uchar *>(lite_mat_norm.data_ptr_), &output_tensor));
*output = output_tensor; *output = output_tensor;
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
RETURN_STATUS_UNEXPECTED("Unexpected error in normalize."); RETURN_STATUS_UNEXPECTED("Unexpected error in normalize.");
@@ -394,11 +403,17 @@ Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
} }


LiteMat lite_mat_resize; LiteMat lite_mat_resize;
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateEmpty(shape, input->type(), &output_tensor));

uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));

lite_mat_resize.Init(output_width, output_height, lite_mat_rgb.channel_, reinterpret_cast<void *>(buffer),
GetLiteCVDataType(input->type()));

bool ret = ResizeBilinear(lite_mat_rgb, lite_mat_resize, output_width, output_height); bool ret = ResizeBilinear(lite_mat_rgb, lite_mat_resize, output_width, output_height);
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Resize failed in lite cv"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Resize failed in lite cv");
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(
Tensor::CreateFromMemory(shape, input->type(), static_cast<uchar *>(lite_mat_resize.data_ptr_), &output_tensor));

*output = output_tensor; *output = output_tensor;
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
RETURN_STATUS_UNEXPECTED("Error in image resize."); RETURN_STATUS_UNEXPECTED("Error in image resize.");
@@ -426,14 +441,23 @@ Status Pad(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output
const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())), const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())),
GetLiteCVDataType(input->type())); GetLiteCVDataType(input->type()));
LiteMat lite_mat_pad; LiteMat lite_mat_pad;

std::shared_ptr<Tensor> output_tensor;

int pad_width = lite_mat_rgb.width_ + pad_left + pad_right;
int pad_height = lite_mat_rgb.height_ + pad_top + pad_bottom;
TensorShape new_shape = TensorShape({pad_height, pad_width, input->shape()[2]});
RETURN_IF_NOT_OK(Tensor::CreateEmpty(new_shape, input->type(), &output_tensor));

uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));

lite_mat_pad.Init(pad_width, pad_height, lite_mat_rgb.channel_, reinterpret_cast<void *>(buffer),
GetLiteCVDataType(input->type()));

bool ret = Pad(lite_mat_rgb, lite_mat_pad, pad_top, pad_bottom, pad_left, pad_right, bool ret = Pad(lite_mat_rgb, lite_mat_pad, pad_top, pad_bottom, pad_left, pad_right,
PaddBorderType::PADD_BORDER_CONSTANT, fill_r, fill_g, fill_b); PaddBorderType::PADD_BORDER_CONSTANT, fill_r, fill_g, fill_b);
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Pad failed in lite cv"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Pad failed in lite cv");
// new shape for output tensor
TensorShape new_shape = TensorShape({lite_mat_pad.height_, lite_mat_pad.width_, input->shape()[2]});
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(
Tensor::CreateFromMemory(new_shape, input->type(), static_cast<uchar *>(lite_mat_pad.data_ptr_), &output_tensor));

*output = output_tensor; *output = output_tensor;
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
RETURN_STATUS_UNEXPECTED("Error in image Pad."); RETURN_STATUS_UNEXPECTED("Error in image Pad.");
@@ -451,7 +475,6 @@ static Status RotateAngleWithOutMirror(const std::shared_ptr<Tensor> &input, std
LiteMat lite_mat_rgb(input->shape()[1], input->shape()[0], input->shape()[2], LiteMat lite_mat_rgb(input->shape()[1], input->shape()[0], input->shape()[2],
const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())), const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())),
GetLiteCVDataType(input->type())); GetLiteCVDataType(input->type()));
LiteMat lite_mat_affine;


if (orientation == 3) { if (orientation == 3) {
height = lite_mat_rgb.height_; height = lite_mat_rgb.height_;
@@ -486,14 +509,17 @@ static Status RotateAngleWithOutMirror(const std::shared_ptr<Tensor> &input, std
std::vector<size_t> dsize; std::vector<size_t> dsize;
dsize.push_back(width); dsize.push_back(width);
dsize.push_back(height); dsize.push_back(height);
LiteMat lite_mat_affine;
std::shared_ptr<Tensor> output_tensor;
TensorShape new_shape = TensorShape({height, width, input->shape()[2]});
RETURN_IF_NOT_OK(Tensor::CreateEmpty(new_shape, input->type(), &output_tensor));
uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));
lite_mat_affine.Init(width, height, lite_mat_rgb.channel_, reinterpret_cast<void *>(buffer),
GetLiteCVDataType(input->type()));

bool ret = Affine(lite_mat_rgb, lite_mat_affine, M, dsize, UINT8_C3(0, 0, 0)); bool ret = Affine(lite_mat_rgb, lite_mat_affine, M, dsize, UINT8_C3(0, 0, 0));
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Rotate failed in lite cv"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Rotate failed in lite cv");


// new shape for output tensor
TensorShape new_shape = TensorShape({lite_mat_affine.height_, lite_mat_affine.width_, input->shape()[2]});
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateFromMemory(new_shape, input->type(), static_cast<uchar *>(lite_mat_affine.data_ptr_),
&output_tensor));
*output = output_tensor; *output = output_tensor;
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
RETURN_STATUS_UNEXPECTED("Error in image Rotate."); RETURN_STATUS_UNEXPECTED("Error in image Rotate.");
@@ -511,7 +537,7 @@ static Status RotateAngleWithMirror(const std::shared_ptr<Tensor> &input, std::s
LiteMat lite_mat_rgb(input->shape()[1], input->shape()[0], input->shape()[2], LiteMat lite_mat_rgb(input->shape()[1], input->shape()[0], input->shape()[2],
const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())), const_cast<void *>(reinterpret_cast<const void *>(input->GetBuffer())),
GetLiteCVDataType(input->type())); GetLiteCVDataType(input->type()));
LiteMat lite_mat_affine;
if (orientation == 2) { if (orientation == 2) {
height = lite_mat_rgb.height_; height = lite_mat_rgb.height_;
width = lite_mat_rgb.width_; width = lite_mat_rgb.width_;
@@ -553,14 +579,17 @@ static Status RotateAngleWithMirror(const std::shared_ptr<Tensor> &input, std::s
std::vector<size_t> dsize; std::vector<size_t> dsize;
dsize.push_back(width); dsize.push_back(width);
dsize.push_back(height); dsize.push_back(height);
LiteMat lite_mat_affine;
std::shared_ptr<Tensor> output_tensor;
TensorShape new_shape = TensorShape({height, width, input->shape()[2]});
RETURN_IF_NOT_OK(Tensor::CreateEmpty(new_shape, input->type(), &output_tensor));
uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));
lite_mat_affine.Init(width, height, lite_mat_rgb.channel_, reinterpret_cast<void *>(buffer),
GetLiteCVDataType(input->type()));

bool ret = Affine(lite_mat_rgb, lite_mat_affine, M, dsize, UINT8_C3(0, 0, 0)); bool ret = Affine(lite_mat_rgb, lite_mat_affine, M, dsize, UINT8_C3(0, 0, 0));
CHECK_FAIL_RETURN_UNEXPECTED(ret, "Rotate failed in lite cv"); CHECK_FAIL_RETURN_UNEXPECTED(ret, "Rotate failed in lite cv");


// new shape for output tensor
TensorShape new_shape = TensorShape({lite_mat_affine.height_, lite_mat_affine.width_, input->shape()[2]});
std::shared_ptr<Tensor> output_tensor;
RETURN_IF_NOT_OK(Tensor::CreateFromMemory(new_shape, input->type(), static_cast<uchar *>(lite_mat_affine.data_ptr_),
&output_tensor));
*output = output_tensor; *output = output_tensor;
} catch (std::runtime_error &e) { } catch (std::runtime_error &e) {
RETURN_STATUS_UNEXPECTED("Error in image Rotate."); RETURN_STATUS_UNEXPECTED("Error in image Rotate.");


Loading…
Cancel
Save