| @@ -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; | |||
| Status InitChipResource(); | |||
| 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(); | |||
| } | |||
| Execute::Execute(std::shared_ptr<TensorOperation> op) { ops_.emplace_back(std::move(op)); } | |||
| 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(std::vector<std::shared_ptr<TensorOperation>> ops) : ops_(std::move(ops)) {} | |||
| 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()); | |||
| } | |||
| 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; | |||
| } | |||
| // 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 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_); | |||
| // For next transform | |||
| de_tensor = std::move(de_output); | |||
| } | |||
| // 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)); | |||
| // 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 | |||
| 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()); | |||
| } | |||
| 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)); | |||
| } | |||
| // 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); | |||
| } | |||
| 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); | |||
| 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); | |||
| } | |||
| de_tensor_list.emplace_back(std::move(de_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)); | |||
| // 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); | |||
| // 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()); | |||
| } | |||
| // For next transform | |||
| de_tensor_list = std::move(de_output_list); | |||
| CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor vector is empty"); | |||
| #endif | |||
| } | |||
| return Status::OK(); | |||
| } | |||
| 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); | |||
| 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); | |||
| } | |||
| CHECK_FAIL_RETURN_UNEXPECTED(!output_tensor_list->empty(), "Output Tensor is not valid"); | |||
| 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 | |||
| @@ -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 | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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_; | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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(); | |||
| } | |||
| @@ -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 | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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. | |||
| @@ -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_ | |||
| @@ -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) | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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(); } | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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 | |||
| @@ -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(); | |||
| @@ -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; | |||
| } | |||
| @@ -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_ | |||
| @@ -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; | |||
| } | |||
| @@ -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 | |||
| @@ -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) { | |||
| @@ -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 { | |||
| friend APP_ERROR ExistFile(const std::string &filePath); | |||
| public: | |||
| ResourceManager() {} | |||
| ResourceManager(){}; | |||
| ~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 | |||
| @@ -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]; | |||
| @@ -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, | |||
| @@ -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) {} | |||
| @@ -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; | |||
| @@ -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 | |||
| @@ -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}; | |||
| @@ -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) | |||
| @@ -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 | |||
| } | |||
| @@ -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}) | |||
| @@ -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") | |||
| @@ -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()); | |||
| } | |||