Dvpp refactor and 6 Dvpp operators

This commit is contained in:
Zhenglong Li 2021-02-05 16:46:24 +08:00
parent 5f72693b4b
commit e2d3495925
49 changed files with 3749 additions and 644 deletions

View File

@ -16,6 +16,7 @@
#include "minddata/dataset/include/execute.h"
#include "minddata/dataset/core/de_tensor.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/core/tensor_row.h"
#include "minddata/dataset/include/tensor.h"
#include "minddata/dataset/include/type_id.h"
@ -25,53 +26,194 @@
#else
#include "mindspore/lite/src/common/log_adapter.h"
#endif
#ifdef ENABLE_ACL
#include "acl/acl.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h"
#endif
namespace mindspore {
namespace dataset {
#ifdef ENABLE_ACL
class AscendResource {
public:
AscendResource();
~AscendResource() = default;
Execute::Execute(std::shared_ptr<TensorOperation> op) { ops_.emplace_back(std::move(op)); }
Status InitChipResource();
Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> ops) : ops_(std::move(ops)) {}
Status FinalizeChipResource();
Status Sink(const mindspore::MSTensor &host_input, std::shared_ptr<DeviceTensor> *device_input);
Status Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *host_output);
Status DeviceDataRelease();
std::shared_ptr<MDAclProcess> processor_;
std::shared_ptr<ResourceManager> ascend_resource_;
};
AscendResource::AscendResource() { InitChipResource(); }
Status AscendResource::InitChipResource() {
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
ascend_resource_ = ResourceManager::GetInstance();
APP_ERROR ret = ascend_resource_->InitResource(resource);
if (ret != APP_ERR_OK) {
ascend_resource_->Release();
std::string err_msg = "Error in Init D-chip:" + std::to_string(ret);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
int device_id = *(resource.deviceIds.begin());
aclrtContext context = ascend_resource_->GetContext(device_id);
processor_ = std::make_shared<MDAclProcess>(context, false);
ret = processor_->InitResource();
if (ret != APP_ERR_OK) {
ascend_resource_->Release();
std::string err_msg = "Error in Init resource:" + std::to_string(ret);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
MS_LOG(INFO) << "Ascend resource all initialized!";
return Status::OK();
}
Status AscendResource::FinalizeChipResource() {
processor_->Release();
return Status::OK();
}
Status AscendResource::Sink(const mindspore::MSTensor &host_input, std::shared_ptr<DeviceTensor> *device_input) {
std::shared_ptr<mindspore::dataset::Tensor> de_input;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(host_input.Shape()),
MSTypeToDEType(static_cast<TypeId>(host_input.DataType())),
(const uchar *)(host_input.Data().get()), &de_input);
RETURN_IF_NOT_OK(rc);
APP_ERROR ret = processor_->H2D_Sink(de_input, *device_input);
if (ret != APP_ERR_OK) {
ascend_resource_->Release();
std::string err_msg = "Error in data sink process:" + std::to_string(ret);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
MS_LOG(INFO) << "Process data sink successfully";
return Status::OK();
}
Status AscendResource::Pop(std::shared_ptr<DeviceTensor> device_output, std::shared_ptr<Tensor> *host_output) {
APP_ERROR ret = processor_->D2H_Pop(device_output, *host_output);
if (ret != APP_ERR_OK) {
ascend_resource_->Release();
std::string err_msg = "Error in data pop processing:" + std::to_string(ret);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
return Status::OK();
}
Status AscendResource::DeviceDataRelease() {
APP_ERROR ret = processor_->device_memory_release();
if (ret != APP_ERR_OK) {
ascend_resource_->Release();
std::string err_msg = "Error in device data release:" + std::to_string(ret);
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
return Status::OK();
}
#endif
Execute::Execute(std::shared_ptr<TensorOperation> op, std::string deviceType) {
ops_.emplace_back(std::move(op));
device_type_ = deviceType;
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
D_resource_ = std::make_shared<AscendResource>();
}
#endif
}
Execute::Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string deviceType)
: ops_(std::move(ops)), device_type_(deviceType) {
MS_LOG(INFO) << "Running Device: " << device_type_;
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
D_resource_ = std::make_shared<AscendResource>();
}
#endif
}
Execute::~Execute() {
#ifdef ENABLE_ACL
if (device_type_ == "Ascend310") {
D_resource_->FinalizeChipResource();
}
#endif
}
Status Execute::operator()(const mindspore::MSTensor &input, mindspore::MSTensor *output) {
// Validate input tensor
CHECK_FAIL_RETURN_UNEXPECTED(input.DataSize() > 0, "Input Tensor has no data");
CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided");
CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'");
// Validate and build runtime ops
std::vector<std::shared_ptr<TensorOp>> transforms;
std::vector<std::shared_ptr<TensorOp>> transforms; // record the transformations
for (int32_t i = 0; i < ops_.size(); i++) {
CHECK_FAIL_RETURN_UNEXPECTED(ops_[i] != nullptr, "Input TensorOperation[" + std::to_string(i) + "] is null");
RETURN_IF_NOT_OK(ops_[i]->ValidateParams());
transforms.emplace_back(ops_[i]->Build());
}
// Convert mindspore::Tensor to dataset::Tensor
std::shared_ptr<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()),
MSTypeToDEType(static_cast<TypeId>(input.DataType())),
(const uchar *)(input.Data().get()), input.DataSize(), &de_tensor);
if (rc.IsError()) {
MS_LOG(ERROR) << rc;
RETURN_IF_NOT_OK(rc);
}
// Apply transforms on tensor
for (auto &t : transforms) {
std::shared_ptr<dataset::Tensor> de_output;
Status rc_ = t->Compute(de_tensor, &de_output);
if (rc_.IsError()) {
MS_LOG(ERROR) << rc_;
RETURN_IF_NOT_OK(rc_);
if (device_type_ == "CPU") {
// Convert mindspore::Tensor to dataset::Tensor
std::shared_ptr<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(input.Shape()),
MSTypeToDEType(static_cast<TypeId>(input.DataType())),
(const uchar *)(input.Data().get()), input.DataSize(), &de_tensor);
if (rc.IsError()) {
MS_LOG(ERROR) << rc;
return rc;
}
// For next transform
de_tensor = std::move(de_output);
}
// Apply transforms on tensor
for (auto &t : transforms) {
std::shared_ptr<dataset::Tensor> de_output;
Status rc_ = t->Compute(de_tensor, &de_output);
if (rc_.IsError()) {
MS_LOG(ERROR) << rc_;
return rc_;
}
// Convert dataset::Tensor to mindspore::Tensor
CHECK_FAIL_RETURN_UNEXPECTED(de_tensor->HasData(), "Apply transform failed, output tensor has no data");
*output = mindspore::MSTensor(std::make_shared<DETensor>(de_tensor));
// For next transform
de_tensor = std::move(de_output);
}
// Convert dataset::Tensor to mindspore::Tensor
CHECK_FAIL_RETURN_UNEXPECTED(de_tensor->HasData(), "Apply transform failed, output tensor has no data");
*output = mindspore::MSTensor(std::make_shared<DETensor>(de_tensor));
} else { // Ascend310 case, where we must set Ascend resource on each operators
#ifdef ENABLE_ACL
std::shared_ptr<mindspore::dataset::DeviceTensor> device_input;
RETURN_IF_NOT_OK(D_resource_->Sink(input, &device_input));
for (auto &t : transforms) {
std::shared_ptr<DeviceTensor> device_output;
RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_));
RETURN_IF_NOT_OK(t->Compute(device_input, &device_output));
// For next transform
device_input = std::move(device_output);
}
CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data");
*output = mindspore::MSTensor(std::make_shared<DETensor>(device_input, true));
#endif
}
return Status::OK();
}
@ -82,6 +224,7 @@ Status Execute::operator()(const std::vector<MSTensor> &input_tensor_list, std::
CHECK_FAIL_RETURN_UNEXPECTED(tensor.DataSize() > 0, "Input Tensor has no data");
}
CHECK_FAIL_RETURN_UNEXPECTED(!ops_.empty(), "Input TensorOperation should be provided");
CHECK_FAIL_RETURN_UNEXPECTED(validate_device_(), "Device Type should be 'Ascend310' or 'CPU'");
// Validate and build runtime ops
std::vector<std::shared_ptr<TensorOp>> transforms;
@ -90,40 +233,81 @@ Status Execute::operator()(const std::vector<MSTensor> &input_tensor_list, std::
RETURN_IF_NOT_OK(ops_[i]->ValidateParams());
transforms.emplace_back(ops_[i]->Build());
}
TensorRow de_tensor_list;
for (auto &tensor : input_tensor_list) {
std::shared_ptr<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(dataset::TensorShape(tensor.Shape()),
MSTypeToDEType(static_cast<TypeId>(tensor.DataType())),
(const uchar *)(tensor.Data().get()), tensor.DataSize(), &de_tensor);
if (rc.IsError()) {
MS_LOG(ERROR) << rc;
RETURN_IF_NOT_OK(rc);
if (device_type_ == "CPU") { // Case CPU
TensorRow de_tensor_list;
for (auto &tensor : input_tensor_list) {
std::shared_ptr<dataset::Tensor> de_tensor;
Status rc = dataset::Tensor::CreateFromMemory(
dataset::TensorShape(tensor.Shape()), MSTypeToDEType(static_cast<TypeId>(tensor.DataType())),
(const uchar *)(tensor.Data().get()), tensor.DataSize(), &de_tensor);
if (rc.IsError()) {
MS_LOG(ERROR) << rc;
RETURN_IF_NOT_OK(rc);
}
de_tensor_list.emplace_back(std::move(de_tensor));
}
de_tensor_list.emplace_back(std::move(de_tensor));
}
// Apply transforms on tensor
for (auto &t : transforms) {
TensorRow de_output_list;
Status rc = t->Compute(de_tensor_list, &de_output_list);
if (rc.IsError()) {
MS_LOG(ERROR) << rc;
RETURN_IF_NOT_OK(rc);
// Apply transforms on tensor
for (auto &t : transforms) {
TensorRow de_output_list;
RETURN_IF_NOT_OK(t->Compute(de_tensor_list, &de_output_list));
// For next transform
de_tensor_list = std::move(de_output_list);
}
// For next transform
de_tensor_list = std::move(de_output_list);
}
for (auto &tensor : de_tensor_list) {
CHECK_FAIL_RETURN_UNEXPECTED(tensor->HasData(), "Apply transform failed, output tensor has no data");
auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(tensor));
output_tensor_list->emplace_back(ms_tensor);
for (auto &tensor : de_tensor_list) {
CHECK_FAIL_RETURN_UNEXPECTED(tensor->HasData(), "Apply transform failed, output tensor has no data");
auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(tensor));
output_tensor_list->emplace_back(ms_tensor);
}
CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid");
} else { // Case Ascend310
#ifdef ENABLE_ACL
for (auto &input_tensor : input_tensor_list) {
std::shared_ptr<dataset::DeviceTensor> device_input;
RETURN_IF_NOT_OK(D_resource_->Sink(input_tensor, &device_input));
for (auto &t : transforms) {
std::shared_ptr<DeviceTensor> device_output;
RETURN_IF_NOT_OK(t->SetAscendResource(D_resource_->processor_));
RETURN_IF_NOT_OK(t->Compute(device_input, &device_output));
// For next transform
device_input = std::move(device_output);
}
CHECK_FAIL_RETURN_UNEXPECTED(device_input->HasDeviceData(), "Apply transform failed, output tensor has no data");
// Due to the limitation of Ascend310 memory, we have to pop every data onto host memory
// So the speed of this method is slower than solo mode
std::shared_ptr<mindspore::dataset::Tensor> host_output;
RETURN_IF_NOT_OK(D_resource_->Pop(device_input, &host_output));
auto ms_tensor = mindspore::MSTensor(std::make_shared<DETensor>(host_output));
output_tensor_list->emplace_back(ms_tensor);
RETURN_IF_NOT_OK(D_resource_->DeviceDataRelease());
}
CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor vector is empty");
#endif
}
CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid");
return Status::OK();
}
Status Execute::validate_device_() {
if (device_type_ != "CPU" && device_type_ != "Ascend310") {
std::string err_msg = device_type_ + " is not supported. (Option: CPU or Ascend310)";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
return Status::OK();
}
#ifdef ENABLE_ACL
Status Execute::DeviceMemoryRelease() {
Status rc = D_resource_->DeviceDataRelease();
if (rc.IsError()) {
D_resource_->ascend_resource_->Release();
std::string err_msg = "Error in device data release";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_UNEXPECTED(err_msg);
}
return Status::OK();
}
#endif
} // namespace dataset
} // namespace mindspore

View File

@ -37,7 +37,13 @@
#endif
#include "minddata/dataset/kernels/image/decode_op.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/include/vision_ascend.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h"
#endif
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/equalize_op.h"
@ -143,6 +149,20 @@ std::shared_ptr<DecodeOperation> Decode(bool rgb) {
}
#ifdef ENABLE_ACL
// Function to create DvppResizeOperation.
std::shared_ptr<DvppCropJpegOperation> DvppCropJpeg(std::vector<uint32_t> crop) {
auto op = std::make_shared<DvppCropJpegOperation>(crop);
// Input validation
return op->ValidateParams() ? op : nullptr;
}
// Function to create DvppDecodeResizeOperation.
std::shared_ptr<DvppDecodeResizeOperation> DvppDecodeResizeJpeg(std::vector<uint32_t> resize) {
auto op = std::make_shared<DvppDecodeResizeOperation>(resize);
// Input validation
return op->ValidateParams() ? op : nullptr;
}
// Function to create DvppDecodeResizeCropOperation.
std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop,
std::vector<uint32_t> resize) {
@ -150,6 +170,27 @@ std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vec
// Input validation
return op->ValidateParams() ? op : nullptr;
}
// Function to create DvppDecodeJpegOperation.
std::shared_ptr<DvppDecodeJpegOperation> DvppDecodeJpeg() {
auto op = std::make_shared<DvppDecodeJpegOperation>();
// Input validation
return op->ValidateParams() ? op : nullptr;
}
// Function to create DvppDecodePngOperation.
std::shared_ptr<DvppDecodePngOperation> DvppDecodePng() {
auto op = std::make_shared<DvppDecodePngOperation>();
// Input validation
return op->ValidateParams() ? op : nullptr;
}
// Function to create DvppResizeOperation.
std::shared_ptr<DvppResizeJpegOperation> DvppResizeJpeg(std::vector<uint32_t> resize) {
auto op = std::make_shared<DvppResizeJpegOperation>(resize);
// Input validation
return op->ValidateParams() ? op : nullptr;
}
#endif
// Function to create EqualizeOperation.
@ -445,6 +486,232 @@ std::shared_ptr<UniformAugOperation> UniformAugment(std::vector<std::shared_ptr<
}
#endif
#ifdef ENABLE_ACL
// DvppCropOperation
DvppCropJpegOperation::DvppCropJpegOperation(const std::vector<uint32_t> &crop) : crop_(crop) {}
Status DvppCropJpegOperation::ValidateParams() {
// size
if (crop_.empty() || crop_.size() > 2) {
std::string err_msg =
"DvppCropJpeg: Crop resolution must be a vector of one or two elements, got: " + std::to_string(crop_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) {
std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got crop Parameters: ";
if (crop_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
return Status::OK();
}
std::shared_ptr<TensorOp> DvppCropJpegOperation::Build() {
// If size is a single value, the smaller edge of the image will be
// resized to this value with the same image aspect ratio.
uint32_t cropHeight, cropWidth;
// User specified the width value.
if (crop_.size() == 1) {
cropHeight = crop_[0];
cropWidth = crop_[0];
} else {
cropHeight = crop_[0];
cropWidth = crop_[1];
}
std::shared_ptr<DvppCropJpegOp> tensor_op = std::make_shared<DvppCropJpegOp>(cropHeight, cropWidth);
return tensor_op;
}
// DvppDecodeResizeOperation
DvppDecodeResizeOperation::DvppDecodeResizeOperation(const std::vector<uint32_t> &resize) : resize_(resize) {}
Status DvppDecodeResizeOperation::ValidateParams() {
// size
if (resize_.empty() || resize_.size() > 2) {
std::string err_msg = "DvppDecodeResizeJpeg: resize resolution must be a vector of one or two elements, got: " +
std::to_string(resize_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
std::string err_msg =
"Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: ";
if (resize_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
return Status::OK();
}
std::shared_ptr<TensorOp> DvppDecodeResizeOperation::Build() {
// If size is a single value, the smaller edge of the image will be
// resized to this value with the same image aspect ratio.
uint32_t resizeHeight, resizeWidth;
// User specified the width value.
if (resize_.size() == 1) {
resizeHeight = resize_[0];
resizeWidth = 0;
} else {
resizeHeight = resize_[0];
resizeWidth = resize_[1];
}
std::shared_ptr<DvppDecodeResizeJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeJpegOp>(resizeHeight, resizeWidth);
return tensor_op;
}
// DvppDecodeResizeCropOperation
DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop,
const std::vector<uint32_t> &resize)
: crop_(crop), resize_(resize) {}
Status DvppDecodeResizeCropOperation::ValidateParams() {
// size
if (crop_.empty() || crop_.size() > 2) {
std::string err_msg = "DvppDecodeResizeCropJpeg: crop resolution must be a vector of one or two elements, got: " +
std::to_string(crop_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (resize_.empty() || resize_.size() > 2) {
std::string err_msg = "DvppDecodeResizeCropJpeg: resize resolution must be a vector of one or two elements, got: " +
std::to_string(resize_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) {
std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got Crop Parameters: ";
if (crop_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
std::string err_msg =
"Dvpp module supports resize image with resolution in range [32, 2048], got Crop Parameters: ";
if (resize_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (crop_.size() < resize_.size()) {
if (crop_[0] > MIN(resize_[0], resize_[1])) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
if (crop_.size() > resize_.size()) {
if (MAX(crop_[0], crop_[1]) > resize_[0]) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
if (crop_.size() == resize_.size()) {
for (int32_t i = 0; i < crop_.size(); ++i) {
if (crop_[i] > resize_[i]) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
}
return Status::OK();
}
std::shared_ptr<TensorOp> DvppDecodeResizeCropOperation::Build() {
// If size is a single value, the smaller edge of the image will be
// resized to this value with the same image aspect ratio.
uint32_t cropHeight, cropWidth, resizeHeight, resizeWidth;
if (crop_.size() == 1) {
cropHeight = crop_[0];
cropWidth = crop_[0];
} else {
cropHeight = crop_[0];
cropWidth = crop_[1];
}
// User specified the width value.
if (resize_.size() == 1) {
resizeHeight = resize_[0];
resizeWidth = 0;
} else {
resizeHeight = resize_[0];
resizeWidth = resize_[1];
}
std::shared_ptr<DvppDecodeResizeCropJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeCropJpegOp>(cropHeight, cropWidth, resizeHeight, resizeWidth);
return tensor_op;
}
// DvppDecodeJPEG
Status DvppDecodeJpegOperation::ValidateParams() { return Status::OK(); }
std::shared_ptr<TensorOp> DvppDecodeJpegOperation::Build() { return std::make_shared<DvppDecodeJpegOp>(); }
// DvppDecodePNG
Status DvppDecodePngOperation::ValidateParams() { return Status::OK(); }
std::shared_ptr<TensorOp> DvppDecodePngOperation::Build() { return std::make_shared<DvppDecodePngOp>(); }
// DvppResizeOperation
DvppResizeJpegOperation::DvppResizeJpegOperation(const std::vector<uint32_t> &resize) : resize_(resize) {}
Status DvppResizeJpegOperation::ValidateParams() {
// size
if (resize_.empty() || resize_.size() > 2) {
std::string err_msg = "DvppResizeJpeg: resize resolution must be a vector of one or two elements, got: " +
std::to_string(resize_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
std::string err_msg =
"Dvpp module supports resize image with resolution in range [32, 2048], got resize Parameters: ";
if (resize_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
return Status::OK();
}
std::shared_ptr<TensorOp> DvppResizeJpegOperation::Build() {
// If size is a single value, the smaller edge of the image will be
// resized to this value with the same image aspect ratio.
uint32_t resizeHeight, resizeWidth;
// User specified the width value.
if (resize_.size() == 1) {
resizeHeight = resize_[0];
resizeWidth = 0;
} else {
resizeHeight = resize_[0];
resizeWidth = resize_[1];
}
std::shared_ptr<DvppResizeJpegOp> tensor_op = std::make_shared<DvppResizeJpegOp>(resizeHeight, resizeWidth);
return tensor_op;
}
#endif
} // namespace vision
} // namespace dataset
} // namespace mindspore

View File

@ -1,17 +1,18 @@
file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc")
set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD)
set(DATASET_CORE_SRC_FILES
client.cc
config_manager.cc
cv_tensor.cc
data_type.cc
de_tensor.cc
global_context.cc
tensor.cc
tensor_helpers.cc
tensor_row.cc
tensor_shape.cc
)
client.cc
config_manager.cc
cv_tensor.cc
data_type.cc
device_tensor.cc
de_tensor.cc
global_context.cc
tensor.cc
tensor_helpers.cc
tensor_row.cc
tensor_shape.cc
)
ms_protobuf_generate(EXAMPLE_SRCS EXAMPLE_HDRS example.proto)
ms_protobuf_generate(FEATURE_SRCS FEATURE_HDRS feature.proto)

View File

@ -15,6 +15,7 @@
*/
#include "minddata/dataset/core/de_tensor.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/core/constants.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/include/type_id.h"
@ -35,7 +36,27 @@ DETensor::DETensor(std::shared_ptr<dataset::Tensor> tensor_impl)
: tensor_impl_(tensor_impl),
name_("MindDataTensor"),
type_(static_cast<mindspore::DataType>(DETypeToMSType(tensor_impl_->type()))),
shape_(tensor_impl_->shape().AsVector()) {}
shape_(tensor_impl_->shape().AsVector()),
is_device_(false) {}
#ifndef ENABLE_ANDROID
DETensor::DETensor(std::shared_ptr<dataset::DeviceTensor> device_tensor_impl, bool is_device)
: device_tensor_impl_(device_tensor_impl), name_("MindDataDeviceTensor"), is_device_(is_device) {
// The sequence of shape_ is (width, widthStride, height, heightStride) in Dvpp module
// We need to add [1]widthStride and [3]heightStride, which are actual YUV image shape, into shape_ attribute
uint8_t flag = 0;
for (auto &i : device_tensor_impl->GetYuvStrideShape()) {
if (flag % 2 == 1) {
int64_t j = static_cast<int64_t>(i);
shape_.emplace_back(j);
}
++flag;
}
std::reverse(shape_.begin(), shape_.end());
MS_LOG(INFO) << "This is a YUV420 format image, one pixel takes 1.5 bytes. Therefore, the shape of"
<< " image is in (H, W) format. You can search for more information about YUV420 format";
}
#endif
const std::string &DETensor::Name() const { return name_; }
@ -45,6 +66,12 @@ enum mindspore::DataType DETensor::DataType() const {
}
size_t DETensor::DataSize() const {
#ifndef ENABLE_ANDROID
if (is_device_) {
ASSERT_NULL(device_tensor_impl_);
return device_tensor_impl_->DeviceDataSize();
}
#endif
ASSERT_NULL(tensor_impl_);
return tensor_impl_->SizeInBytes();
}
@ -52,6 +79,11 @@ size_t DETensor::DataSize() const {
const std::vector<int64_t> &DETensor::Shape() const { return shape_; }
std::shared_ptr<const void> DETensor::Data() const {
#ifndef ENABLE_ANDROID
if (is_device_) {
return std::shared_ptr<const void>(device_tensor_impl_->GetDeviceBuffer(), [](const void *) {});
}
#endif
return std::shared_ptr<const void>(tensor_impl_->GetBuffer(), [](const void *) {});
}
@ -60,7 +92,7 @@ void *DETensor::MutableData() {
return tensor_impl_->GetMutableBuffer();
}
bool DETensor::IsDevice() const { return false; }
bool DETensor::IsDevice() const { return is_device_; }
std::shared_ptr<mindspore::MSTensor::Impl> DETensor::Clone() const { return std::make_shared<DETensor>(tensor_impl_); }
} // namespace dataset

View File

@ -31,7 +31,9 @@ class DETensor : public mindspore::MSTensor::Impl {
DETensor() = default;
~DETensor() override = default;
explicit DETensor(std::shared_ptr<dataset::Tensor> tensor_impl);
#ifndef ENABLE_ANDROID
explicit DETensor(std::shared_ptr<dataset::DeviceTensor> device_tensor_impl, bool is_device);
#endif
const std::string &Name() const override;
enum mindspore::DataType DataType() const override;
@ -50,6 +52,10 @@ class DETensor : public mindspore::MSTensor::Impl {
private:
std::shared_ptr<dataset::Tensor> tensor_impl_;
#ifndef ENABLE_ANDROID
std::shared_ptr<dataset::DeviceTensor> device_tensor_impl_;
#endif
bool is_device_;
std::string name_;
enum mindspore::DataType type_;
std::vector<int64_t> shape_;

View File

@ -0,0 +1,77 @@
/**
* 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/core/global_context.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/core/device_tensor.h"
namespace mindspore {
namespace dataset {
Status DeviceTensor::SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height,
const uint32_t &heightStride) {
YUV_shape_ = {width, widthStride, height, heightStride};
return Status::OK();
}
std::vector<uint32_t> DeviceTensor::GetYuvStrideShape() { return YUV_shape_; }
#ifdef ENABLE_ACL
Status DeviceTensor::SetAttributes(const std::shared_ptr<DvppDataInfo> &data_ptr) {
device_data_ = data_ptr->data;
CHECK_FAIL_RETURN_UNEXPECTED(device_data_ != nullptr, "Fail to get the device data.");
SetSize_(data_ptr->dataSize);
SetYuvStrideShape_(data_ptr->width, data_ptr->widthStride, data_ptr->height, data_ptr->heightStride);
return Status::OK();
}
#endif
DeviceTensor::DeviceTensor(const TensorShape &shape, const DataType &type) : Tensor(shape, type) {
// grab the mem pool from global context and create the allocator for char data area
std::shared_ptr<MemoryPool> global_pool = GlobalContext::Instance()->mem_pool();
data_allocator_ = std::make_unique<Allocator<unsigned char>>(global_pool);
}
Status DeviceTensor::CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr<DeviceTensor> *out) {
CHECK_FAIL_RETURN_UNEXPECTED(shape.known(), "Invalid shape.");
CHECK_FAIL_RETURN_UNEXPECTED(type != DataType::DE_UNKNOWN, "Invalid data type.");
const DeviceTensorAlloc *alloc = GlobalContext::Instance()->device_tensor_allocator();
*out = std::allocate_shared<DeviceTensor>(*alloc, shape, type);
// if it's a string tensor and it has no elements, Just initialize the shape and type.
if (!type.IsNumeric() && shape.NumOfElements() == 0) {
return Status::OK();
}
CHECK_FAIL_RETURN_UNEXPECTED(type.IsNumeric(), "Number of elements is not 0. The type should be numeric.");
int64_t byte_size = (*out)->SizeInBytes();
// Don't allocate if we have a tensor with no elements.
if (byte_size != 0) {
RETURN_IF_NOT_OK((*out)->AllocateBuffer(byte_size));
}
return Status::OK();
}
uint8_t *DeviceTensor::GetDeviceBuffer() { return device_data_; }
uint32_t DeviceTensor::DeviceDataSize() { return size_; }
Status DeviceTensor::SetSize_(const uint32_t &new_size) {
size_ = new_size;
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,65 @@
/**
* 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_DEVICE_TENSOR_H
#define MINDSPORE_DEVICE_TENSOR_H
#include <memory>
#include <utility>
#include <vector>
#include "include/api/status.h"
#include "minddata/dataset/core/tensor.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/kernels/image/dvpp/utils/DvppCommon.h"
#endif
#include "minddata/dataset/core/constants.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
class Tensor;
class DeviceTensor : public Tensor {
public:
DeviceTensor(const TensorShape &shape, const DataType &type);
~DeviceTensor() {}
#ifdef ENABLE_ACL
Status SetAttributes(const std::shared_ptr<DvppDataInfo> &data);
#endif
static Status CreateEmpty(const TensorShape &shape, const DataType &type, std::shared_ptr<DeviceTensor> *out);
uint8_t *GetDeviceBuffer();
std::vector<uint32_t> GetYuvStrideShape();
uint32_t DeviceDataSize();
bool HasDeviceData() { return device_data_ != nullptr; }
private:
Status SetSize_(const uint32_t &new_size);
Status SetYuvStrideShape_(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height,
const uint32_t &heightStride);
std::vector<uint32_t> YUV_shape_;
uint8_t *device_data_;
uint32_t size_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_DEVICE_TENSOR_H

View File

@ -1,5 +1,5 @@
/**
* Copyright 2019 Huawei Technologies Co., Ltd
* Copyright 2019-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.
@ -22,6 +22,7 @@
#ifndef ENABLE_ANDROID
#include "minddata/dataset/core/cv_tensor.h"
#endif
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/util/allocator.h"
#include "minddata/dataset/util/circular_pool.h"
@ -61,6 +62,7 @@ Status GlobalContext::Init() {
#ifndef ENABLE_ANDROID
cv_tensor_allocator_ = std::make_unique<Allocator<CVTensor>>(mem_pool_);
#endif
device_tensor_allocator_ = std::make_unique<Allocator<DeviceTensor>>(mem_pool_);
int_allocator_ = std::make_unique<IntAlloc>(mem_pool_);
return Status::OK();
}

View File

@ -1,5 +1,5 @@
/**
* Copyright 2019 Huawei Technologies Co., Ltd
* Copyright 2019-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.
@ -19,10 +19,10 @@
#include <memory>
#include <mutex>
#include "include/api/status.h"
#include "minddata/dataset/core/config_manager.h"
#include "minddata/dataset/core/constants.h"
#include "minddata/dataset/util/allocator.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
@ -30,9 +30,11 @@ namespace dataset {
class MemoryPool;
class Tensor;
class CVTensor;
class DeviceTensor;
using TensorAlloc = Allocator<Tensor>; // An allocator for Tensors
using CVTensorAlloc = Allocator<CVTensor>; // An allocator CVTensors
using TensorAlloc = Allocator<Tensor>; // An allocator for Tensors
using CVTensorAlloc = Allocator<CVTensor>; // An allocator CVTensors
using DeviceTensorAlloc = Allocator<DeviceTensor>; // An allocator for Device_Tensors
using IntAlloc = Allocator<dsize_t>;
class GlobalContext {
@ -82,6 +84,10 @@ class GlobalContext {
// @return the CVTensor allocator as raw pointer
const CVTensorAlloc *cv_tensor_allocator() const { return cv_tensor_allocator_.get(); }
// Getter method
// @return the DeviceTensor allocator as raw pointer
const DeviceTensorAlloc *device_tensor_allocator() const { return device_tensor_allocator_.get(); }
// Getter method
// @return the integer allocator as raw pointer
const IntAlloc *int_allocator() const { return int_allocator_.get(); }
@ -95,12 +101,13 @@ class GlobalContext {
Status Init();
static std::once_flag init_instance_flag_;
static std::unique_ptr<GlobalContext> global_context_; // The instance of the singleton (global)
std::shared_ptr<MemoryPool> mem_pool_; // A global memory pool
std::shared_ptr<ConfigManager> config_manager_; // The configs
std::unique_ptr<TensorAlloc> tensor_allocator_; // An allocator for Tensors
std::unique_ptr<CVTensorAlloc> cv_tensor_allocator_; // An allocator for CV Tensors
std::unique_ptr<IntAlloc> int_allocator_; // An allocator for ints
static std::unique_ptr<GlobalContext> global_context_; // The instance of the singleton (global)
std::shared_ptr<MemoryPool> mem_pool_; // A global memory pool
std::shared_ptr<ConfigManager> config_manager_; // The configs
std::unique_ptr<TensorAlloc> tensor_allocator_; // An allocator for Tensors
std::unique_ptr<CVTensorAlloc> cv_tensor_allocator_; // An allocator for CV Tensors
std::unique_ptr<DeviceTensorAlloc> device_tensor_allocator_; // An allocator for Device Tensors
std::unique_ptr<IntAlloc> int_allocator_; // An allocator for ints
};
} // namespace dataset
} // namespace mindspore

View File

@ -423,6 +423,17 @@ class Tensor {
static Status GetBufferInfo(Tensor *t, py::buffer_info *out);
#endif
#ifdef ENABLE_ACL
Status SetYuvShape(const uint32_t &width, const uint32_t &widthStride, const uint32_t &height,
const uint32_t &heightStride) {
std::vector<uint32_t> tmp{width, widthStride, height, heightStride};
yuv_shape_ = tmp;
return Status::OK();
}
std::vector<uint32_t> GetYuvShape() { return yuv_shape_; }
#endif
/// TensorIterator is a linear iterator that can be used to iterate over the elements of the Tensor
/// The order elements is as the memory layout (i.e., row-major) [[1,2,3],[4,5,6] --> 1,2,3,4,5,6
/// \tparam T type of values in the Tensor Iterator
@ -686,6 +697,11 @@ class Tensor {
/// pointer to the end of the physical data
unsigned char *data_end_ = nullptr;
#ifdef ENABLE_ACL
/// shape for interpretation of YUV image
std::vector<uint32_t> yuv_shape_;
#endif
private:
friend class DETensor;

View File

@ -17,25 +17,28 @@
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_EXECUTE_H_
#include <string>
#include <vector>
#include <memory>
#include "include/api/context.h"
#include "include/api/types.h"
#include "minddata/dataset/include/constants.h"
#include "minddata/dataset/include/transforms.h"
namespace mindspore {
namespace dataset {
class AscendResource; // Class to manage the resource of Ascend310
// class to run tensor operations in eager mode
class Execute {
public:
/// \brief Constructor
explicit Execute(std::shared_ptr<TensorOperation> op);
explicit Execute(std::shared_ptr<TensorOperation> op, std::string deviceType = "CPU");
explicit Execute(std::vector<std::shared_ptr<TensorOperation>> ops);
explicit Execute(std::vector<std::shared_ptr<TensorOperation>> ops, std::string deviceType = "CPU");
/// \brief Destructor
~Execute() = default;
~Execute();
/// \brief callable function to execute the TensorOperation in eager mode
/// \param[in] input Tensor to be transformed
@ -48,9 +51,19 @@ class Execute {
/// \param[out] out Result tensor after transform
/// \return - Status
Status operator()(const std::vector<mindspore::MSTensor> &input_tensor_list, std::vector<mindspore::MSTensor> *out);
#ifdef ENABLE_ACL
Status DeviceMemoryRelease();
#endif
private:
Status validate_device_();
std::vector<std::shared_ptr<TensorOperation>> ops_;
std::string device_type_;
#ifdef ENABLE_ACL
std::shared_ptr<AscendResource> D_resource_;
#endif
};
} // namespace dataset

View File

@ -39,7 +39,6 @@ class AutoContrastOperation;
class BoundingBoxAugmentOperation;
class CutMixBatchOperation;
class CutOutOperation;
class DvppDecodeResizeCropOperation;
class EqualizeOperation;
class HwcToChwOperation;
class InvertOperation;
@ -106,22 +105,6 @@ std::shared_ptr<CutMixBatchOperation> CutMixBatch(ImageBatchFormat image_batch_f
/// \return Shared pointer to the current TensorOp
std::shared_ptr<CutOutOperation> CutOut(int32_t length, int32_t num_patches = 1);
/// \brief Function to create a DvppDecodeResizeCropJpeg TensorOperation.
/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [16*16, 4096*4096].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \param[in] crop vector representing the output size of the final crop image.
/// \param[in] size A vector representing the output size of the intermediate resized image.
/// If size is a single value, smaller edge of the image will be resized to this value with
/// the same image aspect ratio. If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop = {224, 224},
std::vector<uint32_t> resize = {256, 256});
/// \brief Function to create a Equalize TensorOperation.
/// \notes Apply histogram equalization on input image.
/// \return Shared pointer to the current TensorOperation.

View File

@ -0,0 +1,219 @@
/**
* 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_INCLUDE_VISION_ASCEND_H_
#define MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_
#include <map>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "include/api/status.h"
#include "minddata/dataset/include/constants.h"
#include "minddata/dataset/include/transforms.h"
namespace mindspore {
namespace dataset {
// Transform operations for performing computer vision.
namespace vision {
// Char arrays storing name of corresponding classes (in alphabetical order)
constexpr char kDvppCropJpegOperation[] = "DvppCropJpeg";
constexpr char kDvppDecodeResizeOperation[] = "DvppDecodeResize";
constexpr char kDvppDecodeResizeCropOperation[] = "DvppDecodeResizeCrop";
constexpr char kDvppDecodeJpegOperation[] = "DvppDecodeJpeg";
constexpr char kDvppDecodePngOperation[] = "DvppDecodePng";
constexpr char kDvppResizeJpegOperation[] = "DvppResizeJpeg";
class DvppCropJpegOperation;
class DvppDecodeResizeOperation;
class DvppDecodeResizeCropOperation;
class DvppDecodeJpegOperation;
class DvppDecodePngOperation;
class DvppResizeJpegOperation;
/// \brief Function to create a DvppCropJpeg TensorOperation.
/// \notes Tensor operation to crop JPEG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \param[in] crop vector representing the output size of the final crop image.
/// \param[in] size A vector representing the output size of the intermediate resized image.
/// If size is a single value, the shape will be a square. If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppCropJpegOperation> DvppCropJpeg(std::vector<uint32_t> crop = {256, 256});
/// \brief Function to create a DvppDecodeResizeJpeg TensorOperation.
/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \param[in] crop vector representing the output size of the final crop image.
/// \param[in] size A vector representing the output size of the intermediate resized image.
/// If size is a single value, smaller edge of the image will be resized to this value with
/// the same image aspect ratio. If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppDecodeResizeOperation> DvppDecodeResizeJpeg(std::vector<uint32_t> resize = {256, 256});
/// \brief Function to create a DvppDecodeResizeCropJpeg TensorOperation.
/// \notes Tensor operation to decode and resize JPEG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \param[in] crop vector representing the output size of the final crop image.
/// \param[in] Resize vector representing the output size of the intermediate resized image.
/// If size is a single value, smaller edge of the image will be resized to the value with
/// the same image aspect ratio. If size has 2 values, it should be (height, width).
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppDecodeResizeCropOperation> DvppDecodeResizeCropJpeg(std::vector<uint32_t> crop = {224, 224},
std::vector<uint32_t> resize = {256, 256});
/// \brief Function to create a DvppDecodeJpeg TensorOperation.
/// \notes Tensor operation to decode JPEG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppDecodeJpegOperation> DvppDecodeJpeg();
/// \brief Function to create a DvppDecodePng TensorOperation.
/// \notes Tensor operation to decode PNG image using the simulation algorithm of Ascend series
/// chip DVPP module. It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppDecodePngOperation> DvppDecodePng();
/// \brief Function to create a DvppResizeJpeg TensorOperation.
/// \notes Tensor operation to resize JPEG image using Ascend series chip DVPP module.
/// It is recommended to use this algorithm in the following scenarios:
/// When training, the DVPP of the Ascend chip is not used,
/// and the DVPP of the Ascend chip is used during inference,
/// and the accuracy of inference is lower than the accuracy of training;
/// and the input image size should be in range [32*32, 2048*2048].
/// Only images with an even resolution can be output. The output of odd resolution is not supported.
/// \param[in] resize vector represents the shape of image after resize.
/// \return Shared pointer to the current TensorOperation.
std::shared_ptr<DvppResizeJpegOperation> DvppResizeJpeg(std::vector<uint32_t> resize = {256, 256});
class DvppCropJpegOperation : public TensorOperation {
public:
explicit DvppCropJpegOperation(const std::vector<uint32_t> &resize);
~DvppCropJpegOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppCropJpegOperation; }
private:
std::vector<uint32_t> crop_;
};
class DvppDecodeResizeOperation : public TensorOperation {
public:
explicit DvppDecodeResizeOperation(const std::vector<uint32_t> &resize);
~DvppDecodeResizeOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppDecodeResizeOperation; }
private:
std::vector<uint32_t> resize_;
};
class DvppDecodeResizeCropOperation : public TensorOperation {
public:
explicit DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop, const std::vector<uint32_t> &resize);
~DvppDecodeResizeCropOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppDecodeResizeCropOperation; }
private:
std::vector<uint32_t> crop_;
std::vector<uint32_t> resize_;
};
class DvppDecodeJpegOperation : public TensorOperation {
public:
~DvppDecodeJpegOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppDecodeJpegOperation; }
};
class DvppDecodePngOperation : public TensorOperation {
public:
~DvppDecodePngOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppDecodePngOperation; }
};
class DvppResizeJpegOperation : public TensorOperation {
public:
explicit DvppResizeJpegOperation(const std::vector<uint32_t> &resize);
~DvppResizeJpegOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppResizeJpegOperation; }
private:
std::vector<uint32_t> resize_;
};
} // namespace vision
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_INCLUDE_VISION_ASCEND_H_

View File

@ -2,5 +2,10 @@ file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc"
set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD)
add_subdirectory(utils)
add_library(kernels-dvpp-image OBJECT
dvpp_decode_resize_crop_jpeg_op.cc)
dvpp_crop_jpeg_op.cc
dvpp_decode_resize_crop_jpeg_op.cc
dvpp_decode_resize_jpeg_op.cc
dvpp_decode_jpeg_op.cc
dvpp_resize_jpeg_op.cc
dvpp_decode_png_op.cc)
add_dependencies(kernels-dvpp-image dvpp-utils)

View File

@ -0,0 +1,145 @@
/**
* 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 <string>
#include <vector>
#include <iostream>
#include "include/api/context.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_crop_jpeg_op.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
Status DvppCropJpegOp::Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer is empty.");
std::string last_step = "Resize";
std::shared_ptr<DvppDataInfo> imageinfo(processor_->Get_Resized_DeviceData());
if (!imageinfo->data) {
last_step = "Decode";
}
APP_ERROR ret = processor_->JPEG_C(last_step);
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp crop processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> CropOut(processor_->Get_Croped_DeviceData());
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(CropOut);
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from device memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppCropJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppCropJpegOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
DvppDataInfo imageinfo;
imageinfo.dataSize = input->SizeInBytes();
imageinfo.data = static_cast<uint8_t *>(buffer);
std::vector<uint32_t> yuv_shape_ = input->GetYuvShape();
imageinfo.width = yuv_shape_[0];
imageinfo.widthStride = yuv_shape_[1];
imageinfo.height = yuv_shape_[2];
imageinfo.heightStride = yuv_shape_[3];
imageinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> instance = ResourceManager::GetInstance();
APP_ERROR ret = instance->InitResource(resource);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init D-chip:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D-chip and set up all configures
MDAclProcess process(crop_width_, crop_height_, context, true);
ret = process.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.JPEG_C(imageinfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp crop processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> CropOut(process.Get_Croped_DeviceData());
dsize_t dvpp_length = CropOut->dataSize;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
uint32_t crop_height = CropOut->height;
uint32_t crop_heightStride = CropOut->heightStride;
uint32_t crop_width = CropOut->width;
uint32_t crop_widthStride = CropOut->widthStride;
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
(*output)->SetYuvShape(crop_width, crop_widthStride, crop_height, crop_heightStride);
if (!((*output)->HasData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppCropJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppCropJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels
if (inputs[0].Rank() == 1) outputs.emplace_back(out);
if (!outputs.empty()) return Status::OK();
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
Status DvppCropJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetCropParas(crop_width_, crop_height_);
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,62 @@
/**
* 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_DVPP_DVPP_CROP_JPEG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "mindspore/core/utils/log_adapter.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
class DvppCropJpegOp : public TensorOp {
public:
DvppCropJpegOp(int32_t crop_height, int32_t crop_width) : crop_height_(crop_height), crop_width_(crop_width) {}
/// \brief Destructor
~DvppCropJpegOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppCropJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
uint32_t crop_height_;
uint32_t crop_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_CROP_JPEG_OP_H

View File

@ -0,0 +1,139 @@
/**
* 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 <string>
#include <vector>
#include <iostream>
#include "include/api/context.h"
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
// Compute() will be called when context=="Ascend310"
Status DvppDecodeJpegOp::Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty");
APP_ERROR ret = processor_->JPEG_D();
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> DecodeOut(processor_->Get_Decode_DeviceData());
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(DecodeOut);
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
// Compute() will be called when context=="CPU"
Status DvppDecodeJpegOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
if (!IsNonEmptyJPEG(input)) {
RETURN_STATUS_UNEXPECTED("DvppDecodeJpegOp only support process JPEG image.");
}
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> instance = ResourceManager::GetInstance();
APP_ERROR ret = instance->InitResource(resource);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init D-chip:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D-chip and set up all configures
MDAclProcess process(context, false);
ret = process.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.JPEG_D(imageInfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> DecodeOut(process.Get_Decode_DeviceData());
dsize_t dvpp_length = DecodeOut->dataSize;
uint32_t decoded_height = DecodeOut->height;
uint32_t decoded_heightStride = DecodeOut->heightStride;
uint32_t decoded_width = DecodeOut->width;
uint32_t decoded_widthStride = DecodeOut->widthStride;
// std::cout << "Decoded size: " << decoded_width << ", " << decoded_height << std::endl;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
(*output)->SetYuvShape(decoded_width, decoded_widthStride, decoded_height, decoded_heightStride);
if (!((*output)->HasData())) {
std::string error = "[ERROR] Fail to get the Output result from device memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodeJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
return Status::OK();
}
Status DvppDecodeJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 3 channels
if (inputs[0].Rank() == 1) outputs.emplace_back(out);
if (!outputs.empty()) return Status::OK();
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,59 @@
/**
* 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_DVPP_DVPP_DECODE_JPEG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "mindspore/core/utils/log_adapter.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
class DvppDecodeJpegOp : public TensorOp {
public:
DvppDecodeJpegOp() { processor_ = nullptr; }
/// \brief Destructor
~DvppDecodeJpegOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_JPEG_OP_H

View File

@ -0,0 +1,138 @@
/**
* 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 <string>
#include <vector>
#include <iostream>
#include "include/api/context.h"
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_png_op.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
Status DvppDecodePngOp::Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty");
APP_ERROR ret = processor_->PNG_D();
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> DecodeOut(processor_->Get_Decode_DeviceData());
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(DecodeOut);
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodePngOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
if (!IsNonEmptyPNG(input)) {
RETURN_STATUS_UNEXPECTED("DvppDecodePngOp only support process PNG image.");
}
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> instance = ResourceManager::GetInstance();
APP_ERROR ret = instance->InitResource(resource);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init D-chip:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D-chip and set up all configures
MDAclProcess process(context, false);
ret = process.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.PNG_D(imageInfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
/* 测试Device内存
*/
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> DecodeOut(process.Get_Decode_DeviceData());
dsize_t dvpp_length = DecodeOut->dataSize;
// dsize_t decode_height = DecodeOut->height;
// dsize_t decode_width = DecodeOut->width;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
if (!((*output)->HasData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodePngOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodePngOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 3 channels
if (inputs[0].Rank() == 1) outputs.emplace_back(out);
if (!outputs.empty()) return Status::OK();
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
Status DvppDecodePngOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,58 @@
/**
* 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_DVPP_DVPP_DECODE_PNG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "mindspore/core/utils/log_adapter.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
class DvppDecodePngOp : public TensorOp {
public:
DvppDecodePngOp() {}
/// \brief Destructor
~DvppDecodePngOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodePngOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_PNG_OP_H

View File

@ -17,20 +17,48 @@
#include <string>
#include <vector>
#include <iostream>
#include "minddata/dataset/kernels/image/dvpp/utils/AclProcess.h"
#include "include/api/context.h"
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/kernels/image/image_utils.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
#include "include/api/context.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<DeviceTensor> &input,
std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty");
APP_ERROR ret = processor_->JPEG_DRC();
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> CropOut(processor_->Get_Croped_DeviceData());
// std::cout << "Decoded size: " << decoded_width << ", " << decoded_height << std::endl;
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(CropOut);
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeResizeCropJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
if (!IsNonEmptyJPEG(input)) {
RETURN_STATUS_UNEXPECTED("SoftDvppDecodeReiszeJpegOp only support process jpeg image.");
RETURN_STATUS_UNEXPECTED("DvppDecodeReiszeJpegOp only support process jpeg image.");
}
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
@ -38,11 +66,7 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<Tensor> &input,
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = std::make_shared<uint8_t>();
imageInfo.data.reset(new uint8_t[filesize], std::default_delete<uint8_t[]>());
memcpy_s(imageInfo.data.get(), filesize, buffer, filesize);
// First part end, whose function is to transform data from a Tensor to imageinfo data structure which can be
// applied on device
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
@ -56,25 +80,26 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<Tensor> &input,
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D chip and set up all configures
AclProcess process(resized_width_, resized_height_, crop_width_, crop_height_, context);
process.set_mode(true);
ret = process.InitResource();
MDAclProcess processor(resized_width_, resized_height_, crop_width_, crop_height_, context, true);
ret = processor.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.Process(imageInfo);
ret = processor.JPEG_DRC(imageInfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
auto data = std::static_pointer_cast<unsigned char>(processor.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> CropOut = process.Get_Device_Memory_Data();
dsize_t dvpp_length = CropOut->dataSize;
std::shared_ptr<DvppDataInfo> CropOut(processor.Get_Croped_DeviceData());
uint32_t dvpp_length = CropOut->dataSize;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
@ -82,8 +107,8 @@ Status DvppDecodeResizeCropJpegOp::Compute(const std::shared_ptr<Tensor> &input,
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
processor.device_memory_release();
processor.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeResizeCropJpegOp:" + std::string(e.what());
@ -102,5 +127,12 @@ Status DvppDecodeResizeCropJpegOp::OutputShape(const std::vector<TensorShape> &i
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
Status DvppDecodeResizeCropJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
processor_->SetCropParas(crop_width_, crop_height_);
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

View File

@ -14,21 +14,21 @@
* limitations under the License.
*/
#ifndef MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H
#define MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H
#ifndef MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
#include "minddata/dataset/core/data_type.h"
#include "acl/acl.h"
#include "mindspore/core/utils/log_adapter.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "acl/acl.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
@ -44,17 +44,23 @@ class DvppDecodeResizeCropJpegOp : public TensorOp {
~DvppDecodeResizeCropJpegOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeResizeCropJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
int32_t crop_height_;
int32_t crop_width_;
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_CROP_JPEG_OP_H

View File

@ -0,0 +1,134 @@
/**
* 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 <string>
#include <vector>
#include <iostream>
#include "include/api/context.h"
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
Status DvppDecodeResizeJpegOp::Compute(const std::shared_ptr<DeviceTensor> &input,
std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer on device is empty");
APP_ERROR ret = processor_->JPEG_DR();
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> ResizeOut(processor_->Get_Resized_DeviceData());
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(ResizeOut);
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeResizeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodeResizeJpegOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
if (!IsNonEmptyJPEG(input)) {
RETURN_STATUS_UNEXPECTED("DvppDecodeReiszeJpegOp only support process jpeg image.");
}
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
RawData imageInfo;
uint32_t filesize = input->SizeInBytes();
imageInfo.lenOfByte = filesize;
imageInfo.data = static_cast<void *>(buffer);
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> instance = ResourceManager::GetInstance();
APP_ERROR ret = instance->InitResource(resource);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init D-chip:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D-chip and set up all configures
MDAclProcess process(resized_width_, resized_height_, context, false);
ret = process.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.JPEG_DR(imageInfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> ResizeOut(process.Get_Resized_DeviceData());
dsize_t dvpp_length = ResizeOut->dataSize;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
if (!((*output)->HasData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppDecodeResizeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppDecodeResizeJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels
if (inputs[0].Rank() == 1) outputs.emplace_back(out);
if (!outputs.empty()) return Status::OK();
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
Status DvppDecodeResizeJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
return Status::OK();
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,62 @@
/**
* 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_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "mindspore/core/utils/log_adapter.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
namespace mindspore {
namespace dataset {
class DvppDecodeResizeJpegOp : public TensorOp {
public:
DvppDecodeResizeJpegOp(int32_t resized_height, int32_t resized_width)
: resized_height_(resized_height), resized_width_(resized_width) {}
/// \brief Destructor
~DvppDecodeResizeJpegOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeResizeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_DECODE_RESIZE_JPEG_OP_H

View File

@ -0,0 +1,147 @@
/**
* 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 <string>
#include <vector>
#include <iostream>
#include "include/api/context.h"
#include "minddata/dataset/core/cv_tensor.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_resize_jpeg_op.h"
#include "minddata/dataset/kernels/image/dvpp/utils/CommonDataType.h"
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#include "minddata/dataset/kernels/image/image_utils.h"
namespace mindspore {
namespace dataset {
Status DvppResizeJpegOp::Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetDeviceBuffer() != nullptr, "The input image buffer is empty.");
std::string last_step = "Decode";
std::shared_ptr<DvppDataInfo> imageinfo(processor_->Get_Decode_DeviceData());
if (!imageinfo->data) {
last_step = "Crop";
}
APP_ERROR ret = processor_->JPEG_R(last_step);
if (ret != APP_ERR_OK) {
processor_->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
std::shared_ptr<DvppDataInfo> ResizeOut(processor_->Get_Resized_DeviceData());
const TensorShape dvpp_shape({1, 1, 1});
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, output);
(*output)->SetAttributes(ResizeOut); // Set attributes for output DeviceTensor
if (!((*output)->HasDeviceData())) {
std::string error = "[ERROR] Fail to get the Output result from device memory!";
RETURN_STATUS_UNEXPECTED(error);
}
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppResizeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppResizeJpegOp::Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
IO_CHECK(input, output);
try {
CHECK_FAIL_RETURN_UNEXPECTED(input->GetBuffer() != nullptr, "The input image buffer is empty.");
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
DvppDataInfo imageinfo;
imageinfo.dataSize = input->SizeInBytes();
imageinfo.data = static_cast<uint8_t *>(buffer);
std::vector<uint32_t> yuv_shape_ = input->GetYuvShape();
imageinfo.width = yuv_shape_[0];
imageinfo.widthStride = yuv_shape_[1];
imageinfo.height = yuv_shape_[2];
imageinfo.heightStride = yuv_shape_[3];
imageinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
ResourceInfo resource;
resource.aclConfigPath = "";
resource.deviceIds.insert(mindspore::GlobalContext::GetGlobalDeviceID());
std::shared_ptr<ResourceManager> instance = ResourceManager::GetInstance();
APP_ERROR ret = instance->InitResource(resource);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init D-chip:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
int deviceId = *(resource.deviceIds.begin());
aclrtContext context = instance->GetContext(deviceId);
// Second part end where we initialize the resource of D-chip and set up all configures
MDAclProcess process(resized_width_, resized_height_, context, false);
ret = process.InitResource();
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in Init resource:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
ret = process.JPEG_R(imageinfo);
if (ret != APP_ERR_OK) {
instance->Release();
std::string error = "Error in dvpp processing:" + std::to_string(ret);
RETURN_STATUS_UNEXPECTED(error);
}
// Third part end where we execute the core function of dvpp
auto data = std::static_pointer_cast<unsigned char>(process.Get_Memory_Data());
unsigned char *ret_ptr = data.get();
std::shared_ptr<DvppDataInfo> ResizeOut(process.Get_Resized_DeviceData());
dsize_t dvpp_length = ResizeOut->dataSize;
const TensorShape dvpp_shape({dvpp_length, 1, 1});
uint32_t resized_height = ResizeOut->height;
uint32_t resized_heightStride = ResizeOut->heightStride;
uint32_t resized_width = ResizeOut->width;
uint32_t resized_widthStride = ResizeOut->widthStride;
const DataType dvpp_data_type(DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, output);
(*output)->SetYuvShape(resized_width, resized_widthStride, resized_height, resized_heightStride);
if (!((*output)->HasData())) {
std::string error = "[ERROR] Fail to get the Output result from memory!";
RETURN_STATUS_UNEXPECTED(error);
}
process.device_memory_release();
process.Release();
// Last part end where we transform the processed data into a tensor which can be applied in later units.
} catch (const cv::Exception &e) {
std::string error = "[ERROR] Fail in DvppResizeJpegOp:" + std::string(e.what());
RETURN_STATUS_UNEXPECTED(error);
}
return Status::OK();
}
Status DvppResizeJpegOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
processor_ = processor;
processor_->SetResizeParas(resized_width_, resized_height_);
return Status::OK();
}
Status DvppResizeJpegOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
RETURN_IF_NOT_OK(TensorOp::OutputShape(inputs, outputs));
outputs.clear();
TensorShape out({-1, 1, 1}); // we don't know what is output image size, but we know it should be 1 channels
if (inputs[0].Rank() == 1) outputs.emplace_back(out);
if (!outputs.empty()) return Status::OK();
return Status(StatusCode::kMDUnexpectedError, "Input has a wrong shape");
}
} // namespace dataset
} // namespace mindspore

View File

@ -0,0 +1,63 @@
/**
* 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_DVPP_DVPP_RESIZE_JPEG_OP_H
#define MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "minddata/dataset/core/data_type.h"
#include "minddata/dataset/core/device_tensor.h"
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ErrorCode.h"
#include "minddata/dataset/kernels/image/dvpp/utils/ResourceManager.h"
#include "minddata/dataset/kernels/tensor_op.h"
#include "minddata/dataset/util/status.h"
#include "mindspore/core/utils/log_adapter.h"
namespace mindspore {
namespace dataset {
class DvppResizeJpegOp : public TensorOp {
public:
DvppResizeJpegOp(int32_t resized_height, int32_t resized_width)
: resized_height_(resized_height), resized_width_(resized_width) {}
/// \brief Destructor
~DvppResizeJpegOp() = default;
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) override;
Status OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) override;
std::string Name() const override { return kDvppDecodeResizeJpegOp; }
Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) override;
private:
int32_t resized_height_;
int32_t resized_width_;
std::shared_ptr<MDAclProcess> processor_;
};
} // namespace dataset
} // namespace mindspore
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_DVPP_DVPP_RESIZE_JPEG_OP_H

View File

@ -1,255 +0,0 @@
/*
* Copyright (c) 2020.Huawei Technologies Co., Ltd. All rights reserved.
* 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 "AclProcess.h"
#include <sys/stat.h>
#include <sys/time.h>
#include <thread>
namespace {
const int BUFFER_SIZE = 2048;
const mode_t DEFAULT_FILE_PERMISSION = 0077;
} // namespace
mode_t SetFileDefaultUmask() { return umask(DEFAULT_FILE_PERMISSION); }
/*
* @description: Constructor
* @param: resizeWidth specifies the resized width
* @param: resizeHeight specifies the resized hegiht
* @param: stream is used to maintain the execution order of operations
* @param: context is used to manage the life cycle of objects
* @param: dvppCommon is a class for decoding and resizing
*/
AclProcess::AclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight,
aclrtContext context, aclrtStream stream, std::shared_ptr<DvppCommon> dvppCommon)
: resizeWidth_(resizeWidth),
resizeHeight_(resizeHeight),
cropWidth_(cropWidth),
cropHeight_(cropHeight),
context_(context),
stream_(stream),
dvppCommon_(dvppCommon) {
repeat_ = true;
}
/*
* @description: Release AclProcess resources
* @return: aclError which is error code of ACL API
*/
APP_ERROR AclProcess::Release() {
// Release objects resource
APP_ERROR ret = dvppCommon_->DeInit();
dvppCommon_->ReleaseDvppBuffer();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to deinitialize dvppCommon_, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "dvppCommon_ object deinitialized successfully";
dvppCommon_.reset();
// Release stream
if (stream_ != nullptr) {
ret = aclrtDestroyStream(stream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to destroy stream, ret = " << ret;
stream_ = nullptr;
return ret;
}
stream_ = nullptr;
}
MS_LOG(INFO) << "The stream is destroyed successfully";
return APP_ERR_OK;
}
/*
* @description: Initialize DvppCommon object
* @return: aclError which is error code of ACL API
*/
APP_ERROR AclProcess::InitModule() {
// Create Dvpp JpegD object
dvppCommon_ = std::make_shared<DvppCommon>(stream_);
if (dvppCommon_ == nullptr) {
MS_LOG(ERROR) << "Failed to create dvppCommon_ object";
return APP_ERR_COMM_INIT_FAIL;
}
MS_LOG(INFO) << "DvppCommon object created successfully";
APP_ERROR ret = dvppCommon_->Init();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to initialize dvppCommon_ object, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "DvppCommon object initialized successfully";
return APP_ERR_OK;
}
/*
* @description: Initialize AclProcess resources
* @return: aclError which is error code of ACL API
*/
APP_ERROR AclProcess::InitResource() {
APP_ERROR ret = aclrtSetCurrentContext(context_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get ACL context, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "The context is created successfully";
ret = aclrtCreateStream(&stream_); // Create stream for application
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to create ACL stream, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "The stream is created successfully";
// Initialize dvpp module
if (InitModule() != APP_ERR_OK) {
return APP_ERR_COMM_INIT_FAIL;
}
return APP_ERR_OK;
}
/*
* @description: Read image files, and perform decoding and scaling
* @param: imageFile specifies the image path to be processed
* @return: aclError which is error code of ACL API
*/
APP_ERROR AclProcess::Preprocess(const RawData &ImageInfo) {
// Decode process
APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
// Get output of decoded jpeg image
std::shared_ptr<DvppDataInfo> decodeOutData = dvppCommon_->GetDecodedImage();
if (decodeOutData == nullptr) {
MS_LOG(ERROR) << "Decode output buffer is null.";
return APP_ERR_COMM_INVALID_POINTER;
}
// Define output of resize jpeg image
DvppDataInfo resizeOut;
resizeOut.width = resizeWidth_;
resizeOut.height = resizeHeight_;
resizeOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
// Run resize application function
ret = dvppCommon_->CombineResizeProcess(*(decodeOutData.get()), resizeOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << ".";
return ret;
}
// Get output of resize jpeg image
std::shared_ptr<DvppDataInfo> resizeOutData = dvppCommon_->GetResizedImage();
if (resizeOutData == nullptr) {
MS_LOG(ERROR) << "resize output buffer is null.";
return APP_ERR_COMM_INVALID_POINTER;
}
// Define output of crop jpeg image
DvppDataInfo cropOut;
cropOut.width = cropWidth_;
cropOut.height = cropHeight_;
cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
// Define input of crop jpeg image
DvppCropInputInfo cropInfo;
cropInfo.dataInfo = *(resizeOutData.get());
// Define crop parameters
CropRoiConfig cropCfg;
CropConfigFilter(cropCfg, cropInfo);
ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
/*
* @description: Decode and scale the picture, and write the result to a file
* @param: imageFile specifies the image path to be processed
* @return: aclError which is error code of ACL API
*/
APP_ERROR AclProcess::Process(const RawData &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = Preprocess(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to preprocess, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> CropOutData = dvppCommon_->GetCropedImage();
if (CropOutData->dataSize == 0) {
MS_LOG(ERROR) << "CropOutData return NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
void AclProcess::CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo) {
cfg.up = (resizeHeight_ - cropHeight_) / 2;
if (cfg.up % 2 != 0) {
cfg.up++;
}
cfg.down = resizeHeight_ - (resizeHeight_ - cropHeight_) / 2;
if (cfg.down % 2 == 0) {
cfg.down--;
}
cfg.left = (resizeWidth_ - cropWidth_) / 2;
if (cfg.left % 2 != 0) {
cfg.left++;
}
cfg.right = resizeWidth_ - (resizeWidth_ - cropWidth_) / 2;
if (cfg.right % 2 == 0) {
cfg.right--;
}
cropinfo.roi = cfg;
}
/*
* @description: Obtain result data of memory
* @param: processed_data is result data info pointer
* @return: Address of data in the memory
*/
std::shared_ptr<void> AclProcess::Get_Memory_Data() { return processedInfo_; }
std::shared_ptr<DvppDataInfo> AclProcess::Get_Device_Memory_Data() { return dvppCommon_->GetCropedImage(); }
void AclProcess::set_mode(bool flag) { repeat_ = flag; }
bool AclProcess::get_mode() { return repeat_; }
void AclProcess::device_memory_release() { dvppCommon_->ReleaseDvppBuffer(); }

View File

@ -1,80 +0,0 @@
/*
* Copyright (c) 2020.Huawei Technologies Co., Ltd. All rights reserved.
* 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 ACLMANAGER_H
#define ACLMANAGER_H
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <string.h>
#include <sys/types.h>
#include <string>
#include <map>
#include <climits>
#include <iostream>
#include <memory>
#include "acl/acl.h"
#include "CommonDataType.h"
#include "mindspore/core/utils/log_adapter.h"
#include "ErrorCode.h"
#include "DvppCommon.h"
mode_t SetFileDefaultUmask();
class AclProcess {
public:
AclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight, aclrtContext context,
aclrtStream stream = nullptr, std::shared_ptr<DvppCommon> dvppCommon = nullptr);
~AclProcess() {}
// Release all the resource
APP_ERROR Release();
// Create resource for this sample
APP_ERROR InitResource();
// Process the result
APP_ERROR Process(const RawData &ImageInfo);
// API for access memory
std::shared_ptr<void> Get_Memory_Data();
// API for access device memory
std::shared_ptr<DvppDataInfo> Get_Device_Memory_Data();
// change output method
void set_mode(bool flag);
// Get the mode of Acl process
bool get_mode();
// Crop definition
void CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo);
// D-chip memory release
void device_memory_release();
private:
// Initialize the modules used by this sample
APP_ERROR InitModule();
// Preprocess the input image
APP_ERROR Preprocess(const RawData &ImageInfo);
aclrtContext context_;
aclrtStream stream_;
std::shared_ptr<DvppCommon> dvppCommon_; // dvpp object
std::shared_ptr<void> processedInfo_; // processed data
uint32_t resizeWidth_; // dvpp resize width
uint32_t resizeHeight_; // dvpp resize height
uint32_t cropWidth_; // dvpp crop width
uint32_t cropHeight_; // dvpp crop height
bool repeat_; // Repeatly process image or not
};
#endif

View File

@ -4,7 +4,7 @@ set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE
add_definitions(-DENABLE_DVPP_INTERFACE)
add_library(dvpp-utils OBJECT
AclProcess.cc
MDAclProcess.cc
DvppCommon.cc
ErrorCode.cpp
ResourceManager.cc

View File

@ -21,7 +21,6 @@
#include <stdio.h>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "acl/acl.h"
#include "acl/ops/acl_dvpp.h"
@ -42,15 +41,6 @@ const int JPEG_WIDTH_ALIGN = 128;
const int JPEG_HEIGHT_ALIGN = 16;
const int VPC_OFFSET_ALIGN = 2;
// Tensor Descriptor
struct Tensor {
aclDataType dataType; // Tensor data type
int numDim; // Number of dimensions of Tensor
std::vector<int64_t> dims; // Dimension vector
aclFormat format; // Format of tensor, e.g. ND, NCHW, NC1HWC0
std::string name; // Name of tensor
};
// Data type of tensor
enum OpAttrType {
BOOL = 0,
@ -92,8 +82,8 @@ struct ImageInfo {
// Description of data in device
struct RawData {
size_t lenOfByte; // Size of memory, bytes
std::shared_ptr<void> data; // Smart pointer of data
size_t lenOfByte; // Size of memory, bytes
void *data; // Pointer of data
};
// Description of data in device

View File

@ -15,6 +15,7 @@
#include <iostream>
#include <memory>
#include "mindspore/core/utils/log_adapter.h"
#include "DvppCommon.h"
#include "CommonDataType.h"
@ -185,11 +186,16 @@ void DvppCommon::ReleaseDvppBuffer() {
*/
APP_ERROR DvppCommon::GetVpcDataSize(uint32_t width, uint32_t height, acldvppPixelFormat format, uint32_t &vpcSize) {
// Check the invalid format of VPC function and calculate the output buffer size
if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
MS_LOG(ERROR) << "Format[" << format << "] for VPC is not supported, just support NV12 or NV21.";
if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 &&
format != PIXEL_FORMAT_RGB_888) {
MS_LOG(ERROR) << "Format[" << format << "] for VPC is not supported, just support NV12 or NV21 or RGB888.";
return APP_ERR_COMM_INVALID_PARAM;
}
uint32_t widthStride = DVPP_ALIGN_UP(width, VPC_WIDTH_ALIGN);
if (format == PIXEL_FORMAT_RGB_888) {
widthStride *= 3;
}
uint32_t heightStride = DVPP_ALIGN_UP(height, VPC_HEIGHT_ALIGN);
vpcSize = widthStride * heightStride * YUV_BGR_SIZE_CONVERT_3 / YUV_BGR_SIZE_CONVERT_2;
return APP_ERR_OK;
@ -254,12 +260,17 @@ APP_ERROR DvppCommon::GetVpcInputStrideSize(uint32_t width, uint32_t height, acl
APP_ERROR DvppCommon::GetVpcOutputStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format,
uint32_t &widthStride, uint32_t &heightStride) {
// Check the invalidty of output format and calculate the output width and height
if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
MS_LOG(ERROR) << "Output format[" << format << "] for VPC is not supported, just support NV12 or NV21.";
if (format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 &&
format != PIXEL_FORMAT_RGB_888) {
MS_LOG(ERROR) << "Output format[" << format << "] for VPC is not supported, just support NV12 or NV21 or RGB888.";
return APP_ERR_COMM_INVALID_PARAM;
}
widthStride = DVPP_ALIGN_UP(width, VPC_STRIDE_WIDTH);
if (format == PIXEL_FORMAT_RGB_888) {
widthStride *= 3;
}
heightStride = DVPP_ALIGN_UP(height, VPC_STRIDE_HEIGHT);
return APP_ERR_OK;
}
@ -373,8 +384,9 @@ APP_ERROR DvppCommon::SetDvppPicDescData(const DvppDataInfo &dataInfo, acldvppPi
* @return: APP_ERR_OK if success, other values if failure
*/
APP_ERROR DvppCommon::CheckResizeParams(const DvppDataInfo &input, const DvppDataInfo &output) {
if (output.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && output.format != PIXEL_FORMAT_YVU_SEMIPLANAR_420) {
MS_LOG(ERROR) << "Output format[" << output.format << "] for VPC is not supported, just support NV12 or NV21.";
if (output.format != PIXEL_FORMAT_YUV_SEMIPLANAR_420 && output.format != PIXEL_FORMAT_YVU_SEMIPLANAR_420 &&
output.format != PIXEL_FORMAT_RGB_888) {
MS_LOG(ERROR) << "Output format[" << output.format << "] for VPC is not supported, only NV12 or NV21 or RGB888.";
return APP_ERR_COMM_INVALID_PARAM;
}
if (((float)output.height / input.height) < MIN_RESIZE_SCALE ||
@ -419,6 +431,7 @@ APP_ERROR DvppCommon::ResizeProcess(acldvppPicDesc &inputDesc, acldvppPicDesc &o
return ret;
}
}
return APP_ERR_OK;
}
@ -770,6 +783,7 @@ APP_ERROR DvppCommon::CombineCropProcess(DvppCropInputInfo &input, DvppDataInfo
if (ret != APP_ERR_OK) {
return ret;
}
// cropImage_所持有的成员变量 uint8_t *data通过acldvppMalloc()接口申请位于Device上
cropImage_ = std::make_shared<DvppDataInfo>();
cropImage_->width = output.width;
cropImage_->height = output.height;
@ -839,6 +853,44 @@ APP_ERROR DvppCommon::JpegDecode(DvppDataInfo &input, DvppDataInfo &output, bool
return APP_ERR_OK;
}
/*
* @description: Set the description of the output image and decode
* @param: input specifies the input image information
* @param: output specifies the output image information
* @param: withSynchronize specifies whether to execute synchronously
* @return: APP_ERR_OK if success, other values if failure
* @attention: This function can be called only when the DvppCommon object is initialized with Init
*/
APP_ERROR DvppCommon::PngDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize) {
// Return special error code when the DvppCommon object is initialized with InitVdec
if (isVdec_) {
MS_LOG(ERROR) << "PngDecode cannot be called by the DvppCommon object which is initialized with InitVdec.";
return APP_ERR_DVPP_OBJ_FUNC_MISMATCH;
}
acldvppPicDesc *outputDesc = acldvppCreatePicDesc();
decodeOutputDesc_.reset(outputDesc, g_picDescDeleter);
APP_ERROR ret = SetDvppPicDescData(output, *decodeOutputDesc_);
if (ret != APP_ERR_OK) {
return ret;
}
ret = acldvppPngDecodeAsync(dvppChannelDesc_, input.data, input.dataSize, decodeOutputDesc_.get(), dvppStream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode png, ret = " << ret << ".";
return ret;
}
if (withSynchronize) {
ret = aclrtSynchronizeStream(dvppStream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to synchronize stream, ret = " << ret << ".";
return APP_ERR_DVPP_JPEG_DECODE_FAIL;
}
}
return APP_ERR_OK;
}
/*
* @description: Get the aligned width and height of the image after decoding
* @param: width specifies the width before alignment
@ -853,6 +905,17 @@ void DvppCommon::GetJpegDecodeStrideSize(uint32_t width, uint32_t height, uint32
heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT);
}
void DvppCommon::GetPngDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride,
acldvppPixelFormat format) {
if (format == PIXEL_FORMAT_RGB_888) {
widthStride = DVPP_ALIGN_UP(width * 3, JPEGD_STRIDE_WIDTH);
heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT);
} else {
widthStride = DVPP_ALIGN_UP(width * 4, JPEGD_STRIDE_WIDTH);
heightStride = DVPP_ALIGN_UP(height, JPEGD_STRIDE_HEIGHT);
}
}
/*
* @description: Get picture width and height and number of channels from image data
* @param: data specifies the memory to store the image data
@ -886,6 +949,39 @@ APP_ERROR DvppCommon::GetJpegImageInfo(const void *data, uint32_t dataSize, uint
return APP_ERR_OK;
}
/*
* @description: Get picture width and height and number of channels from PNG image data
* @param: data specifies the memory to store the image data
* @param: dataSize specifies the size of the image data
* @param: width is used to save the image width
* @param: height is used to save the image height
* @param: components is used to save the number of channels
* @return: APP_ERR_OK if success, other values if failure
*/
APP_ERROR DvppCommon::GetPngImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height,
int32_t &components) {
uint32_t widthTmp;
uint32_t heightTmp;
int32_t componentsTmp;
APP_ERROR ret = acldvppPngGetImageInfo(data, dataSize, &widthTmp, &heightTmp, &componentsTmp);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get image info of PNG, ret = " << ret << ".";
return ret;
}
if (widthTmp > MAX_PNGD_WIDTH || widthTmp < MIN_PNGD_WIDTH) {
MS_LOG(ERROR) << "Input width is invalid, not in [" << MIN_PNGD_WIDTH << ", " << MAX_PNGD_WIDTH << "].";
return APP_ERR_COMM_INVALID_PARAM;
}
if (heightTmp > MAX_PNGD_HEIGHT || heightTmp < MIN_PNGD_HEIGHT) {
MS_LOG(ERROR) << "Input height is invalid, not in [" << MIN_PNGD_HEIGHT << ", " << MAX_PNGD_HEIGHT << "].";
return APP_ERR_COMM_INVALID_PARAM;
}
width = widthTmp;
height = heightTmp;
components = componentsTmp;
return APP_ERR_OK;
}
/*
* @description: Get the size of the buffer for storing decoded images based on the image data, size, and format
* @param: data specifies the memory to store the image data
@ -906,6 +1002,26 @@ APP_ERROR DvppCommon::GetJpegDecodeDataSize(const void *data, uint32_t dataSize,
return APP_ERR_OK;
}
/*
* @description: Get the size of the buffer for storing decoded images based on the PNG image data, size, and format
* @param: data specifies the memory to store the image data
* @param: dataSize specifies the size of the image data
* @param: format specifies the image format
* @param: decSize is used to store the result size
* @return: APP_ERR_OK if success, other values if failure
*/
APP_ERROR DvppCommon::GetPngDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format,
uint32_t &decSize) {
uint32_t outputSize;
APP_ERROR ret = acldvppPngPredictDecSize(data, dataSize, format, &outputSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to predict decode size of png image, ret = " << ret << ".";
return ret;
}
decSize = outputSize;
return APP_ERR_OK;
}
/*
* @description: Decode the image specified by imageInfo and save the result to member variable decodedImage_
* @param: imageInfo specifies image information
@ -923,24 +1039,27 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel
}
int32_t components;
// Member variable of inputImage_, uint8_t *data will be on device
inputImage_ = std::make_shared<DvppDataInfo>();
inputImage_->format = format;
APP_ERROR ret =
GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
// GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
GetJpegImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << ".";
return ret;
}
// Get the buffer size of decode output according to the input data and output format
// Get the buffer size(On device) of decode output according to the input data and output format
uint32_t outBuffSize;
ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize);
// ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize);
ret = GetJpegDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << ".";
return ret;
}
// In TransferImageH2D function, device buffer will be alloced to store the input image
// In TransferImageH2D function, device buffer will be alloced to store the input image before decode
// Need to pay attention to release of the buffer
ret = TransferImageH2D(imageInfo, inputImage_);
if (ret != APP_ERR_OK) {
@ -976,6 +1095,150 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel
return APP_ERR_OK;
}
APP_ERROR DvppCommon::SinkCombineJpegdProcess(std::shared_ptr<DvppDataInfo> &input,
std::shared_ptr<DvppDataInfo> &output, bool withSynchronize) {
// Both input and output are locate on device, so we must release them if fail in decode
APP_ERROR ret = JpegDecode(*input, *output, withSynchronize);
if (ret != APP_ERR_OK) {
// Release the output buffer when decode failed, otherwise release it after use
RELEASE_DVPP_DATA(inputImage_->data);
inputImage_->data = nullptr;
RELEASE_DVPP_DATA(decodedImage_->data);
decodedImage_->data = nullptr;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR DvppCommon::SinkCombinePngdProcess(std::shared_ptr<DvppDataInfo> &input,
std::shared_ptr<DvppDataInfo> &output, bool withSynchronize) {
// Both input and output are locate on device, so we must release them if fail in decode
APP_ERROR ret = PngDecode(*input, *output, withSynchronize);
if (ret != APP_ERR_OK) {
// Release the output buffer when decode failed, otherwise release it after use
RELEASE_DVPP_DATA(inputImage_->data);
inputImage_->data = nullptr;
RELEASE_DVPP_DATA(decodedImage_->data);
decodedImage_->data = nullptr;
return ret;
}
return APP_ERR_OK;
}
/*
* @description: Decode the image specified by imageInfo and save the result to member variable decodedImage_
* This function is for PNG format image
* @param: imageInfo specifies image information
* @param: format specifies the image format
* @param: withSynchronize specifies whether to execute synchronously
* @return: APP_ERR_OK if success, other values if failure
* @attention: This function can be called only when the DvppCommon object is initialized with Init
*/
APP_ERROR DvppCommon::CombinePngdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize) {
// Return special error code when the DvppCommon object is initialized with InitVdec
if (isVdec_) {
MS_LOG(ERROR) << "CombinePngdProcess cannot be called by the DvppCommon object which is initialized with InitVdec.";
return APP_ERR_DVPP_OBJ_FUNC_MISMATCH;
}
int32_t components;
inputImage_ = std::make_shared<DvppDataInfo>();
inputImage_->format = format;
APP_ERROR ret =
// GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
GetPngImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << ".";
return ret;
}
// Get the buffer size of decode output according to the input data and output format
uint32_t outBuffSize;
// ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize);
ret = GetPngDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << ".";
return ret;
}
// In TransferImageH2D function, device buffer will be alloced to store the input image
// Need to pay attention to release of the buffer
ret = TransferImageH2D(imageInfo, inputImage_);
if (ret != APP_ERR_OK) {
return ret;
}
decodedImage_ = std::make_shared<DvppDataInfo>();
decodedImage_->format = format;
decodedImage_->width = inputImage_->width;
decodedImage_->height = inputImage_->height;
GetPngDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride,
decodedImage_->heightStride, format);
decodedImage_->dataSize = outBuffSize;
// Malloc dvpp buffer to store the output data after decoding
// Need to pay attention to release of the buffer
ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << ".";
RELEASE_DVPP_DATA(inputImage_->data);
return ret;
}
ret = PngDecode(*inputImage_, *decodedImage_, withSynchronize);
if (ret != APP_ERR_OK) {
// Release the output buffer when decode failed, otherwise release it after use
RELEASE_DVPP_DATA(inputImage_->data);
inputImage_->data = nullptr;
RELEASE_DVPP_DATA(decodedImage_->data);
decodedImage_->data = nullptr;
return ret;
}
return APP_ERR_OK;
}
/*
* @description: Transfer data from host to device
* @param: imageInfo specifies the image data on the host
* @return: APP_ERR_OK if success, other values if failure
*/
APP_ERROR DvppCommon::TransferYuvDataH2D(const DvppDataInfo &imageinfo) {
if (imageinfo.dataSize <= 0) {
MS_LOG(ERROR) << "The input buffer size on host should not be empty.";
return APP_ERR_COMM_INVALID_PARAM;
}
uint8_t *device_ptr = nullptr;
APP_ERROR ret = acldvppMalloc((void **)&device_ptr, imageinfo.dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to malloc " << imageinfo.dataSize << " bytes on dvpp, ret = " << ret << ".";
return ret;
}
ret = aclrtMemcpyAsync(device_ptr, imageinfo.dataSize, imageinfo.data, imageinfo.dataSize, ACL_MEMCPY_HOST_TO_DEVICE,
dvppStream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy " << imageinfo.dataSize << " bytes from host to device, ret = " << ret << ".";
RELEASE_DVPP_DATA(device_ptr);
return ret;
}
ret = aclrtSynchronizeStream(dvppStream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to synchronize stream, ret = " << ret << ".";
RELEASE_DVPP_DATA(device_ptr);
return ret;
}
/* Important!!! decodedImage_ speifies the image in deocded format(RGB OR YUV)
* Not essentailly to be the image after decode.(Specifies the data not in RAW encode format)
* It can also be the image after resize(Very important)
*/
decodedImage_ = std::make_shared<DvppDataInfo>();
decodedImage_->data = device_ptr;
decodedImage_->dataSize = imageinfo.dataSize;
decodedImage_->height = imageinfo.height;
decodedImage_->heightStride = imageinfo.heightStride;
decodedImage_->width = imageinfo.width;
decodedImage_->widthStride = imageinfo.widthStride;
return APP_ERR_OK;
}
/*
* @description: Transfer data from host to device
* @param: imageInfo specifies the image data on the host
@ -983,7 +1246,13 @@ APP_ERROR DvppCommon::CombineJpegdProcess(const RawData &imageInfo, acldvppPixel
* @return: APP_ERR_OK if success, other values if failure
*/
APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shared_ptr<DvppDataInfo> &jpegInput) {
uint8_t *inDevBuff = nullptr;
// Check image buffer size validity
if (imageInfo.lenOfByte <= 0) {
MS_LOG(ERROR) << "The input buffer size on host should not be empty.";
return APP_ERR_COMM_INVALID_PARAM;
}
uint8_t *inDevBuff = nullptr; // This pointer will be on device
APP_ERROR ret = acldvppMalloc((void **)&inDevBuff, imageInfo.lenOfByte);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to malloc " << imageInfo.lenOfByte << " bytes on dvpp, ret = " << ret << ".";
@ -991,8 +1260,10 @@ APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shar
}
// Copy the image data from host to device
ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data.get(), imageInfo.lenOfByte,
ACL_MEMCPY_HOST_TO_DEVICE, dvppStream_);
// ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data.get(), imageInfo.lenOfByte,
// ACL_MEMCPY_HOST_TO_DEVICE, dvppStream_);
ret = aclrtMemcpyAsync(inDevBuff, imageInfo.lenOfByte, imageInfo.data, imageInfo.lenOfByte, ACL_MEMCPY_HOST_TO_DEVICE,
dvppStream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy " << imageInfo.lenOfByte << " bytes from host to device, ret = " << ret << ".";
RELEASE_DVPP_DATA(inDevBuff);
@ -1011,6 +1282,114 @@ APP_ERROR DvppCommon::TransferImageH2D(const RawData &imageInfo, const std::shar
return APP_ERR_OK;
}
/*
* Sink RawData(On host) into DvppDataInfo(On device)
*/
APP_ERROR DvppCommon::SinkImageH2D(const RawData &imageInfo, acldvppPixelFormat format) {
if (isVdec_) {
MS_LOG(ERROR)
<< "CombineJpegdProcess cannot be called by the DvppCommon object which is initialized with InitVdec.";
return APP_ERR_DVPP_OBJ_FUNC_MISMATCH;
}
int32_t components;
// Member variable of inputImage_, uint8_t *data will be on device
inputImage_ = std::make_shared<DvppDataInfo>();
inputImage_->format = format;
APP_ERROR ret =
// GetJpegImageInfo(imageInfo.data.get(), imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
GetJpegImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << ".";
return ret;
}
// Get the buffer size(On device) of decode output according to the input data and output format
uint32_t outBufferSize;
// ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize);
ret = GetJpegDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBufferSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << ".";
return ret;
}
// In TransferImageH2D function, device buffer will be alloced to store the input image before decode
// Need to pay attention to release of the buffer
ret = TransferImageH2D(imageInfo, inputImage_);
if (ret != APP_ERR_OK) {
return ret;
}
// This part is to define the data after decode (MALLOC ON DEVICE!!)
decodedImage_ = std::make_shared<DvppDataInfo>();
decodedImage_->format = format;
decodedImage_->width = inputImage_->width;
decodedImage_->height = inputImage_->height;
GetJpegDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride,
decodedImage_->heightStride);
// Obtain all the attributes of inputImage_
GetJpegDecodeStrideSize(inputImage_->width, inputImage_->height, inputImage_->widthStride, inputImage_->heightStride);
decodedImage_->dataSize = outBufferSize;
// Malloc dvpp buffer to store the output data after decoding
// Need to pay attention to release of the buffer
ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << ".";
RELEASE_DVPP_DATA(inputImage_->data);
return ret;
}
return APP_ERR_OK;
}
APP_ERROR DvppCommon::SinkImageH2D(const RawData &imageInfo) {
if (isVdec_) {
MS_LOG(ERROR) << "CombinePngdProcess cannot be called by the DvppCommon object which is initialized with InitVdec.";
return APP_ERR_DVPP_OBJ_FUNC_MISMATCH;
}
int32_t components;
inputImage_ = std::make_shared<DvppDataInfo>();
acldvppPixelFormat format = PIXEL_FORMAT_RGB_888;
inputImage_->format = format;
APP_ERROR ret =
GetPngImageInfo(imageInfo.data, imageInfo.lenOfByte, inputImage_->width, inputImage_->height, components);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get input image info, ret = " << ret << ".";
return ret;
}
// Get the buffer size of decode output according to the input data and output format
uint32_t outBuffSize;
// ret = GetJpegDecodeDataSize(imageInfo.data.get(), imageInfo.lenOfByte, format, outBuffSize);
ret = GetPngDecodeDataSize(imageInfo.data, imageInfo.lenOfByte, format, outBuffSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get size of decode output buffer, ret = " << ret << ".";
return ret;
}
// In TransferImageH2D function, device buffer will be alloced to store the input image
// Need to pay attention to release of the buffer
ret = TransferImageH2D(imageInfo, inputImage_);
if (ret != APP_ERR_OK) {
return ret;
}
decodedImage_ = std::make_shared<DvppDataInfo>();
decodedImage_->format = format;
decodedImage_->width = inputImage_->width;
decodedImage_->height = inputImage_->height;
GetPngDecodeStrideSize(inputImage_->width, inputImage_->height, decodedImage_->widthStride,
decodedImage_->heightStride, format);
decodedImage_->dataSize = outBuffSize;
// Malloc dvpp buffer to store the output data after decoding
// Need to pay attention to release of the buffer
ret = acldvppMalloc((void **)&decodedImage_->data, decodedImage_->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to malloc memory on dvpp, ret = " << ret << ".";
RELEASE_DVPP_DATA(inputImage_->data);
return ret;
}
return APP_ERR_OK;
}
/*
* @description: Create and set the description of a video stream
* @param: data specifies the information about the video stream

View File

@ -16,8 +16,6 @@
#ifndef DVPP_COMMON_H
#define DVPP_COMMON_H
#include <vector>
#include <memory>
#include "CommonDataType.h"
#include "ErrorCode.h"
#include "acl/ops/acl_dvpp.h"
@ -61,6 +59,8 @@ struct DeviceStreamData {
const uint32_t JPEGD_STRIDE_WIDTH = 128; // Jpegd module output width need to align up to 128
const uint32_t JPEGD_STRIDE_HEIGHT = 16; // Jpegd module output height need to align up to 16
const uint32_t PNGD_STRIDE_WIDTH = 128; // Pngd module output width need to align up to 128
const uint32_t PNGD_STRIDE_HEIGHT = 16; // Pngd module output height need to align up to 16
const uint32_t JPEGE_STRIDE_WIDTH = 16; // Jpege module input width need to align up to 16
const uint32_t JPEGE_STRIDE_HEIGHT = 1; // Jpege module input height remains unchanged
const uint32_t VPC_STRIDE_WIDTH = 16; // Vpc module output width need to align up to 16
@ -77,6 +77,10 @@ const uint32_t MAX_JPEGD_WIDTH = 8192; // Max width of jpegd module
const uint32_t MAX_JPEGD_HEIGHT = 8192; // Max height of jpegd module
const uint32_t MIN_JPEGD_WIDTH = 32; // Min width of jpegd module
const uint32_t MIN_JPEGD_HEIGHT = 32; // Min height of jpegd module
const uint32_t MAX_PNGD_WIDTH = 4096; // Max width of pngd module
const uint32_t MAX_PNGD_HEIGHT = 4096; // Max height of pngd module
const uint32_t MIN_PNGD_WIDTH = 32; // Min width of pngd module
const uint32_t MIN_PNGD_HEIGHT = 32; // Min height of pngd module
const uint32_t MAX_JPEGE_WIDTH = 8192; // Max width of jpege module
const uint32_t MAX_JPEGE_HEIGHT = 8192; // Max height of jpege module
const uint32_t MIN_JPEGE_WIDTH = 32; // Min width of jpege module
@ -126,10 +130,16 @@ class DvppCommon {
static APP_ERROR GetVpcOutputStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format,
uint32_t &widthStride, uint32_t &heightStride);
static void GetJpegDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride);
static void GetPngDecodeStrideSize(uint32_t width, uint32_t height, uint32_t &widthStride, uint32_t &heightStride,
acldvppPixelFormat format);
static APP_ERROR GetJpegImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height,
int32_t &components);
static APP_ERROR GetPngImageInfo(const void *data, uint32_t dataSize, uint32_t &width, uint32_t &height,
int32_t &components);
static APP_ERROR GetJpegDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format,
uint32_t &decSize);
static APP_ERROR GetPngDecodeDataSize(const void *data, uint32_t dataSize, acldvppPixelFormat format,
uint32_t &decSize);
static APP_ERROR GetJpegEncodeStrideSize(std::shared_ptr<DvppDataInfo> &input);
static APP_ERROR SetEncodeLevel(uint32_t level, acldvppJpegeConfig &jpegeConfig);
static APP_ERROR GetVideoDecodeStrideSize(uint32_t width, uint32_t height, acldvppPixelFormat format,
@ -143,6 +153,8 @@ class DvppCommon {
APP_ERROR VpcCrop(const DvppCropInputInfo &input, const DvppDataInfo &output, bool withSynchronize);
APP_ERROR JpegDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize);
APP_ERROR PngDecode(DvppDataInfo &input, DvppDataInfo &output, bool withSynchronize);
APP_ERROR JpegEncode(DvppDataInfo &input, DvppDataInfo &output, acldvppJpegeConfig *jpegeConfig,
bool withSynchronize);
@ -156,8 +168,17 @@ class DvppCommon {
VpcProcessType processType = VPC_PT_DEFAULT);
APP_ERROR CombineCropProcess(DvppCropInputInfo &input, DvppDataInfo &output, bool withSynchronize);
APP_ERROR CombineJpegdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize);
APP_ERROR SinkCombineJpegdProcess(std::shared_ptr<DvppDataInfo> &input, std::shared_ptr<DvppDataInfo> &output,
bool withSynchronize);
APP_ERROR SinkCombinePngdProcess(std::shared_ptr<DvppDataInfo> &input, std::shared_ptr<DvppDataInfo> &output,
bool withSynchronize);
APP_ERROR CombineJpegeProcess(const RawData &imageInfo, uint32_t width, uint32_t height, acldvppPixelFormat format,
bool withSynchronize);
// New feature for PNG format image decode
APP_ERROR CombinePngdProcess(const RawData &imageInfo, acldvppPixelFormat format, bool withSynchronize);
// The following interface can be called only when the DvppCommon object is initialized with InitVdec
APP_ERROR CombineVdecProcess(std::shared_ptr<DvppDataInfo> data, void *userData);
@ -168,6 +189,15 @@ class DvppCommon {
std::shared_ptr<DvppDataInfo> GetEncodedImage();
std::shared_ptr<DvppDataInfo> GetCropedImage();
// Transfer DvppDataInfo from host to device, aim at resize and crop
APP_ERROR TransferYuvDataH2D(const DvppDataInfo &imageinfo);
// Transfer RawData(image) from host to device, aim at decode
APP_ERROR TransferImageH2D(const RawData &imageInfo, const std::shared_ptr<DvppDataInfo> &jpegInput);
// Transfer RawData(image on host) to inputImage_(data on device), this is for data sink mode
APP_ERROR SinkImageH2D(const RawData &imageInfo, acldvppPixelFormat format);
// This overload function is for PNG image sink, hence we ignore the pixel format
APP_ERROR SinkImageH2D(const RawData &imageInfo);
// Release the memory that is allocated in the interfaces which are started with "Combine"
void ReleaseDvppBuffer();
APP_ERROR VdecSendEosFrame() const;
@ -185,7 +215,6 @@ class DvppCommon {
bool withSynchronize);
APP_ERROR CheckResizeParams(const DvppDataInfo &input, const DvppDataInfo &output);
APP_ERROR CheckCropParams(const DvppCropInputInfo &input);
APP_ERROR TransferImageH2D(const RawData &imageInfo, const std::shared_ptr<DvppDataInfo> &jpegInput);
APP_ERROR CreateStreamDesc(std::shared_ptr<DvppDataInfo> data);
APP_ERROR DestroyResource();

View File

@ -37,13 +37,14 @@ std::string GetAppErrCodeInfo(const APP_ERROR err) {
}
}
void AssertErrorCode(const int code, const std::string &file, const std::string &function, const int line) {
void AssertErrorCode(const int code, const std::string file, const std::string function, const int line) {
if (code != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed at " << file << "->" << function << "->" << line << ": error code=" << code;
exit(code);
}
}
void CheckErrorCode(const int code, const std::string &file, const std::string &function, const int line) {
void CheckErrorCode(const int code, const std::string file, const std::string function, const int line) {
if (code != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed at " << file << "->" << function << "->" << line << ": error code=" << code;
}

View File

@ -139,7 +139,7 @@ enum {
APP_ERROR_FACE_WEB_USE_PART_SUCCESS = APP_ERROR_FACE_WEB_USE_BASE + 4, // Web: partial search succeeded
APP_ERROR_FACE_WEB_USE_NO_FACE = APP_ERROR_FACE_WEB_USE_BASE + 5, // Web: no face detected
APP_ERR_QUEUE_END, // Not an error code, define the range of blocking queue
// error code
// error code
};
const std::string APP_ERR_ACL_LOG_STRING[] = {
[APP_ERR_OK] = "Success",
@ -249,10 +249,10 @@ const std::string APP_ERR_FACE_LOG_STRING[] = {
};
std::string GetAppErrCodeInfo(APP_ERROR err);
void AssertErrorCode(const int code, const std::string &file, const std::string &function, const int line);
void CheckErrorCode(const int code, const std::string &file, const std::string &function, const int line);
void AssertErrorCode(const int code, const std::string file, const std::string function, const int line);
void CheckErrorCode(const int code, const std::string file, const std::string function, const int line);
#define RtAssert(code) AssertErrorCode(code, __FILE__, __FUNCTION__, __LINE__);
#define RtCheckError(code) CheckErrorCode(code, __FILE__, __FUNCTION__, __LINE__);
#endif // ERROR_CODE_H_
#endif // ERROR_CODE_H_

View File

@ -0,0 +1,966 @@
/*
* Copyright (c) 2020.Huawei Technologies Co., Ltd. All rights reserved.
* 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/core/constants.h"
#include "minddata/dataset/core/tensor_shape.h"
#include "minddata/dataset/kernels/image/image_utils.h"
#include "MDAclProcess.h"
#include <sys/time.h>
#include <thread>
#include <sys/stat.h>
namespace {
const int BUFFER_SIZE = 2048;
const mode_t DEFAULT_FILE_PERMISSION = 0077;
} // namespace
mode_t SetFileDefaultUmask() { return umask(DEFAULT_FILE_PERMISSION); }
/*
* @description: Constructor
* @param: resizeWidth specifies the resized width
* @param: resizeHeight specifies the resized hegiht
* @param: stream is used to maintain the execution order of operations
* @param: context is used to manage the life cycle of objects
* @param: dvppCommon is a class for decoding and resizing
*/
MDAclProcess::MDAclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight,
aclrtContext context, bool is_crop, aclrtStream stream,
std::shared_ptr<DvppCommon> dvppCommon)
: resizeWidth_(resizeWidth),
resizeHeight_(resizeHeight),
cropWidth_(cropWidth),
cropHeight_(cropHeight),
context_(context),
stream_(stream),
contain_crop_(is_crop),
dvppCommon_(dvppCommon),
processedInfo_(nullptr) {}
MDAclProcess::MDAclProcess(uint32_t ParaWidth, uint32_t ParaHeight, aclrtContext context, bool is_crop,
aclrtStream stream, std::shared_ptr<DvppCommon> dvppCommon)
: contain_crop_(is_crop), context_(context), stream_(stream), dvppCommon_(dvppCommon), processedInfo_(nullptr) {
if (is_crop) {
resizeWidth_ = 0;
resizeHeight_ = 0;
cropWidth_ = ParaWidth;
cropHeight_ = ParaHeight;
} else {
resizeWidth_ = ParaWidth;
resizeHeight_ = ParaHeight;
cropWidth_ = 0;
cropHeight_ = 0;
}
}
MDAclProcess::MDAclProcess(aclrtContext context, bool is_crop, aclrtStream stream,
std::shared_ptr<DvppCommon> dvppCommon)
: resizeWidth_(0),
resizeHeight_(0),
cropWidth_(0),
cropHeight_(0),
contain_crop_(is_crop),
context_(context),
stream_(stream),
dvppCommon_(dvppCommon),
processedInfo_(nullptr) {}
/*
* @description: Release MDAclProcess resources
* @return: aclError which is error code of ACL API
*/
APP_ERROR MDAclProcess::Release() {
// Release objects resource
APP_ERROR ret = dvppCommon_->DeInit();
dvppCommon_->ReleaseDvppBuffer();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to deinitialize dvppCommon_, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "dvppCommon_ object deinitialized successfully";
dvppCommon_.reset();
// Release stream
if (stream_ != nullptr) {
ret = aclrtDestroyStream(stream_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to destroy stream, ret = " << ret;
stream_ = nullptr;
return ret;
}
stream_ = nullptr;
}
MS_LOG(INFO) << "The stream is destroyed successfully";
return APP_ERR_OK;
}
/*
* @description: Initialize DvppCommon object
* @return: aclError which is error code of ACL API
*/
APP_ERROR MDAclProcess::InitModule() {
// Create Dvpp JpegD object
dvppCommon_ = std::make_shared<DvppCommon>(stream_);
if (dvppCommon_ == nullptr) {
MS_LOG(ERROR) << "Failed to create dvppCommon_ object";
return APP_ERR_COMM_INIT_FAIL;
}
MS_LOG(INFO) << "DvppCommon object created successfully";
APP_ERROR ret = dvppCommon_->Init();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to initialize dvppCommon_ object, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "DvppCommon object initialized successfully";
return APP_ERR_OK;
}
/*
* @description: Initialize MDAclProcess resources
* @return: aclError which is error code of ACL API
*/
APP_ERROR MDAclProcess::InitResource() {
APP_ERROR ret = aclrtSetCurrentContext(context_);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to get ACL context, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "The context is created successfully";
ret = aclrtCreateStream(&stream_); // Create stream for application
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to create ACL stream, ret = " << ret;
return ret;
}
MS_LOG(INFO) << "The stream is created successfully";
// Initialize dvpp module
if (InitModule() != APP_ERR_OK) {
return APP_ERR_COMM_INIT_FAIL;
}
return APP_ERR_OK;
}
std::shared_ptr<DvppCommon> MDAclProcess::GetDeviceModule() { return dvppCommon_; }
/*
* Sink data from Tensor(On host) to DeviceTensor(On device)
* Two cases are different, jpeg and png
*/
APP_ERROR MDAclProcess::H2D_Sink(std::shared_ptr<mindspore::dataset::Tensor> &input,
std::shared_ptr<mindspore::dataset::DeviceTensor> &device_input) {
RawData imageinfo;
uint32_t filesize = input->SizeInBytes();
// MS_LOG(INFO) << "Filesize on host is: " << filesize;
imageinfo.lenOfByte = filesize;
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
imageinfo.data = static_cast<void *>(buffer);
// Transfer RawData(Raw image) from host to device, which we call sink
APP_ERROR ret;
if (IsNonEmptyJPEG(input)) { // case JPEG
ret = dvppCommon_->SinkImageH2D(imageinfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420);
} else { // case PNG
ret = dvppCommon_->SinkImageH2D(imageinfo);
}
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to transport Tensor to device, ret = " << ret;
return ret;
}
auto deviceInputData = dvppCommon_->GetInputImage();
// std::cout << "[DEBUG]Sink data sunccessfully, Filesize on device is: " << deviceInputData->dataSize << std::endl;
const mindspore::dataset::DataType dvpp_data_type(mindspore::dataset::DataType::DE_UINT8);
const mindspore::dataset::TensorShape dvpp_shape({1, 1, 1});
mindspore::dataset::DeviceTensor::CreateEmpty(dvpp_shape, dvpp_data_type, &device_input);
device_input->SetAttributes(deviceInputData);
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::D2H_Pop(std::shared_ptr<mindspore::dataset::DeviceTensor> &device_output,
std::shared_ptr<mindspore::dataset::Tensor> &output) {
void *resHostBuf = nullptr;
APP_ERROR ret = aclrtMallocHost(&resHostBuf, device_output->DeviceDataSize());
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), device_output->DeviceDataSize(), device_output->GetDeviceBuffer(),
device_output->DeviceDataSize(), ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
auto data = std::static_pointer_cast<unsigned char>(processedInfo_);
unsigned char *ret_ptr = data.get();
mindspore::dataset::dsize_t dvppDataSize = device_output->DeviceDataSize();
const mindspore::dataset::TensorShape dvpp_shape({dvppDataSize, 1, 1});
uint32_t _output_width_ = device_output->GetYuvStrideShape()[0];
uint32_t _output_widthStride_ = device_output->GetYuvStrideShape()[1];
uint32_t _output_height_ = device_output->GetYuvStrideShape()[2];
uint32_t _output_heightStride_ = device_output->GetYuvStrideShape()[3];
const mindspore::dataset::DataType dvpp_data_type(mindspore::dataset::DataType::DE_UINT8);
mindspore::dataset::Tensor::CreateFromMemory(dvpp_shape, dvpp_data_type, ret_ptr, &output);
output->SetYuvShape(_output_width_, _output_widthStride_, _output_height_, _output_heightStride_);
if (!output->HasData()) {
return APP_ERR_COMM_ALLOC_MEM;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_D(const RawData &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_D_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> DecodeOutData = dvppCommon_->GetDecodedImage();
if (!DecodeOutData) {
MS_LOG(ERROR) << "Decode Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, DecodeOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), DecodeOutData->dataSize, DecodeOutData->data, DecodeOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_D() {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_D_();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> DecodeOutData = dvppCommon_->GetDecodedImage();
if (!DecodeOutData) {
MS_LOG(ERROR) << "Decode Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_D_(const RawData &ImageInfo) {
APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_D_() {
auto input_ = dvppCommon_->GetInputImage();
auto decode_output_ = dvppCommon_->GetDecodedImage();
APP_ERROR ret = dvppCommon_->SinkCombineJpegdProcess(input_, decode_output_, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_R(const DvppDataInfo &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_R_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to resize, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp resize Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> ResizeOutData = dvppCommon_->GetResizedImage();
if (!ResizeOutData) {
MS_LOG(ERROR) << "Resize Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, ResizeOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), ResizeOutData->dataSize, ResizeOutData->data, ResizeOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_R(std::string &last_step) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_R_(last_step);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to resize, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp resize Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> ResizeOutData = dvppCommon_->GetResizedImage();
if (!ResizeOutData) {
MS_LOG(ERROR) << "Resize Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_R_(const DvppDataInfo &ImageInfo) {
APP_ERROR ret = dvppCommon_->TransferYuvDataH2D(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy data from host to device, ret = " << ret << ".";
return ret;
}
std::shared_ptr<DvppDataInfo> decoded_image = dvppCommon_->GetDecodedImage();
uint32_t pri_h = decoded_image->heightStride;
uint32_t pri_w = decoded_image->widthStride;
// Define the resize shape
DvppDataInfo resizeOut;
ResizeConfigFilter(resizeOut, pri_w, pri_h);
ret = dvppCommon_->CombineResizeProcess(*decoded_image, resizeOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_R_(std::string &last_step) {
std::shared_ptr<DvppDataInfo> input_image = std::make_shared<DvppDataInfo>();
if (last_step == "Decode") {
input_image = dvppCommon_->GetDecodedImage();
} else {
input_image = dvppCommon_->GetCropedImage();
}
if (!input_image->data) {
MS_LOG(ERROR) << "Failed to get data for resize, please verify last step operation";
return APP_ERR_DVPP_RESIZE_FAIL;
}
uint32_t pri_h = input_image->heightStride;
uint32_t pri_w = input_image->widthStride;
DvppDataInfo resizeOut;
ResizeConfigFilter(resizeOut, pri_w, pri_h);
APP_ERROR ret = dvppCommon_->CombineResizeProcess(*input_image, resizeOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_C(const DvppDataInfo &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_C_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to crop image, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp crop Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> CropOutData = dvppCommon_->GetCropedImage();
if (!CropOutData) {
MS_LOG(ERROR) << "Crop Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_C(std::string &last_step) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_C_(last_step);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to crop image, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp crop Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> CropOutData = dvppCommon_->GetCropedImage();
if (!CropOutData) {
MS_LOG(ERROR) << "Crop Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_C_(const DvppDataInfo &ImageInfo) {
APP_ERROR ret = dvppCommon_->TransferYuvDataH2D(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy data from host to device, ret = " << ret << ".";
return ret;
}
// Unneccessary to be image after resize, maybe after decode, we store both of them in DecodedImage()
std::shared_ptr<DvppDataInfo> resized_image = dvppCommon_->GetDecodedImage();
uint32_t pri_h = resized_image->heightStride;
uint32_t pri_w = resized_image->widthStride;
// Validate the crop shape
DvppDataInfo cropOut;
cropOut.width = cropWidth_;
cropOut.height = cropHeight_;
if (cropOut.width > pri_w || cropOut.height > pri_h) {
MS_LOG(ERROR) << "Crop size can not excceed resize, please verify your input [CROP SIZE] parameters";
return APP_ERR_COMM_INVALID_PARAM;
}
cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
DvppCropInputInfo cropInfo;
cropInfo.dataInfo = *resized_image;
// Define crop area
CropRoiConfig cropCfg;
CropConfigFilter(cropCfg, cropInfo, *resized_image);
ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_C_(std::string &last_step) {
std::shared_ptr<DvppDataInfo> input_image = std::make_shared<DvppDataInfo>();
if (last_step == "Resize") {
input_image = dvppCommon_->GetResizedImage();
} else {
input_image = dvppCommon_->GetDecodedImage();
}
if (!input_image->data) {
MS_LOG(ERROR) << "Failed to get input data for crop, please verify last step operation";
return APP_ERR_DVPP_CROP_FAIL;
}
uint32_t pri_h = input_image->heightStride;
uint32_t pri_w = input_image->widthStride;
DvppDataInfo cropOut;
cropOut.width = cropWidth_;
cropOut.height = cropHeight_;
if (cropOut.width > pri_w || cropOut.height > pri_h) {
MS_LOG(ERROR) << "Crop size can not excceed resize, please verify your input [CROP SIZE] parameters";
return APP_ERR_COMM_INVALID_PARAM;
}
cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
DvppCropInputInfo cropInfo;
cropInfo.dataInfo = *input_image;
// Define crop area
CropRoiConfig cropCfg;
CropConfigFilter(cropCfg, cropInfo, *input_image);
APP_ERROR ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::PNG_D(const RawData &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = PNG_D_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> DecodeOutData = dvppCommon_->GetDecodedImage();
if (!DecodeOutData) {
MS_LOG(ERROR) << "ResizedOutData returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, DecodeOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), DecodeOutData->dataSize, DecodeOutData->data, DecodeOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::PNG_D() {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = PNG_D_();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp decode Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> DecodeOutData = dvppCommon_->GetDecodedImage();
if (!DecodeOutData) {
MS_LOG(ERROR) << "Decode Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::PNG_D_(const RawData &ImageInfo) {
APP_ERROR ret = dvppCommon_->CombinePngdProcess(ImageInfo, PIXEL_FORMAT_RGB_888, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::PNG_D_() {
auto input_ = dvppCommon_->GetInputImage();
auto decode_output_ = dvppCommon_->GetDecodedImage();
APP_ERROR ret = dvppCommon_->SinkCombinePngdProcess(input_, decode_output_, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
/*
* @description: Decode and scale the picture, and write the result to a file
* @param: imageFile specifies the image path to be processed
* @return: aclError which is error code of ACL API
*/
APP_ERROR MDAclProcess::JPEG_DRC(const RawData &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_DRC_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode or resize or crop, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
/* 测试Device内存
*/
std::shared_ptr<DvppDataInfo> CropOutData = dvppCommon_->GetCropedImage();
if (CropOutData->dataSize == 0) {
MS_LOG(ERROR) << "CropOutData return NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, CropOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), CropOutData->dataSize, CropOutData->data, CropOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_DRC() {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_D_();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
std::string last_step = "Decode";
ret = JPEG_R_(last_step);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to resize, ret = " << ret;
return ret;
}
last_step = "Resize";
ret = JPEG_C_(last_step);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to crop, ret = " << ret;
return ret;
}
// Get output of crop module
std::shared_ptr<DvppDataInfo> CropOutData = dvppCommon_->GetCropedImage();
if (!CropOutData) {
MS_LOG(ERROR) << "Decode Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp (Decode + Resize + Crop) Delay] cost: " << costMs << "ms\tfps: " << fps;
return APP_ERR_OK;
}
/*
* @description: Read image files, and perform decoding and scaling
* @param: imageFile specifies the image path to be processed
* @return: aclError which is error code of ACL API
*/
APP_ERROR MDAclProcess::JPEG_DRC_(const RawData &ImageInfo) {
// Decode process
APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
// Get output of decoded jpeg image, decodeOutData locates on device
std::shared_ptr<DvppDataInfo> decodeOutData = dvppCommon_->GetDecodedImage();
if (decodeOutData == nullptr) {
MS_LOG(ERROR) << "Decode output buffer is null.";
return APP_ERR_COMM_INVALID_POINTER;
}
uint32_t pri_h = decodeOutData->heightStride;
uint32_t pri_w = decodeOutData->widthStride;
// Define output of resize jpeg image
DvppDataInfo resizeOut;
ResizeConfigFilter(resizeOut, pri_w, pri_h);
// Run resize application function
ret = dvppCommon_->CombineResizeProcess(*decodeOutData, resizeOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << ".";
return ret;
}
// Get output of resize jpeg image, resizeOutData locates on device
std::shared_ptr<DvppDataInfo> resizeOutData = dvppCommon_->GetResizedImage();
if (resizeOutData == nullptr) {
MS_LOG(ERROR) << "resize output buffer is null.";
return APP_ERR_COMM_INVALID_POINTER;
}
// Define output of crop jpeg image
DvppDataInfo cropOut;
cropOut.width = cropWidth_;
cropOut.height = cropHeight_;
cropOut.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
// Define input of crop jpeg image
DvppCropInputInfo cropInfo;
cropInfo.dataInfo = *resizeOutData;
// Define crop area
CropRoiConfig cropCfg;
CropConfigFilter(cropCfg, cropInfo, resizeOut);
ret = dvppCommon_->CombineCropProcess(cropInfo, cropOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process center crop, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_DR(const RawData &ImageInfo) {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_DR_(ImageInfo);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode or resize, ret = " << ret;
return ret;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp Delay] cost: " << costMs << "ms\tfps: " << fps;
// Get output of resize module
std::shared_ptr<DvppDataInfo> ResizeOutData = dvppCommon_->GetResizedImage();
if (!ResizeOutData) {
MS_LOG(ERROR) << "ResizedOutData returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
// Alloc host memory for the inference output according to the size of output
void *resHostBuf = nullptr;
ret = aclrtMallocHost(&resHostBuf, ResizeOutData->dataSize);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to allocate memory from host ret = " << ret;
return ret;
}
std::shared_ptr<void> outBuf(resHostBuf, aclrtFreeHost);
processedInfo_ = outBuf;
// Memcpy the output data from device to host
ret = aclrtMemcpy(outBuf.get(), ResizeOutData->dataSize, ResizeOutData->data, ResizeOutData->dataSize,
ACL_MEMCPY_DEVICE_TO_HOST);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to copy memory from device to host, ret = " << ret;
return ret;
}
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_DR() {
struct timeval begin = {0};
struct timeval end = {0};
gettimeofday(&begin, nullptr);
// deal with image
APP_ERROR ret = JPEG_D_();
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to decode, ret = " << ret;
return ret;
}
std::string last_step = "Decode";
ret = JPEG_R_(last_step);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to resize, ret = " << ret;
return ret;
}
// Get output of resize module
std::shared_ptr<DvppDataInfo> ResizeOutData = dvppCommon_->GetResizedImage();
if (!ResizeOutData) {
MS_LOG(ERROR) << "Decode Data returns NULL";
return APP_ERR_COMM_INVALID_POINTER;
}
gettimeofday(&end, nullptr);
// Calculate the time cost of preprocess
const double costMs = SEC2MS * (end.tv_sec - begin.tv_sec) + (end.tv_usec - begin.tv_usec) / SEC2MS;
const double fps = 1 * SEC2MS / costMs;
MS_LOG(INFO) << "[dvpp (Decode + Resize) Delay] cost: " << costMs << "ms\tfps: " << fps;
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::JPEG_DR_(const RawData &ImageInfo) {
// Decode process
APP_ERROR ret = dvppCommon_->CombineJpegdProcess(ImageInfo, PIXEL_FORMAT_YUV_SEMIPLANAR_420, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process decode, ret = " << ret << ".";
return ret;
}
// Get output of decoded jpeg image
std::shared_ptr<DvppDataInfo> decodeOutData = dvppCommon_->GetDecodedImage();
if (decodeOutData == nullptr) {
MS_LOG(ERROR) << "Decode output buffer is null.";
return APP_ERR_COMM_INVALID_POINTER;
}
// Define output of resize jpeg image
uint32_t pri_h = decodeOutData->heightStride;
uint32_t pri_w = decodeOutData->widthStride;
DvppDataInfo resizeOut;
ResizeConfigFilter(resizeOut, pri_w, pri_h);
// Run resize application function
ret = dvppCommon_->CombineResizeProcess(*decodeOutData, resizeOut, true);
if (ret != APP_ERR_OK) {
MS_LOG(ERROR) << "Failed to process resize, ret = " << ret << ".";
return ret;
}
return APP_ERR_OK;
}
void MDAclProcess::CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo, DvppDataInfo &resizeinfo) {
if (resizeHeight_ != 0) {
cfg.up = (resizeHeight_ - cropHeight_) / 2;
if (cfg.up % 2 != 0) {
cfg.up++;
}
cfg.down = resizeHeight_ - (resizeHeight_ - cropHeight_) / 2;
if (cfg.down % 2 == 0) {
cfg.down--;
}
} else {
cfg.up = (resizeinfo.height - cropHeight_) / 2;
if (cfg.up % 2 != 0) {
cfg.up++;
}
cfg.down = resizeinfo.height - (resizeinfo.height - cropHeight_) / 2;
if (cfg.down % 2 == 0) {
cfg.down--;
}
}
if (resizeWidth_ != 0) {
cfg.left = (resizeWidth_ - cropWidth_) / 2;
if (cfg.left % 2 != 0) {
cfg.left++;
}
cfg.right = resizeWidth_ - (resizeWidth_ - cropWidth_) / 2;
if (cfg.right % 2 == 0) {
cfg.right--;
}
} else {
cfg.left = (resizeinfo.width - cropWidth_) / 2;
if (cfg.left % 2 != 0) {
cfg.left++;
}
cfg.right = resizeinfo.width - (resizeinfo.width - cropWidth_) / 2;
if (cfg.right % 2 == 0) {
cfg.right--;
}
}
cropinfo.roi = cfg;
}
APP_ERROR MDAclProcess::ResizeConfigFilter(DvppDataInfo &resizeinfo, const uint32_t pri_w_, const uint32_t pri_h_) {
if (resizeWidth_ != 0) { // 如果输入参数个数为2按指定参数缩放
resizeinfo.width = resizeWidth_;
resizeinfo.widthStride = DVPP_ALIGN_UP(resizeWidth_, VPC_STRIDE_WIDTH);
resizeinfo.height = resizeHeight_;
resizeinfo.heightStride = DVPP_ALIGN_UP(resizeHeight_, VPC_STRIDE_HEIGHT);
} else { // 如果输入参数个数为1保持原图片比例缩放
if (pri_h_ >= pri_w_) {
resizeinfo.width = resizeHeight_; // 若输入参数个数为1则只有resizeHeight_有值
resizeinfo.widthStride = DVPP_ALIGN_UP(resizeinfo.width, VPC_STRIDE_WIDTH);
resizeinfo.height = uint32_t(resizeHeight_ * pri_h_ / pri_w_);
resizeinfo.heightStride = DVPP_ALIGN_UP(resizeinfo.height, VPC_STRIDE_HEIGHT);
} else {
resizeinfo.width = uint32_t(resizeHeight_ * pri_w_ / pri_h_);
resizeinfo.widthStride = DVPP_ALIGN_UP(resizeinfo.width, VPC_STRIDE_WIDTH);
resizeinfo.height = resizeHeight_;
resizeinfo.heightStride = DVPP_ALIGN_UP(resizeinfo.height, VPC_STRIDE_HEIGHT);
}
}
resizeinfo.format = PIXEL_FORMAT_YUV_SEMIPLANAR_420;
return APP_ERR_OK;
}
/*
* @description: Obtain result data of memory
* @param: processed_data is result data info pointer
* @return: Address of data in the memory
*/
std::shared_ptr<void> MDAclProcess::Get_Memory_Data() { return processedInfo_; }
std::shared_ptr<DvppDataInfo> MDAclProcess::Get_Croped_DeviceData() { return dvppCommon_->GetCropedImage(); }
std::shared_ptr<DvppDataInfo> MDAclProcess::Get_Resized_DeviceData() { return dvppCommon_->GetResizedImage(); }
std::shared_ptr<DvppDataInfo> MDAclProcess::Get_Decode_DeviceData() { return dvppCommon_->GetDecodedImage(); }
APP_ERROR MDAclProcess::SetResizeParas(uint32_t width, uint32_t height) {
resizeWidth_ = width;
resizeHeight_ = height;
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::SetCropParas(uint32_t width, uint32_t height) {
cropWidth_ = width;
cropHeight_ = height;
return APP_ERR_OK;
}
APP_ERROR MDAclProcess::device_memory_release() {
dvppCommon_->ReleaseDvppBuffer();
MS_LOG(INFO) << "Device memory release successfully";
return APP_ERR_OK;
}
std::vector<uint32_t> MDAclProcess::Get_Primary_Shape() {
std::vector<uint32_t> pri_shape;
if (!dvppCommon_) {
pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->heightStride);
pri_shape.emplace_back(dvppCommon_->GetDecodedImage()->widthStride);
}
return pri_shape;
}

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2020.Huawei Technologies Co., Ltd. All rights reserved.
* 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 MDACLMANAGER_H
#define MDACLMANAGER_H
#include <climits>
#include <string>
#include <string.h>
#include <map>
#include <iostream>
#include <memory>
#include "acl/acl.h"
#include "CommonDataType.h"
#include "minddata/dataset/core/tensor_shape.h"
#include "minddata/dataset/core/data_type.h"
#include "mindspore/ccsrc/minddata/dataset/core/device_tensor.h"
#include "mindspore/ccsrc/minddata/dataset/core/tensor.h"
#include "mindspore/core/utils/log_adapter.h"
#include "mindspore/ccsrc/minddata/dataset/util/status.h"
#include "ErrorCode.h"
#include "DvppCommon.h"
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
mode_t SetFileDefaultUmask();
class MDAclProcess {
public:
MDAclProcess(uint32_t resizeWidth, uint32_t resizeHeight, uint32_t cropWidth, uint32_t cropHeight,
aclrtContext context, bool is_crop = true, aclrtStream stream = nullptr,
std::shared_ptr<DvppCommon> dvppCommon = nullptr);
MDAclProcess(uint32_t ParaWidth, uint32_t ParaHeight, aclrtContext context, bool is_crop = false,
aclrtStream stream = nullptr, std::shared_ptr<DvppCommon> dvppCommon = nullptr);
MDAclProcess(aclrtContext context, bool is_crop = false, aclrtStream stream = nullptr,
std::shared_ptr<DvppCommon> dvppCommon = nullptr);
~MDAclProcess(){};
// Release all the resource
APP_ERROR Release();
// Create resource for this sample
APP_ERROR InitResource();
// Process the result
APP_ERROR JPEG_DRC(const RawData &ImageInfo);
APP_ERROR JPEG_DRC();
// Procss the image without crop
APP_ERROR JPEG_DR(const RawData &ImageInfo);
APP_ERROR JPEG_DR();
// Process the JPEG image only with decode
APP_ERROR JPEG_D(const RawData &ImageInfo);
APP_ERROR JPEG_D();
// Process the JPEG image only with resize
APP_ERROR JPEG_R(const DvppDataInfo &ImageInfo);
APP_ERROR JPEG_R(std::string &last_step);
// Process the JPEG image only with crop
APP_ERROR JPEG_C(const DvppDataInfo &ImageInfo);
APP_ERROR JPEG_C(std::string &last_step);
// Process the PNG image only with decode
APP_ERROR PNG_D(const RawData &ImageInfo);
APP_ERROR PNG_D();
// API for access memory
std::shared_ptr<void> Get_Memory_Data();
// API for access device memory of croped data
std::shared_ptr<DvppDataInfo> Get_Croped_DeviceData();
// API for access device memory of resized data
std::shared_ptr<DvppDataInfo> Get_Resized_DeviceData();
// API for access device memory of decode data
std::shared_ptr<DvppDataInfo> Get_Decode_DeviceData();
APP_ERROR H2D_Sink(std::shared_ptr<mindspore::dataset::Tensor> &input,
std::shared_ptr<mindspore::dataset::DeviceTensor> &device_input);
APP_ERROR D2H_Pop(std::shared_ptr<mindspore::dataset::DeviceTensor> &device_output,
std::shared_ptr<mindspore::dataset::Tensor> &output);
// D-chip memory release
APP_ERROR device_memory_release();
std::shared_ptr<DvppCommon> GetDeviceModule();
std::vector<uint32_t> Get_Primary_Shape();
// Set Dvpp parameters
APP_ERROR SetResizeParas(uint32_t width, uint32_t height);
APP_ERROR SetCropParas(uint32_t width, uint32_t height);
private:
// Crop definition
void CropConfigFilter(CropRoiConfig &cfg, DvppCropInputInfo &cropinfo, DvppDataInfo &resizeinfo);
// Resize definition
APP_ERROR ResizeConfigFilter(DvppDataInfo &resizeinfo, const uint32_t pri_w_, const uint32_t pri_h_);
// Initialize DVPP modules used by this sample
APP_ERROR InitModule();
// Dvpp process with crop
APP_ERROR JPEG_DRC_(const RawData &ImageInfo);
// Dvpp process without crop
APP_ERROR JPEG_DR_(const RawData &ImageInfo);
// Impl of JPEG_D
APP_ERROR JPEG_D_(const RawData &ImageInfo);
APP_ERROR JPEG_D_();
// Impl of JPEG_R
APP_ERROR JPEG_R_(const DvppDataInfo &ImageInfo);
APP_ERROR JPEG_R_(std::string &last_step);
// Impl of JPEG_C
APP_ERROR JPEG_C_(const DvppDataInfo &ImageInfo);
APP_ERROR JPEG_C_(std::string &last_step);
// Impl of PNG_D
APP_ERROR PNG_D_(const RawData &ImageInfo);
APP_ERROR PNG_D_();
aclrtContext context_;
aclrtStream stream_;
std::shared_ptr<DvppCommon> dvppCommon_; // dvpp object
std::shared_ptr<void> processedInfo_; // processed data (On host)
uint32_t resizeWidth_; // dvpp resize width
uint32_t resizeHeight_; // dvpp resize height
uint32_t cropWidth_; // dvpp crop width
uint32_t cropHeight_; // dvpp crop height
bool contain_crop_; // Initialize with crop or not
};
#endif

View File

@ -29,15 +29,15 @@ std::shared_ptr<ResourceManager> ResourceManager::ptr_ = nullptr;
*/
APP_ERROR ExistFile(const std::string &filePath) {
struct stat fileSat = {0};
char c[PATH_MAX_ASCEND + 1] = {0x00};
size_t count = filePath.copy(c, PATH_MAX_ASCEND + 1);
char c[PATH_MAX + 1] = {0x00};
size_t count = filePath.copy(c, PATH_MAX + 1);
if (count != filePath.length()) {
MS_LOG(ERROR) << "Failed to strcpy" << c;
return APP_ERR_COMM_FAILURE;
}
// Get the absolute path of input directory
char path[PATH_MAX_ASCEND + 1] = {0x00};
if ((strlen(c) > PATH_MAX_ASCEND) || (realpath(c, path) == nullptr)) {
char path[PATH_MAX + 1] = {0x00};
if ((strlen(c) > PATH_MAX) || (realpath(c, path) == nullptr)) {
MS_LOG(ERROR) << "Failed to get canonicalize path";
return APP_ERR_COMM_EXIST;
}
@ -85,7 +85,6 @@ APP_ERROR ResourceManager::InitResource(ResourceInfo &resourceInfo) {
MS_LOG(INFO) << "Acl has been initialized, skip.";
return APP_ERR_OK;
}
std::string &aclConfigPath = resourceInfo.aclConfigPath;
APP_ERROR ret;
if (aclConfigPath.length() == 0) {

View File

@ -16,20 +16,18 @@
#ifndef RESOURCEMANAGER_H
#define RESOURCEMANAGER_H
#include <sys/stat.h>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <unordered_map>
#include <memory>
#include <mutex>
#include "CommonDataType.h"
#include "ErrorCode.h"
#include <sys/stat.h>
#include "mindspore/core/utils/log_adapter.h"
#include "mindspore/ccsrc/cxx_api/graph/acl/acl_env_guard.h"
#define PATH_MAX_ASCEND 4096
#define PATH_MAX 4096
enum ModelLoadMethod {
LOAD_FROM_FILE = 0, // Loading from file, memory of model and weights are managed by ACL
@ -63,10 +61,12 @@ struct ResourceInfo {
APP_ERROR ExistFile(const std::string &filePath);
class ResourceManager {
public:
ResourceManager() {}
friend APP_ERROR ExistFile(const std::string &filePath);
~ResourceManager() {}
public:
ResourceManager(){};
~ResourceManager(){};
// Get the Instance of resource manager
static std::shared_ptr<ResourceManager> GetInstance();
@ -89,4 +89,4 @@ class ResourceManager {
std::shared_ptr<mindspore::AclEnvGuard> acl_env_;
};
#endif
#endif

View File

@ -142,6 +142,12 @@ bool IsNonEmptyJPEG(const std::shared_ptr<Tensor> &input) {
return input->SizeInBytes() > kJpegMagicLen && memcmp(input->GetBuffer(), kJpegMagic, kJpegMagicLen) == 0;
}
bool IsNonEmptyPNG(const std::shared_ptr<Tensor> &input) {
const unsigned char *kPngMagic = (unsigned char *)"\x89\x50\x4E\x47";
constexpr size_t kPngMagicLen = 4;
return input->SizeInBytes() > kPngMagicLen && memcmp(input->GetBuffer(), kPngMagic, kPngMagicLen) == 0;
}
Status Decode(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) {
if (IsNonEmptyJPEG(input)) {
return JpegCropAndDecode(input, output);
@ -953,7 +959,7 @@ Status Erase(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *outp
RETURN_STATUS_UNEXPECTED("CutOut: load image failed.");
}
if (input_cv->Rank() != 3 || num_channels != 3) {
RETURN_STATUS_UNEXPECTED("CutOut: image shape is not <H,W,C>.");
RETURN_STATUS_UNEXPECTED("CutOut: image shape is not <H,W,C> or <H,W>.");
}
cv::Mat input_img = input_cv->mat();
int32_t image_h = input_cv->shape()[0];

View File

@ -103,6 +103,8 @@ Status DecodeCv(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *o
bool IsNonEmptyJPEG(const std::shared_ptr<Tensor> &input);
bool IsNonEmptyPNG(const std::shared_ptr<Tensor> &input);
void JpegSetSource(j_decompress_ptr c_info, const void *data, int64_t data_size);
Status JpegCropAndDecode(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output, int x = 0, int y = 0,

View File

@ -32,9 +32,6 @@
#include "minddata/dataset/kernels/image/cut_out_op.h"
#endif
#include "minddata/dataset/kernels/image/decode_op.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_resize_crop_jpeg_op.h"
#endif
#ifndef ENABLE_ANDROID
#include "minddata/dataset/kernels/image/equalize_op.h"
#include "minddata/dataset/kernels/image/hwc_to_chw_op.h"
@ -305,102 +302,6 @@ Status MixUpBatchOperation::to_json(nlohmann::json *out_json) {
#endif
#ifdef ENABLE_ACL
// DvppDecodeResizeCropOperation
DvppDecodeResizeCropOperation::DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop,
const std::vector<uint32_t> &resize)
: crop_(crop), resize_(resize) {}
Status DvppDecodeResizeCropOperation::ValidateParams() {
// size
if (crop_.empty() || crop_.size() > 2) {
std::string err_msg = "DvppDecodeResizeCropJpeg: crop resolution must be a vector of one or two elements, got: " +
std::to_string(crop_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (resize_.empty() || resize_.size() > 2) {
std::string err_msg = "DvppDecodeResizeCropJpeg: resize resolution must be a vector of one or two elements, got: " +
std::to_string(resize_.size());
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(crop_.begin(), crop_.end()) < 32 || *max_element(crop_.begin(), crop_.end()) > 2048) {
std::string err_msg = "Dvpp module supports crop image with resolution in range [32, 2048], got Crop Parameters: ";
if (crop_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << crop_[0] << ", " << crop_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (*min_element(resize_.begin(), resize_.end()) < 32 || *max_element(resize_.begin(), resize_.end()) > 2048) {
std::string err_msg =
"Dvpp module supports resize image with resolution in range [32, 2048], got Crop Parameters: ";
if (resize_.size() == 2) {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[1] << "]";
} else {
MS_LOG(ERROR) << err_msg << "[" << resize_[0] << ", " << resize_[0] << "]";
}
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
if (crop_.size() < resize_.size()) {
if (crop_[0] > MIN(resize_[0], resize_[1])) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
if (crop_.size() > resize_.size()) {
if (MAX(crop_[0], crop_[1]) > resize_[0]) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
if (crop_.size() == resize_.size()) {
for (int32_t i = 0; i < crop_.size(); ++i) {
if (crop_[i] > resize_[i]) {
std::string err_msg =
"Each value of crop parameter must be smaller than corresponding resize parameter, for example: x[0] <= "
"y[0], and x[1] <= y[1], please verify your input parameters.";
MS_LOG(ERROR) << err_msg;
RETURN_STATUS_SYNTAX_ERROR(err_msg);
}
}
}
return Status::OK();
}
std::shared_ptr<TensorOp> DvppDecodeResizeCropOperation::Build() {
// If size is a single value, the smaller edge of the image will be
// resized to this value with the same image aspect ratio.
uint32_t cropHeight, cropWidth, resizeHeight, resizeWidth;
if (crop_.size() == 1) {
cropHeight = crop_[0];
cropWidth = crop_[0];
} else {
cropHeight = crop_[0];
cropWidth = crop_[1];
}
// User specified the width value.
if (resize_.size() == 1) {
resizeHeight = resize_[0];
resizeWidth = resize_[0];
} else {
resizeHeight = resize_[0];
resizeWidth = resize_[1];
}
std::shared_ptr<DvppDecodeResizeCropJpegOp> tensor_op =
std::make_shared<DvppDecodeResizeCropJpegOp>(cropHeight, cropWidth, resizeHeight, resizeWidth);
return tensor_op;
}
#endif
// NormalizeOperation
NormalizeOperation::NormalizeOperation(std::vector<float> mean, std::vector<float> std) : mean_(mean), std_(std) {}

View File

@ -42,7 +42,6 @@ constexpr char kCropOperation[] = "Crop";
constexpr char kCutMixBatchOperation[] = "CutMixBatch";
constexpr char kCutOutOperation[] = "CutOut";
constexpr char kDecodeOperation[] = "Decode";
constexpr char kDvppDecodeResizeCropOperation[] = "DvppDecodeResizeCrop";
constexpr char kEqualizeOperation[] = "Equalize";
constexpr char kHwcToChwOperation[] = "HwcToChw";
constexpr char kInvertOperation[] = "Invert";
@ -88,7 +87,6 @@ class CropOperation;
class CutMixBatchOperation;
class CutOutOperation;
class DecodeOperation;
class DvppDecodeResizeCropOperation;
class EqualizeOperation;
class HwcToChwOperation;
class InvertOperation;
@ -258,23 +256,6 @@ class DecodeOperation : public TensorOperation {
bool rgb_;
};
class DvppDecodeResizeCropOperation : public TensorOperation {
public:
explicit DvppDecodeResizeCropOperation(const std::vector<uint32_t> &crop, const std::vector<uint32_t> &resize);
~DvppDecodeResizeCropOperation() = default;
std::shared_ptr<TensorOp> Build() override;
Status ValidateParams() override;
std::string Name() const override { return kDvppDecodeResizeCropOperation; }
private:
std::vector<uint32_t> crop_;
std::vector<uint32_t> resize_;
};
class EqualizeOperation : public TensorOperation {
public:
~EqualizeOperation() = default;

View File

@ -48,6 +48,13 @@ Status TensorOp::Compute(const TensorRow &input, TensorRow *output) {
"Is this TensorOp oneToOne? If no, please implement this Compute() in the derived class.");
}
Status TensorOp::Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output) {
IO_CHECK(input, output);
return Status(StatusCode::kMDUnexpectedError,
"Wrong Compute() function is called. This is a function for operators which can be executed by"
"different device. If so, please implement it in the derived class.");
}
Status TensorOp::OutputShape(const std::vector<TensorShape> &inputs, std::vector<TensorShape> &outputs) {
if (inputs.size() != NumInput())
return Status(StatusCode::kMDUnexpectedError,
@ -63,5 +70,11 @@ Status TensorOp::OutputType(const std::vector<DataType> &inputs, std::vector<Dat
outputs = inputs;
return Status::OK();
}
#ifdef ENABLE_ACL
Status TensorOp::SetAscendResource(const std::shared_ptr<MDAclProcess> &processor) {
return Status(StatusCode::kMDUnexpectedError,
"This is a CPU operator which doesn't have Ascend Resource. Please verify your context");
}
#endif
} // namespace dataset
} // namespace mindspore

View File

@ -24,6 +24,10 @@
#include "minddata/dataset/core/tensor.h"
#include "minddata/dataset/core/tensor_row.h"
#include "minddata/dataset/util/status.h"
#include "minddata/dataset/core/device_tensor.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/kernels/image/dvpp/utils/MDAclProcess.h"
#endif
#define IO_CHECK(input, output) \
do { \
@ -58,7 +62,12 @@ constexpr char kCenterCropOp[] = "CenterCropOp";
constexpr char kCutMixBatchOp[] = "CutMixBatchOp";
constexpr char kCutOutOp[] = "CutOutOp";
constexpr char kCropOp[] = "CropOp";
constexpr char kDvppCropJpegOp[] = "DvppCropJpegOp";
constexpr char kDvppDecodeResizeCropJpegOp[] = "DvppDecodeResizeCropJpegOp";
constexpr char kDvppDecodeResizeJpegOp[] = "DvppDecodeResizeJpegOp";
constexpr char kDvppDecodeJpegOp[] = "DvppDecodeJpegOp";
constexpr char kDvppDecodePngOp[] = "DvppDecodePngOp";
constexpr char kDvppResizeJpegOp[] = "DvppResizeJpegOp";
constexpr char kEqualizeOp[] = "EqualizeOp";
constexpr char kHwcToChwOp[] = "HWC2CHWOp";
constexpr char kInvertOp[] = "InvertOp";
@ -168,6 +177,12 @@ class TensorOp {
// @return Status
virtual Status Compute(const TensorRow &input, TensorRow *output);
// Perform an operation on one DeviceTensor and produce one DeviceTensor. This is for 1-to-1 column MapOp
// @param input shares the ownership of the Tensor (increase the ref count).
// @param output the address to a shared_ptr where the result will be placed.
// @return Status
virtual Status Compute(const std::shared_ptr<DeviceTensor> &input, std::shared_ptr<DeviceTensor> *output);
// Returns true oif the TensorOp takes one input and returns one output.
// @return true/false
bool OneToOne() { return NumInput() == 1 && NumOutput() == 1; }
@ -201,6 +216,9 @@ class TensorOp {
virtual std::string Name() const = 0;
virtual Status to_json(nlohmann::json *out_json) { return Status::OK(); }
#ifdef ENABLE_ACL
virtual Status SetAscendResource(const std::shared_ptr<MDAclProcess> &processor);
#endif
protected:
bool is_deterministic_{true};

View File

@ -7,6 +7,9 @@ include_directories(${CMAKE_SOURCE_DIR}/mindspore/core)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${CUDA_INCLUDE_DIRS})
if(ENABLE_ACL)
add_definitions(-D ENABLE_ACL)
endif()
file(GLOB_RECURSE CXX_ST_SRC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *.cc)
add_executable(st_tests ${CXX_ST_SRC})
target_link_libraries(st_tests PRIVATE mindspore_shared_lib _c_dataengine mindspore::gtest)

View File

@ -19,6 +19,9 @@
#include "include/api/types.h"
#include "minddata/dataset/include/execute.h"
#include "minddata/dataset/include/vision.h"
#ifdef ENABLE_ACL
#include "minddata/dataset/include/vision_ascend.h"
#endif
#include "minddata/dataset/kernels/tensor_op.h"
#include "include/api/model.h"
#include "include/api/serialization.h"
@ -39,10 +42,9 @@ TEST_F(TestDE, TestResNetPreprocess) {
auto image = mindspore::MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define transform operations
mindspore::dataset::Execute Transform({
Decode(), Resize({224, 224}),
Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}),
HWC2CHW()});
mindspore::dataset::Execute Transform(
{Decode(), Resize({224, 224}),
Normalize({0.485 * 255, 0.456 * 255, 0.406 * 255}, {0.229 * 255, 0.224 * 255, 0.225 * 255}), HWC2CHW()});
// Apply transform on images
Status rc = Transform(image, &image);
@ -63,9 +65,9 @@ TEST_F(TestDE, TestDvpp) {
auto image = MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define dvpp transform
std::vector<uint32_t> crop_size = {224, 224};
std::vector<uint32_t> resize_size = {256, 256};
mindspore::dataset::Execute Transform(DvppDecodeResizeCropJpeg(crop_size, resize_size));
std::vector<uint32_t> crop_paras = {224, 224};
std::vector<uint32_t> resize_paras = {256, 256};
mindspore::dataset::Execute Transform(DvppDecodeResizeCropJpeg(crop_paras, resize_paras));
// Apply transform on images
Status rc = Transform(image, &image);
@ -75,16 +77,52 @@ TEST_F(TestDE, TestDvpp) {
ASSERT_EQ(image.Shape().size(), 3);
int32_t real_h = 0;
int32_t real_w = 0;
int32_t remainder = crop_size[crop_size.size() - 1] % 16;
if (crop_size.size() == 1) {
real_h = (crop_size[0] % 2 == 0) ? crop_size[0] : crop_size[0] + 1;
real_w = (remainder == 0) ? crop_size[0] : crop_size[0] + 16 - remainder;
int32_t remainder = crop_paras[crop_paras.size() - 1] % 16;
if (crop_paras.size() == 1) {
real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1;
real_w = (remainder == 0) ? crop_paras[0] : crop_paras[0] + 16 - remainder;
} else {
real_h = (crop_size[0] % 2 == 0) ? crop_size[0] : crop_size[0] + 1;
real_w = (remainder == 0) ? crop_size[1] : crop_size[1] + 16 - remainder;
real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1;
real_w = (remainder == 0) ? crop_paras[1] : crop_paras[1] + 16 - remainder;
}
ASSERT_EQ(image.Shape()[0], real_h * real_w * 1.5); // For image in YUV format, each pixel takes 1.5 byte
ASSERT_EQ(image.Shape()[1], 1);
ASSERT_EQ(image.Shape()[2], 1);
#endif
}
TEST_F(TestDE, TestDvppSinkMode) {
#ifdef ENABLE_ACL
// Read images from target directory
std::shared_ptr<mindspore::dataset::Tensor> de_tensor;
mindspore::dataset::Tensor::CreateFromFile("./data/dataset/apple.jpg", &de_tensor);
auto image = MSTensor(std::make_shared<mindspore::dataset::DETensor>(de_tensor));
// Define dvpp transform
std::vector<uint32_t> crop_paras = {224, 224};
std::vector<uint32_t> resize_paras = {256};
mindspore::dataset::Execute Transform({DvppDecodeJpeg(), DvppResizeJpeg(resize_paras), DvppCropJpeg(crop_paras)},
"Ascend310");
// Apply transform on images
Status rc = Transform(image, &image);
// Check image info
ASSERT_TRUE(rc.IsOk());
ASSERT_EQ(image.Shape().size(), 2);
int32_t real_h = 0;
int32_t real_w = 0;
int32_t remainder = crop_paras[crop_paras.size() - 1] % 16;
if (crop_paras.size() == 1) {
real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1;
real_w = (remainder == 0) ? crop_paras[0] : crop_paras[0] + 16 - remainder;
} else {
real_h = (crop_paras[0] % 2 == 0) ? crop_paras[0] : crop_paras[0] + 1;
real_w = (remainder == 0) ? crop_paras[1] : crop_paras[1] + 16 - remainder;
}
ASSERT_EQ(image.Shape()[0], real_h); // For image in YUV format, each pixel takes 1.5 byte
ASSERT_EQ(image.Shape()[1], real_w);
ASSERT_EQ(image.DataSize(), 1.5 * real_w * real_h);
Transform.DeviceMemoryRelease();
#endif
}

View File

@ -70,6 +70,13 @@ if(ENABLE_MINDDATA)
)
list(REMOVE_ITEM UT_SRCS ${PYTHON_RELATED_SRCS})
endif()
if(NOT ENABLE_ACL)
set(ASCEND310_RELATED_SRCS
dataset/dvpp_decode_jpeg_test.cc
)
list(REMOVE_ITEM UT_SRCS ${ASCEND310_RELATED_SRCS})
endif()
else()
file(GLOB_RECURSE TEMP_UT_SRCS ./*.cc)
foreach(OBJ ${TEMP_UT_SRCS})

View File

@ -149,6 +149,12 @@ if(ENABLE_PYTHON)
)
endif()
if(ENABLE_ACL)
set(DE_UT_SRCS
${DE_UT_SRCS}
dvpp_decode_jpeg_test.cc)
endif()
add_executable(de_ut_tests ${DE_UT_SRCS})
set_target_properties(de_ut_tests PROPERTIES INSTALL_RPATH "$ORIGIN/../lib:$ORIGIN/../lib64")

View File

@ -0,0 +1,40 @@
/**
* Copyright 2021Huawei Technologies Co., Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "common/common.h"
#include "common/cvop_common.h"
#include "minddata/dataset/include/vision_ascend.h"
#include "minddata/dataset/kernels/image/dvpp/dvpp_decode_jpeg_op.h"
#include "utils/log_adapter.h"
using namespace mindspore::dataset;
using mindspore::LogStream;
using mindspore::ExceptionType::NoExceptionType;
using mindspore::MsLogLevel::INFO;
class MindDataTestDvppDecodeJpeg : public UT::CVOP::CVOpCommon {
protected:
MindDataTestDvppDecodeJpeg() : CVOpCommon() {}
std::shared_ptr<Tensor> output_tensor_;
};
TEST_F(MindDataTestDvppDecodeJpeg, TestOp1) {
MS_LOG(INFO) << "Doing testDvppDecodeJpeg.";
std::unique_ptr<DvppDecodeJpegOp> op(new DvppDecodeJpegOp());
EXPECT_TRUE(op->OneToOne());
Status s = op->Compute(input_tensor_, &output_tensor_);
EXPECT_EQ(s, Status::OK());
}