[MS][LITE]fix lite minddata DecodeCv read jpeg only issue.

This commit is contained in:
youshu1 2022-11-02 16:25:09 +08:00
parent 0d90568241
commit e25d619c4b
3 changed files with 117 additions and 0 deletions

View File

@ -32,6 +32,7 @@
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/kernels/image/resize_cubic_op.h"
#endif
#define MAX_INT_PRECISION 16777216 // float int precision is 16777216
namespace mindspore {
@ -289,11 +290,39 @@ static LDataType GetLiteCVDataType(const DataType &data_type) {
}
}
#if defined(ENABLE_CLOUD_FUSION_INFERENCE)
Status DecodeCv(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
std::shared_ptr<CVTensor> input_cv = CVTensor::AsCVTensor(input);
if (!input_cv->mat().data) {
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Decode: load image failed.");
}
try {
cv::Mat img_mat = cv::imdecode(input_cv->mat(), cv::IMREAD_COLOR | cv::IMREAD_IGNORE_ORIENTATION);
if (img_mat.data == nullptr) {
std::string err = "Decode: image decode failed.";
RETURN_STATUS_UNEXPECTED(err);
}
cv::cvtColor(img_mat, img_mat, static_cast<int>(cv::COLOR_BGR2RGB));
std::shared_ptr<CVTensor> output_cv;
dsize_t rank_num = 3;
RETURN_IF_NOT_OK(CVTensor::CreateFromMat(img_mat, rank_num, &output_cv));
*output = std::static_pointer_cast<Tensor>(output_cv);
return Status::OK();
} catch (const cv::Exception &e) {
RETURN_STATUS_UNEXPECTED("Decode: " + std::string(e.what()));
}
}
#endif
Status Decode(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
if (IsNonEmptyJPEG(input)) {
return JpegCropAndDecode(input, output);
} else {
#if defined(ENABLE_CLOUD_FUSION_INFERENCE)
return DecodeCv(input, output);
#else
RETURN_STATUS_UNEXPECTED("Decode: Decode only supports jpeg for android");
#endif
}
}
@ -414,6 +443,91 @@ Status Normalize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *
return Status::OK();
}
#if defined(ENABLE_CLOUD_FUSION_INFERENCE)
int GetCVInterpolationMode(InterpolationMode mode) {
switch (mode) {
case InterpolationMode::kLinear:
return static_cast<int>(cv::InterpolationFlags::INTER_LINEAR);
case InterpolationMode::kCubic:
return static_cast<int>(cv::InterpolationFlags::INTER_CUBIC);
case InterpolationMode::kArea:
return static_cast<int>(cv::InterpolationFlags::INTER_AREA);
case InterpolationMode::kNearestNeighbour:
return static_cast<int>(cv::InterpolationFlags::INTER_NEAREST);
default:
return static_cast<int>(cv::InterpolationFlags::INTER_LINEAR);
}
}
Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int32_t output_height,
int32_t output_width, double fx, double fy, InterpolationMode mode) {
std::shared_ptr<CVTensor> input_cv = CVTensor::AsCVTensor(input);
if (!input_cv->mat().data) {
RETURN_STATUS_UNEXPECTED("[Internal ERROR] Resize: load image failed.");
}
RETURN_IF_NOT_OK(ValidateImageRank("Resize", input_cv->Rank()));
cv::Mat in_image = input_cv->mat();
const uint32_t kResizeShapeLimits = 1000;
// resize image too large or too small, 1000 is arbitrarily chosen here to prevent open cv from segmentation fault
CHECK_FAIL_RETURN_UNEXPECTED((std::numeric_limits<int>::max() / kResizeShapeLimits) > in_image.rows,
"Resize: in_image rows out of bounds.");
CHECK_FAIL_RETURN_UNEXPECTED((std::numeric_limits<int>::max() / kResizeShapeLimits) > in_image.cols,
"Resize: in_image cols out of bounds.");
if (output_height > in_image.rows * kResizeShapeLimits || output_width > in_image.cols * kResizeShapeLimits) {
std::string err_msg =
"Resize: the resizing width or height is too big, it's 1000 times bigger than the original image, got output "
"height: " +
std::to_string(output_height) + ", width: " + std::to_string(output_width) +
", and original image size:" + std::to_string(in_image.rows) + ", " + std::to_string(in_image.cols);
return Status(StatusCode::kMDShapeMisMatch, err_msg);
}
if (output_height == 0 || output_width == 0) {
std::string err_msg = "Resize: the input value of 'resize' is invalid, width or height is zero.";
return Status(StatusCode::kMDShapeMisMatch, err_msg);
}
if (mode == InterpolationMode::kCubicPil) {
if (input_cv->shape().Size() != kDefaultImageChannel ||
input_cv->shape()[kChannelIndexHWC] != kDefaultImageChannel) {
RETURN_STATUS_UNEXPECTED("Resize: Interpolation mode PILCUBIC only supports image with 3 channels, but got: " +
input_cv->shape().ToString());
}
LiteMat imIn, imOut;
std::shared_ptr<Tensor> output_tensor;
TensorShape new_shape = TensorShape({output_height, output_width, 3});
RETURN_IF_NOT_OK(Tensor::CreateEmpty(new_shape, input_cv->type(), &output_tensor));
uint8_t *buffer = reinterpret_cast<uint8_t *>(&(*output_tensor->begin<uint8_t>()));
imOut.Init(output_width, output_height, static_cast<int>(input_cv->shape()[kChannelIndexHWC]),
reinterpret_cast<void *>(buffer), LDataType::UINT8);
imIn.Init(static_cast<int>(input_cv->shape()[1]), static_cast<int>(input_cv->shape()[0]),
static_cast<int>(input_cv->shape()[kChannelIndexHWC]), input_cv->mat().data, LDataType::UINT8);
if (ResizeCubic(imIn, imOut, output_width, output_height) == false) {
RETURN_STATUS_UNEXPECTED("Resize: failed to do resize, please check the error msg.");
}
*output = output_tensor;
return Status::OK();
}
try {
TensorShape shape{output_height, output_width};
if (input_cv->Rank() == kDefaultImageRank) {
int num_channels = static_cast<int>(input_cv->shape()[kChannelIndexHWC]);
shape = shape.AppendDim(num_channels);
}
std::shared_ptr<CVTensor> output_cv;
RETURN_IF_NOT_OK(CVTensor::CreateEmpty(shape, input_cv->type(), &output_cv));
auto cv_mode = GetCVInterpolationMode(mode);
cv::resize(in_image, output_cv->mat(), cv::Size(output_width, output_height), fx, fy, cv_mode);
*output = std::static_pointer_cast<Tensor>(output_cv);
return Status::OK();
} catch (const cv::Exception &e) {
RETURN_STATUS_UNEXPECTED("Resize: " + std::string(e.what()));
}
}
#else
Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int32_t output_height,
int32_t output_width, double fx, double fy, InterpolationMode mode) {
if (mode != InterpolationMode::kLinear) {
@ -467,6 +581,7 @@ Status Resize(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *out
}
return Status::OK();
}
#endif
Status ResizePreserve(const TensorRow &inputs, int32_t height, int32_t width, int32_t img_orientation,
TensorRow *outputs) {

View File

@ -24,6 +24,7 @@
#include "lite_cv/lite_mat.h"
#include "minddata/dataset/util/log_adapter.h"
#include "minddata/dataset/util/status.h"
#include "securec/include/securec.h"
namespace mindspore {
namespace dataset {

View File

@ -303,6 +303,7 @@ if(MSLITE_MINDDATA_IMPLEMENT STREQUAL "full")
${MINDDATA_DIR}/kernels/image/rescale_op.cc
${MINDDATA_DIR}/kernels/ir/vision/rescale_ir.cc
${MINDDATA_DIR}/core/cv_tensor.cc
${MINDDATA_DIR}/kernels/image/resize_cubic_op.cc
)
endif()