forked from mindspore-Ecosystem/mindspore
!3874 add SoftDvppDecodeResizeJpegOp and SoftDvppDecodeRandomCropResizeJpeg op
Merge pull request !3874 from qianlong21st/soft_dvpp
This commit is contained in:
commit
a2827eb657
|
@ -8,11 +8,12 @@ endif()
|
|||
set(jpeg_turbo_LDFLAGS "-Wl,-z,relro,-z,now,-z,noexecstack")
|
||||
mindspore_add_pkg(jpeg_turbo
|
||||
VER 2.0.4
|
||||
LIBS jpeg
|
||||
LIBS jpeg turbojpeg
|
||||
URL https://github.com/libjpeg-turbo/libjpeg-turbo/archive/2.0.4.tar.gz
|
||||
MD5 44c43e4a9fb352f47090804529317c88
|
||||
CMAKE_OPTION -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=TRUE
|
||||
CMAKE_OPTION -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=TRUE -DWITH_SIMD=ON
|
||||
PATCHES ${CMAKE_SOURCE_DIR}/third_party/patch/jpeg_turbo/jpeg_turbo.patch001
|
||||
)
|
||||
include_directories(${jpeg_turbo_INC})
|
||||
add_library(mindspore::jpeg_turbo ALIAS jpeg_turbo::jpeg)
|
||||
add_library(mindspore::turbojpeg ALIAS jpeg_turbo::turbojpeg)
|
||||
|
|
|
@ -62,6 +62,7 @@ add_subdirectory(text)
|
|||
add_dependencies(utils core)
|
||||
add_dependencies(kernels-image core)
|
||||
add_dependencies(kernels-data core)
|
||||
add_dependencies(kernels-soft-dvpp-image core soft-dvpp-utils)
|
||||
add_dependencies(kernels core)
|
||||
add_dependencies(engine-datasetops-source core)
|
||||
add_dependencies(engine-datasetops-source-sampler core)
|
||||
|
@ -88,6 +89,8 @@ set(submodules
|
|||
$<TARGET_OBJECTS:kernels-image>
|
||||
$<TARGET_OBJECTS:kernels-data>
|
||||
$<TARGET_OBJECTS:cpp-API>
|
||||
$<TARGET_OBJECTS:kernels-soft-dvpp-image>
|
||||
$<TARGET_OBJECTS:soft-dvpp-utils>
|
||||
$<TARGET_OBJECTS:engine-datasetops-source>
|
||||
$<TARGET_OBJECTS:engine-datasetops-source-sampler>
|
||||
$<TARGET_OBJECTS:engine-datasetops-mapop>
|
||||
|
@ -141,7 +144,7 @@ else()
|
|||
target_link_libraries(_c_dataengine PRIVATE -ldl mindspore::protobuf ${SECUREC_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
target_link_libraries(_c_dataengine PUBLIC mindspore::jpeg_turbo mindspore::opencv_core mindspore::opencv_imgcodecs
|
||||
target_link_libraries(_c_dataengine PUBLIC mindspore::jpeg_turbo mindspore::turbojpeg mindspore::opencv_core mindspore::opencv_imgcodecs
|
||||
mindspore::opencv_imgproc mindspore::tinyxml2 mindspore::sentencepiece mindspore::sentencepiece_train ${ICU_LIB})
|
||||
if (ENABLE_GPUQUE)
|
||||
target_link_libraries(_c_dataengine PRIVATE gpu_queue
|
||||
|
|
|
@ -50,6 +50,8 @@
|
|||
#include "minddata/dataset/kernels/image/resize_bilinear_op.h"
|
||||
#include "minddata/dataset/kernels/image/resize_op.h"
|
||||
#include "minddata/dataset/kernels/image/resize_with_bbox_op.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/soft_dvpp_decode_random_crop_resize_jpeg_op.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/soft_dvpp_decode_resize_jpeg_op.h"
|
||||
#include "minddata/dataset/kernels/image/uniform_aug_op.h"
|
||||
|
||||
namespace mindspore {
|
||||
|
@ -362,6 +364,24 @@ PYBIND_REGISTER(RandomSelectSubpolicyOp, 1, ([](const py::module *m) {
|
|||
return std::make_shared<RandomSelectSubpolicyOp>(cpp_policy);
|
||||
}));
|
||||
}));
|
||||
PYBIND_REGISTER(SoftDvppDecodeResizeJpegOp, 1, ([](const py::module *m) {
|
||||
(void)py::class_<SoftDvppDecodeResizeJpegOp, TensorOp, std::shared_ptr<SoftDvppDecodeResizeJpegOp>>(
|
||||
*m, "SoftDvppDecodeResizeJpegOp", "TensorOp to use soft dvpp decode and resize jpeg image.")
|
||||
.def(py::init<int32_t, int32_t>(), py::arg("targetHeight"), py::arg("targetWidth"));
|
||||
}));
|
||||
PYBIND_REGISTER(
|
||||
SoftDvppDecodeRandomCropResizeJpegOp, 1, ([](const py::module *m) {
|
||||
(void)
|
||||
py::class_<SoftDvppDecodeRandomCropResizeJpegOp, TensorOp, std::shared_ptr<SoftDvppDecodeRandomCropResizeJpegOp>>(
|
||||
*m, "SoftDvppDecodeRandomCropResizeJpegOp",
|
||||
"TensorOp to use soft dvpp decode, random crop and resize jepg image.")
|
||||
.def(py::init<int32_t, int32_t, float, float, float, float, int32_t>(), py::arg("targetHeight"),
|
||||
py::arg("targetWidth"), py::arg("scaleLb") = RandomCropDecodeResizeOp::kDefScaleLb,
|
||||
py::arg("scaleUb") = RandomCropDecodeResizeOp::kDefScaleUb,
|
||||
py::arg("aspectLb") = RandomCropDecodeResizeOp::kDefAspectLb,
|
||||
py::arg("aspectUb") = RandomCropDecodeResizeOp::kDefAspectUb,
|
||||
py::arg("maxIter") = RandomCropDecodeResizeOp::kDefMaxIter);
|
||||
}));
|
||||
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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(soft_dvpp)
|
||||
add_library(kernels-image OBJECT
|
||||
affine_op.cc
|
||||
auto_contrast_op.cc
|
||||
|
@ -38,3 +39,4 @@ add_library(kernels-image OBJECT
|
|||
resize_with_bbox_op.cc
|
||||
random_resize_with_bbox_op.cc
|
||||
)
|
||||
add_dependencies(kernels-image kernels-soft-dvpp-image)
|
||||
|
|
|
@ -956,5 +956,24 @@ Status UpdateBBoxesForResize(const std::shared_ptr<Tensor> &bboxList, const size
|
|||
return Status::OK();
|
||||
}
|
||||
|
||||
Status GetJpegImageInfo(const std::shared_ptr<Tensor> &input, int *img_width, int *img_height) {
|
||||
struct jpeg_decompress_struct cinfo {};
|
||||
struct JpegErrorManagerCustom jerr {};
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = JpegErrorExitCustom;
|
||||
try {
|
||||
jpeg_create_decompress(&cinfo);
|
||||
JpegSetSource(&cinfo, input->GetBuffer(), input->SizeInBytes());
|
||||
(void)jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
} catch (std::runtime_error &e) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
RETURN_STATUS_UNEXPECTED(e.what());
|
||||
}
|
||||
*img_height = cinfo.output_height;
|
||||
*img_width = cinfo.output_width;
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
|
|
@ -268,6 +268,12 @@ Status PadBBoxes(const std::shared_ptr<Tensor> *bboxList, const size_t &bboxCoun
|
|||
Status UpdateBBoxesForResize(const std::shared_ptr<Tensor> &bboxList, const size_t &bboxCount, int32_t target_width_,
|
||||
int32_t target_height_, int orig_width, int orig_height);
|
||||
|
||||
// Get jpeg image width and height
|
||||
// @param input: CVTensor containing the not decoded image 1D bytes
|
||||
// @param img_width: the jpeg image width
|
||||
// @param img_height: the jpeg image height
|
||||
Status GetJpegImageInfo(const std::shared_ptr<Tensor> &input, int *img_width, int *img_height);
|
||||
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
#endif // MINDSPORE_CCSRC_MINDDATA_DATASET_KERNELS_IMAGE_IMAGE_UTILS_H_
|
||||
|
|
|
@ -37,22 +37,9 @@ Status RandomCropDecodeResizeOp::Compute(const std::shared_ptr<Tensor> &input, s
|
|||
RETURN_IF_NOT_OK(op.Compute(input, &decoded));
|
||||
return RandomCropAndResizeOp::Compute(decoded, output);
|
||||
} else {
|
||||
struct jpeg_decompress_struct cinfo {};
|
||||
struct JpegErrorManagerCustom jerr {};
|
||||
cinfo.err = jpeg_std_error(&jerr.pub);
|
||||
jerr.pub.error_exit = JpegErrorExitCustom;
|
||||
try {
|
||||
jpeg_create_decompress(&cinfo);
|
||||
JpegSetSource(&cinfo, input->GetBuffer(), input->SizeInBytes());
|
||||
(void)jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_calc_output_dimensions(&cinfo);
|
||||
} catch (std::runtime_error &e) {
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
RETURN_STATUS_UNEXPECTED(e.what());
|
||||
}
|
||||
int h_in = cinfo.output_height;
|
||||
int w_in = cinfo.output_width;
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
int h_in = 0;
|
||||
int w_in = 0;
|
||||
RETURN_IF_NOT_OK(GetJpegImageInfo(input, &w_in, &h_in));
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
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-soft-dvpp-image OBJECT
|
||||
soft_dvpp_decode_resize_jpeg_op.cc
|
||||
soft_dvpp_decode_random_crop_resize_jpeg_op.cc)
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/soft_dvpp_decode_random_crop_resize_jpeg_op.h"
|
||||
#include <string>
|
||||
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
#include "minddata/dataset/core/cv_tensor.h"
|
||||
#include "minddata/dataset/kernels/image/image_utils.h"
|
||||
#include "minddata/dataset/util/random.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
SoftDvppDecodeRandomCropResizeJpegOp::SoftDvppDecodeRandomCropResizeJpegOp(int32_t target_height, int32_t target_width,
|
||||
float scale_lb, float scale_ub,
|
||||
float aspect_lb, float aspect_ub,
|
||||
int32_t max_iter)
|
||||
: RandomCropAndResizeOp(target_height, target_width, scale_lb, scale_ub, aspect_lb, aspect_ub,
|
||||
InterpolationMode::kLinear, max_iter) {}
|
||||
|
||||
Status SoftDvppDecodeRandomCropResizeJpegOp::GetCropInfo(const std::shared_ptr<Tensor> &input,
|
||||
SoftDpCropInfo *crop_info) {
|
||||
int img_width = 0;
|
||||
int img_height = 0;
|
||||
RETURN_IF_NOT_OK(GetJpegImageInfo(input, &img_width, &img_height));
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int crop_heigh = 0;
|
||||
int crop_widht = 0;
|
||||
RETURN_IF_NOT_OK(GetCropBox(img_height, img_width, &x, &y, &crop_heigh, &crop_widht));
|
||||
crop_info->left = x;
|
||||
crop_info->up = y;
|
||||
crop_info->right = crop_info->left + crop_widht;
|
||||
crop_info->down = crop_info->up + crop_heigh;
|
||||
return Status::OK();
|
||||
}
|
||||
|
||||
Status SoftDvppDecodeRandomCropResizeJpegOp::Compute(const std::shared_ptr<Tensor> &input,
|
||||
std::shared_ptr<Tensor> *output) {
|
||||
IO_CHECK(input, output);
|
||||
if (!IsNonEmptyJPEG(input)) {
|
||||
RETURN_STATUS_UNEXPECTED("SoftDvppDecodeRandomCropResizeJpeg only support process jpeg image.");
|
||||
}
|
||||
SoftDpCropInfo crop_info;
|
||||
RETURN_IF_NOT_OK(GetCropInfo(input, &crop_info));
|
||||
try {
|
||||
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(buffer != nullptr, "The input image buffer is empty.");
|
||||
SoftDpProcsessInfo info;
|
||||
info.input_buffer = static_cast<uint8_t *>(buffer);
|
||||
info.input_buffer_size = input->SizeInBytes();
|
||||
info.output_width = target_width_;
|
||||
info.output_height = target_height_;
|
||||
cv::Mat out_rgb_img(target_height_, target_width_, CV_8UC3);
|
||||
info.output_buffer = out_rgb_img.data;
|
||||
info.output_buffer_size = target_width_ * target_height_ * 3;
|
||||
info.is_v_before_u = true;
|
||||
int ret = DecodeAndCropAndResizeJpeg(&info, crop_info);
|
||||
std::string error_info("Soft dvpp DecodeAndResizeJpeg failed with return code: ");
|
||||
error_info += std::to_string(ret);
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(ret == 0, error_info);
|
||||
std::shared_ptr<CVTensor> cv_tensor = nullptr;
|
||||
RETURN_IF_NOT_OK(CVTensor::CreateFromMat(out_rgb_img, &cv_tensor));
|
||||
*output = std::static_pointer_cast<Tensor>(cv_tensor);
|
||||
} catch (const cv::Exception &e) {
|
||||
RETURN_STATUS_UNEXPECTED("Error in soft dvpp image decode and resize.");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
/**
|
||||
* Copyright 2020 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 DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RANDOM_CROP_RESIZE_JPEG_OP_H_
|
||||
#define DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RANDOM_CROP_RESIZE_JPEG_OP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
#include "./utils/external_soft_dp.h"
|
||||
#include "minddata/dataset/core/tensor.h"
|
||||
#include "minddata/dataset/kernels/image/random_crop_and_resize_op.h"
|
||||
#include "minddata/dataset/util/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
class SoftDvppDecodeRandomCropResizeJpegOp : public RandomCropAndResizeOp {
|
||||
public:
|
||||
SoftDvppDecodeRandomCropResizeJpegOp(int32_t target_height, int32_t target_width, float scale_lb = kDefScaleLb,
|
||||
float scale_ub = kDefScaleUb, float aspect_lb = kDefAspectLb,
|
||||
float aspect_ub = kDefAspectUb, int32_t max_iter = kDefMaxIter);
|
||||
|
||||
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
|
||||
|
||||
std::string Name() const override { return kSoftDvppDecodeRandomCropResizeJpegOp; }
|
||||
|
||||
protected:
|
||||
Status GetCropInfo(const std::shared_ptr<Tensor> &input, SoftDpCropInfo *crop_info);
|
||||
};
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RANDOM_CROP_RESIZE_JPEG_OP_H_
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/soft_dvpp_decode_resize_jpeg_op.h"
|
||||
#include <string>
|
||||
|
||||
#include "./utils/external_soft_dp.h"
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
#include "minddata/dataset/core/cv_tensor.h"
|
||||
#include "minddata/dataset/kernels/image/image_utils.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
Status SoftDvppDecodeResizeJpegOp::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.");
|
||||
}
|
||||
try {
|
||||
unsigned char *buffer = const_cast<unsigned char *>(input->GetBuffer());
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(buffer != nullptr, "The input image buffer is empty.");
|
||||
SoftDpProcsessInfo info;
|
||||
info.input_buffer = static_cast<uint8_t *>(buffer);
|
||||
info.input_buffer_size = input->SizeInBytes();
|
||||
info.output_width = target_width_;
|
||||
info.output_height = target_height_;
|
||||
|
||||
SoftDpCropInfo crop_info{0, 0, 0, 0};
|
||||
|
||||
cv::Mat out_rgb_img(target_height_, target_width_, CV_8UC3);
|
||||
info.output_buffer = out_rgb_img.data;
|
||||
info.output_buffer_size = target_width_ * target_height_ * 3;
|
||||
info.is_v_before_u = true;
|
||||
int ret = DecodeAndResizeJpeg(&info);
|
||||
std::string error_info("Soft dvpp DecodeAndResizeJpeg failed with return code: ");
|
||||
error_info += std::to_string(ret);
|
||||
CHECK_FAIL_RETURN_UNEXPECTED(ret == 0, error_info);
|
||||
std::shared_ptr<CVTensor> cv_tensor = nullptr;
|
||||
RETURN_IF_NOT_OK(CVTensor::CreateFromMat(out_rgb_img, &cv_tensor));
|
||||
*output = std::static_pointer_cast<Tensor>(cv_tensor);
|
||||
} catch (const cv::Exception &e) {
|
||||
RETURN_STATUS_UNEXPECTED("Error in soft dvpp image decode and resize.");
|
||||
}
|
||||
return Status::OK();
|
||||
}
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
|
@ -0,0 +1,44 @@
|
|||
/**
|
||||
* Copyright 2020 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 DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RESIZE_JPEG_OP_H_
|
||||
#define DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RESIZE_JPEG_OP_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "minddata/dataset/core/tensor.h"
|
||||
#include "minddata/dataset/kernels/tensor_op.h"
|
||||
#include "minddata/dataset/util/status.h"
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
class SoftDvppDecodeResizeJpegOp : public TensorOp {
|
||||
public:
|
||||
SoftDvppDecodeResizeJpegOp(int32_t target_height, int32_t target_width)
|
||||
: target_height_(target_height), target_width_(target_width) {}
|
||||
|
||||
Status Compute(const std::shared_ptr<Tensor> &input, std::shared_ptr<Tensor> *output) override;
|
||||
|
||||
std::string Name() const override { return kSoftDvppDecodeReiszeJpegOp; }
|
||||
|
||||
private:
|
||||
int32_t target_height_;
|
||||
int32_t target_width_;
|
||||
};
|
||||
} // namespace dataset
|
||||
} // namespace mindspore
|
||||
|
||||
#endif // DATASET_KERNELS_IMAGE_SOFT_DVPP_DECODE_RESIZE_JPEG_OP_H_
|
|
@ -0,0 +1,13 @@
|
|||
file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cpp")
|
||||
set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD)
|
||||
add_library(soft-dvpp-utils OBJECT
|
||||
soft_dp.cc
|
||||
soft_dp_tools.cc
|
||||
soft_jpegd.cc
|
||||
soft_vpc.cc
|
||||
yuv_scaler_para_set.cc)
|
||||
if (USE_GLOG)
|
||||
message("Soft dvpp use glog to print message.")
|
||||
else()
|
||||
add_compile_definitions(DVPP_UTST)
|
||||
endif()
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright 2020 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 EXTERNAL_SOFTDP_H
|
||||
#define EXTERNAL_SOFTDP_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct SoftDpProcsessInfo {
|
||||
uint8_t *input_buffer; // input buffer
|
||||
uint32_t input_buffer_size; // input buffer size
|
||||
|
||||
uint8_t *output_buffer; // output buffer
|
||||
uint32_t output_buffer_size; // output buffer size
|
||||
|
||||
uint32_t output_width; // output width
|
||||
uint32_t output_height; // output height
|
||||
|
||||
bool is_v_before_u; // uv : true, uv : false
|
||||
};
|
||||
|
||||
struct SoftDpCropInfo {
|
||||
uint32_t left; // crop left boundry
|
||||
uint32_t right; // crop right boundry
|
||||
uint32_t up; // crop up boundry
|
||||
uint32_t down; // crop down boundry
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief decode and resize image
|
||||
* @param [in] SoftDpProcsessInfo& soft_dp_process_info: soft decode process struct
|
||||
* @return success: return 0, fail: return error number
|
||||
*/
|
||||
uint32_t DecodeAndResizeJpeg(SoftDpProcsessInfo *soft_dp_process_info);
|
||||
|
||||
/*
|
||||
* @brief decode and crop and resize image
|
||||
* @param [in] SoftDpProcsessInfo& soft_dp_process_info: soft decode process struct
|
||||
* @param [in] SoftDpCropInfo& crop_info: user crop info
|
||||
* @return success: return 0, fail: return error number
|
||||
*/
|
||||
uint32_t DecodeAndCropAndResizeJpeg(SoftDpProcsessInfo *soft_dp_process_info, const SoftDpCropInfo &crop_info);
|
||||
|
||||
#endif // EXTERNAL_SOFTDP_H
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_check.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_jpegd.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_vpc.h"
|
||||
|
||||
const int32_t decodeSucc = 0;
|
||||
|
||||
uint32_t DecodeAndResizeJpeg(SoftDpProcsessInfo *soft_dp_process_info) {
|
||||
VpcInfo vpc_input_info;
|
||||
SoftJpegd soft_handler;
|
||||
int32_t ret = soft_handler.JpegdSoftwareDecodeProcess(&vpc_input_info, soft_dp_process_info);
|
||||
if (ret != decodeSucc) {
|
||||
API_LOGE("Jpegd decode fail in resize interface.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// use vpc interface to resize and convert RGB, give user output buf and output size.
|
||||
SoftDpCropInfo crop;
|
||||
crop.left = 0;
|
||||
crop.right = vpc_input_info.real_width - 1;
|
||||
crop.up = 0;
|
||||
crop.down = vpc_input_info.real_height - 1;
|
||||
|
||||
VpcInfo output;
|
||||
output.addr = soft_dp_process_info->output_buffer;
|
||||
output.width = soft_dp_process_info->output_width;
|
||||
output.height = soft_dp_process_info->output_height;
|
||||
SoftVpc soft_vpc;
|
||||
ret = soft_vpc.Process(vpc_input_info, crop, output);
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t DecodeAndCropAndResizeJpeg(SoftDpProcsessInfo *soft_dp_process_info, const SoftDpCropInfo &crop_info) {
|
||||
VpcInfo vpc_input_info;
|
||||
SoftJpegd soft_handler;
|
||||
|
||||
int32_t ret = soft_handler.JpegdSoftwareDecodeProcess(&vpc_input_info, soft_dp_process_info);
|
||||
if (ret != decodeSucc) {
|
||||
API_LOGE("Jpegd decode fail in crop and resize interface.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// use vpc interface to resize and crop and convert RGB, give user output buf and output size.
|
||||
VpcInfo output;
|
||||
output.addr = soft_dp_process_info->output_buffer;
|
||||
output.width = soft_dp_process_info->output_width;
|
||||
output.height = soft_dp_process_info->output_height;
|
||||
SoftDpCropInfo crop = crop_info;
|
||||
|
||||
SoftVpc soft_vpc;
|
||||
ret = soft_vpc.Process(vpc_input_info, crop, output);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_DP_H
|
||||
#define SOFT_DP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "./external_soft_dp.h"
|
||||
|
||||
enum JpegdToVpcFormat {
|
||||
INPUT_VPC_UNKNOWN = -1,
|
||||
INPUT_YUV420_PLANNER = 1, // 1
|
||||
INPUT_YUV422_PLANNER, // 2
|
||||
INPUT_YUV444_PLANNER, // 3
|
||||
INPUT_YUV400_PLANNER, // 4
|
||||
};
|
||||
|
||||
struct VpcInfo {
|
||||
uint8_t *addr;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
|
||||
int32_t real_width;
|
||||
int32_t real_height;
|
||||
|
||||
enum JpegdToVpcFormat format;
|
||||
bool is_v_before_u;
|
||||
bool is_fake420;
|
||||
|
||||
VpcInfo()
|
||||
: addr(nullptr),
|
||||
width(0),
|
||||
height(0),
|
||||
real_width(0),
|
||||
real_height(0),
|
||||
format(INPUT_VPC_UNKNOWN),
|
||||
is_v_before_u(false),
|
||||
is_fake420(false) {}
|
||||
};
|
||||
|
||||
#endif // SOFT_DP_H
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_DP_CHECK_H
|
||||
#define SOFT_DP_CHECK_H
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_log.h"
|
||||
|
||||
#define CHECK_COND_FAIL_RETURN(model, cond, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
DP_LOG(model, DP_ERR, "check condition: %s fail", #cond); \
|
||||
return __VA_ARGS__; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VPC_CHECK_COND_FAIL_RETURN(cond, ret) CHECK_COND_FAIL_RETURN("VPC", cond, ret)
|
||||
|
||||
#define CHECK_COND_FAIL_PRINT_RETURN(module, cond, ret, format, argv...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
DP_LOG(module, DP_ERR, format, ##argv); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define VPC_CHECK_COND_FAIL_PRINT_RETURN(cond, ret, format, argv...) \
|
||||
CHECK_COND_FAIL_PRINT_RETURN("VPC", cond, ret, format, ##argv)
|
||||
|
||||
#define JPEGD_CHECK_COND_FAIL_PRINT_RETURN(cond, ret, format, argv...) \
|
||||
CHECK_COND_FAIL_PRINT_RETURN("JPEGD", cond, ret, format, ##argv)
|
||||
|
||||
#endif // SOFT_DP_CHECK_H
|
|
@ -0,0 +1,152 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_DP_LOG_H
|
||||
#define SOFT_DP_LOG_H
|
||||
|
||||
#define VERSION_INFO 0x0
|
||||
#define DP_DEBUG 0x1
|
||||
#define DP_INFO 0x10
|
||||
#define DP_WARNING 0x100
|
||||
#define DP_ERR 0x1000
|
||||
#define DP_EVENT 0x10000
|
||||
#define DP_DEBUG_LEVEL (DP_EVENT | DP_ERR | DP_WARNING | DP_INFO | DP_DEBUG)
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#if defined(DVPP_UTST) || defined(DEBUG)
|
||||
#include <stdio.h>
|
||||
|
||||
#define DP_LOG(model, level, format, ...) \
|
||||
do { \
|
||||
if (DP_DEBUG_LEVEL & level) { \
|
||||
if (DP_DEBUG & level) { \
|
||||
printf( \
|
||||
"[SOFT_DP-%s] [%s %d] [DEBUG:] " \
|
||||
"[T%d] " format "\n", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_INFO & level) { \
|
||||
printf( \
|
||||
"[SOFT_DP-%s] [%s %d] [INFO:] " \
|
||||
"[T%d] " format "\n", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_WARNING & level) { \
|
||||
printf( \
|
||||
"[SOFT_DP-%s] [%s %d] [WARNING] " \
|
||||
"[T%d] " format "\n", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_ERR & level) { \
|
||||
printf( \
|
||||
"[SOFT_DP-%s] [%s %d] [ERROR:] " \
|
||||
"[T%d] " format "\n", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else { \
|
||||
printf( \
|
||||
"[SOFT_DP-%s] [%s %d] [EVENT:] " \
|
||||
"[T%d] " format "\n", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#elif defined(USE_GLOG)
|
||||
|
||||
#include <cstdio>
|
||||
#include "glog/logging.h"
|
||||
|
||||
template <typename... Args>
|
||||
inline std::string GetFormatString(const char *format, Args... args) {
|
||||
char buf[BUFSIZ];
|
||||
int new_len = snprintf(&buf[0], BUFSIZ, format, args...);
|
||||
new_len++;
|
||||
if (new_len > BUFSIZ) {
|
||||
std::vector<char> buf2(new_len);
|
||||
snprintf(buf2.data(), new_len, format, args...);
|
||||
return std::string(buf2.data());
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
#define DP_LOG(model, level, format, ...) \
|
||||
do { \
|
||||
std::string info = GetFormatString( \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
if (DP_WARNING & level) { \
|
||||
LOG(WARNING) << info; \
|
||||
} else if (DP_ERR & level) { \
|
||||
LOG(ERROR) << info; \
|
||||
} else { \
|
||||
LOG(INFO) << info; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else // #if defined(DVPP_UTST) || defined(DEBUG)
|
||||
|
||||
#include "./slog.h"
|
||||
|
||||
#define DP_LOG(model, level, format, ...) \
|
||||
do { \
|
||||
if (DP_DEBUG_LEVEL & level) { \
|
||||
if (DP_DEBUG & level) { \
|
||||
dlog_debug(SOFT_DP, \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_INFO & level) { \
|
||||
dlog_info(SOFT_DP, \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_WARNING & level) { \
|
||||
dlog_warn(SOFT_DP, \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else if (DP_ERR & level) { \
|
||||
dlog_error(SOFT_DP, \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} else { \
|
||||
dlog_event(SOFT_DP, \
|
||||
"[%s] [%s:%d] " \
|
||||
"[T%d] " format "", \
|
||||
model, __FUNCTION__, __LINE__, VERSION_INFO, ##__VA_ARGS__); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif // #if defined(DVPP_UTST) || defined(DEBUG)
|
||||
|
||||
#define VPC_LOG(level, format, argv...) DP_LOG("VPC", level, format, ##argv)
|
||||
#define VPC_LOGD(format, argv...) DP_LOG("VPC", DP_DEBUG, format, ##argv)
|
||||
#define VPC_LOGW(format, argv...) DP_LOG("VPC", DP_WARNING, format, ##argv)
|
||||
#define VPC_LOGE(format, argv...) DP_LOG("VPC", DP_ERR, format, ##argv)
|
||||
|
||||
#define JPEGD_LOG(level, format, argv...) DP_LOG("JPEGD", level, format, ##argv)
|
||||
#define JPEGD_LOGD(format, argv...) DP_LOG("JPEGD", DP_DEBUG, format, ##argv)
|
||||
#define JPEGD_LOGW(format, argv...) DP_LOG("JPEGD", DP_WARNING, format, ##argv)
|
||||
#define JPEGD_LOGE(format, argv...) DP_LOG("JPEGD", DP_ERR, format, ##argv)
|
||||
|
||||
#define API_LOG(level, format, argv...) DP_LOG("API", level, format, ##argv)
|
||||
#define API_LOGD(format, argv...) DP_LOG("API", DP_DEBUG, format, ##argv)
|
||||
#define API_LOGW(format, argv...) DP_LOG("API", DP_WARNING, format, ##argv)
|
||||
#define API_LOGE(format, argv...) DP_LOG("API", DP_ERR, format, ##argv)
|
||||
|
||||
#endif // SOFT_DP_LOG_H
|
|
@ -0,0 +1,56 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_tools.h"
|
||||
#include <sys/stat.h>
|
||||
#include <cstring>
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_check.h"
|
||||
|
||||
const uint32_t kMaxPath = 4096;
|
||||
|
||||
std::pair<bool, std::string> GetRealpath(const std::string &path) {
|
||||
char resolvedPath[kMaxPath];
|
||||
#ifndef DVPP_UTST
|
||||
if (path.size() > kMaxPath) {
|
||||
API_LOGD("path size too large.");
|
||||
return std::make_pair(false, std::string(strerror(errno)));
|
||||
}
|
||||
#endif // !DVPP_UTST
|
||||
|
||||
#ifdef _WIN32
|
||||
auto err = _fullpath(resolvedPath, path.c_str(), kMaxPath);
|
||||
#else
|
||||
auto err = realpath(path.c_str(), resolvedPath);
|
||||
#endif
|
||||
if (err == nullptr) {
|
||||
return std::make_pair(false, std::string(strerror(errno)));
|
||||
} else {
|
||||
return std::make_pair(true, std::string(resolvedPath, strlen(resolvedPath)));
|
||||
}
|
||||
}
|
||||
|
||||
bool IsDirectory(const std::string &path) {
|
||||
struct stat buf;
|
||||
if (stat(path.c_str(), &buf) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (S_ISDIR(buf.st_mode)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_DP_TOOLS_H
|
||||
#define SOFT_DP_TOOLS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
template <typename T1, typename T2>
|
||||
T1 AlignUp(T1 num, T2 align) {
|
||||
if (num % align) {
|
||||
num = (num / align + 1) * align;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T1, typename T2>
|
||||
T1 AlignDown(T1 num, T2 align) {
|
||||
if (num % align) {
|
||||
num = num / align * align;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool IsInTheScope(T num, T left_point, T right_point) {
|
||||
if (num >= left_point && num <= right_point) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T TruncatedFunc(T num, T min, T max) {
|
||||
if (num < min) {
|
||||
return min;
|
||||
}
|
||||
if (num > max) {
|
||||
return max;
|
||||
}
|
||||
|
||||
return num;
|
||||
}
|
||||
|
||||
std::pair<bool, std::string> GetRealpath(const std::string &path);
|
||||
|
||||
bool IsDirectory(const std::string &path);
|
||||
|
||||
#endif // SOFT_DP_TOOLS_H
|
|
@ -0,0 +1,246 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_jpegd.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_log.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_tools.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_check.h"
|
||||
#include <turbojpeg.h>
|
||||
#include <securec.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
const uint32_t yuv400UvValue = 0x80;
|
||||
const int32_t num2 = 2;
|
||||
const uint32_t channel3 = 3;
|
||||
const uint32_t zeroBufSize = 0;
|
||||
const int32_t decodePadding = 1;
|
||||
const int32_t minValue = 32;
|
||||
const int32_t maxValue = 8192;
|
||||
const int32_t decodeSucc = 0;
|
||||
const int32_t decodeErr = 1;
|
||||
|
||||
SoftJpegd::SoftJpegd() : soft_decode_out_buf_(nullptr) {}
|
||||
|
||||
/*
|
||||
* @brief : Use libjpeg to determine the image format.
|
||||
* @param [in] jpeg_decompress_struct& libjpeg_handler : libjpeg
|
||||
* @param [in] VpcInfo& vpc_input_info : vpc input information
|
||||
*/
|
||||
void SetFormat(struct jpeg_decompress_struct *libjpeg_handler, struct VpcInfo *vpc_input_info) {
|
||||
// yuv400: component 1 1x1
|
||||
// yuv420: component 3 2x2 1x1 1x1
|
||||
// yuv422: component 3 2x1 1x1 1x1
|
||||
// yuv444: component 3 1x1 1x1 1x1
|
||||
if ((libjpeg_handler->num_components == 1) &&
|
||||
(libjpeg_handler->comp_info[0].h_samp_factor == libjpeg_handler->comp_info[0].v_samp_factor)) {
|
||||
vpc_input_info->format = INPUT_YUV420_PLANNER;
|
||||
vpc_input_info->is_fake420 = true;
|
||||
} else if ((libjpeg_handler->num_components == channel3) &&
|
||||
(libjpeg_handler->comp_info[1].h_samp_factor == libjpeg_handler->comp_info[2].h_samp_factor) &&
|
||||
(libjpeg_handler->comp_info[1].v_samp_factor == libjpeg_handler->comp_info[2].v_samp_factor)) {
|
||||
if (libjpeg_handler->comp_info[0].h_samp_factor == ((libjpeg_handler->comp_info[1].h_samp_factor) * num2)) {
|
||||
if (libjpeg_handler->comp_info[0].v_samp_factor == ((libjpeg_handler->comp_info[1].v_samp_factor) * num2)) {
|
||||
vpc_input_info->format = INPUT_YUV420_PLANNER;
|
||||
} else if (libjpeg_handler->comp_info[0].v_samp_factor == libjpeg_handler->comp_info[1].v_samp_factor) {
|
||||
vpc_input_info->format = INPUT_YUV422_PLANNER;
|
||||
}
|
||||
} else if (libjpeg_handler->comp_info[0].h_samp_factor == libjpeg_handler->comp_info[1].h_samp_factor) {
|
||||
if (libjpeg_handler->comp_info[0].v_samp_factor == libjpeg_handler->comp_info[1].v_samp_factor) {
|
||||
vpc_input_info->format = INPUT_YUV444_PLANNER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void LibjpegErrorExit(j_common_ptr cinfo) {
|
||||
char jpegLastErrorMsg[JMSG_LENGTH_MAX];
|
||||
(*(cinfo->err->format_message))(cinfo, jpegLastErrorMsg);
|
||||
JPEGD_LOGE("run libjpeg get error : %s", jpegLastErrorMsg);
|
||||
throw std::runtime_error(jpegLastErrorMsg);
|
||||
}
|
||||
|
||||
bool CallLibjpeg(struct jpeg_decompress_struct *libjpeg_handler, uint8_t *addr, uint32_t size) {
|
||||
struct jpeg_error_mgr libjpegErrorMsg;
|
||||
libjpeg_handler->err = jpeg_std_error(&libjpegErrorMsg);
|
||||
libjpegErrorMsg.error_exit = LibjpegErrorExit;
|
||||
|
||||
try {
|
||||
jpeg_mem_src(libjpeg_handler, addr, size);
|
||||
jpeg_read_header(libjpeg_handler, TRUE);
|
||||
return true;
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief : Obtains the JPEG header information through libjpeg to complete the decoding preparation process.
|
||||
* @param [in] jpeg_decompress_struct& libjpeg_handler : libjpeg.
|
||||
* @param [in] VpcInfo& vpc_input_info : vpc input information.
|
||||
* @param [in] SoftDpProcsessInfo& dp_soft_process_info : soft dp struct.
|
||||
* @return : decodeSucc:parse jpeg head succ, decodeErr:parse jpeg head fail.
|
||||
*/
|
||||
uint32_t PrepareDecode(jpeg_decompress_struct *libjpeg_handler, struct VpcInfo *vpc_input_info,
|
||||
struct SoftDpProcsessInfo *dp_soft_process_info) {
|
||||
bool call_libjpeg_succ =
|
||||
CallLibjpeg(libjpeg_handler, dp_soft_process_info->input_buffer, dp_soft_process_info->input_buffer_size);
|
||||
if (!call_libjpeg_succ) {
|
||||
JPEGD_LOGE("CallLibjpeg failed!");
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
SetFormat(libjpeg_handler, vpc_input_info);
|
||||
return decodeSucc;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief : Check the parameters. The width and height range are as follows: [32,8192]
|
||||
* @param [in] int32_t height : image height
|
||||
* @param [in] int32_t width : image width
|
||||
* @return : decodeSucc:params are valid, decodeErr:params are invalid.
|
||||
*/
|
||||
uint32_t CheckInputParam(int32_t height, int32_t width) {
|
||||
JPEGD_CHECK_COND_FAIL_PRINT_RETURN((width >= minValue), decodeErr, "width(%d) should be >= 32.", width);
|
||||
JPEGD_CHECK_COND_FAIL_PRINT_RETURN((width <= maxValue), decodeErr, "width(%d) should be <= 8192.", width);
|
||||
JPEGD_CHECK_COND_FAIL_PRINT_RETURN((height >= minValue), decodeErr, "height(%d) should be >= 32.", height);
|
||||
JPEGD_CHECK_COND_FAIL_PRINT_RETURN((height <= maxValue), decodeErr, "height(%d) should be <= 8192.", height);
|
||||
return decodeSucc;
|
||||
}
|
||||
|
||||
uint32_t SoftJpegd::AllocOutputBuffer(struct VpcInfo *vpc_input_info, int32_t *width, int32_t *height,
|
||||
int32_t *sub_sample) {
|
||||
CheckInputParam(*height, *width);
|
||||
uint32_t output_size = tjBufSizeYUV2(*width, decodePadding, *height, *sub_sample);
|
||||
if (output_size == zeroBufSize) {
|
||||
JPEGD_LOGE("get outbuffer size failed!");
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
if (vpc_input_info->is_fake420) {
|
||||
output_size = output_size * channel3 / num2;
|
||||
}
|
||||
|
||||
soft_decode_out_buf_ = new (std::nothrow) uint8_t[output_size];
|
||||
if (soft_decode_out_buf_ == nullptr) {
|
||||
JPEGD_LOGE("alloc outbuffer failed!");
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
return decodeSucc;
|
||||
}
|
||||
|
||||
uint32_t SoftJpegd::ConfigVpcInputData(struct VpcInfo *vpc_input_info, int32_t *width, int32_t *height) {
|
||||
vpc_input_info->real_height = *height;
|
||||
vpc_input_info->real_width = *width;
|
||||
|
||||
if ((vpc_input_info->format == INPUT_YUV420_PLANNER || vpc_input_info->format == INPUT_YUV422_PLANNER) &&
|
||||
(*width % num2 == 1)) {
|
||||
*width = reinterpret_cast<int32_t>(AlignUp(*width, num2));
|
||||
JPEGD_LOGW("vpc width needs align up %d, height is %d.", width, height);
|
||||
}
|
||||
|
||||
if ((vpc_input_info->format == INPUT_YUV420_PLANNER || vpc_input_info->format == INPUT_YUV422_PLANNER) &&
|
||||
(*height % num2 == 1)) {
|
||||
*height = reinterpret_cast<int32_t>(AlignUp(*height, num2));
|
||||
JPEGD_LOGW("vpc height needs align up %d, height is %d.", width, height);
|
||||
}
|
||||
|
||||
vpc_input_info->addr = soft_decode_out_buf_;
|
||||
vpc_input_info->height = *height;
|
||||
vpc_input_info->width = *width;
|
||||
|
||||
if (vpc_input_info->is_fake420) {
|
||||
uint8_t *u_start = vpc_input_info->addr + vpc_input_info->width * vpc_input_info->height;
|
||||
int32_t uv_size = vpc_input_info->width * vpc_input_info->height / num2;
|
||||
int32_t safe_ret = memset_s(reinterpret_cast<void *>((uintptr_t)u_start), uv_size, yuv400UvValue, uv_size);
|
||||
if (safe_ret != 0) {
|
||||
JPEGD_LOGE("config yuv400 uv memory failed.");
|
||||
delete[] soft_decode_out_buf_;
|
||||
soft_decode_out_buf_ = nullptr;
|
||||
vpc_input_info->addr = nullptr;
|
||||
return decodeErr;
|
||||
}
|
||||
}
|
||||
|
||||
return decodeSucc;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief : destory libjpeg source
|
||||
* @param [in] struct jpeg_decompress_struct &libjpeg_handler : libjpeg handle.
|
||||
* @param [in] tjhandle &handle : tjhandle.
|
||||
*/
|
||||
void DestoryLibjpegSource(struct jpeg_decompress_struct *libjpeg_handler, const tjhandle &handle) {
|
||||
(void)tjDestroy(handle);
|
||||
jpeg_destroy_decompress(libjpeg_handler);
|
||||
}
|
||||
|
||||
uint32_t SoftJpegd::JpegdSoftwareDecodeProcess(struct VpcInfo *vpc_input_info,
|
||||
struct SoftDpProcsessInfo *soft_dp_process_info) {
|
||||
int32_t width = 0;
|
||||
int32_t height = 0;
|
||||
int32_t sub_sample = 0;
|
||||
int32_t color_spase = 0;
|
||||
struct jpeg_decompress_struct libjpeg_handler;
|
||||
jpeg_create_decompress(&libjpeg_handler);
|
||||
tjhandle handle = tjInitDecompress();
|
||||
int32_t prepare_decode_res = PrepareDecode(&libjpeg_handler, vpc_input_info, soft_dp_process_info);
|
||||
if (prepare_decode_res != decodeSucc) {
|
||||
JPEGD_LOGE("prepare decode failed!");
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
int32_t decode_header_res =
|
||||
tjDecompressHeader3(handle, soft_dp_process_info->input_buffer, soft_dp_process_info->input_buffer_size, &width,
|
||||
&height, &sub_sample, &color_spase);
|
||||
if (decode_header_res != decodeSucc) {
|
||||
JPEGD_LOGE("Decompress header failed, width = %d, height = %d.", width, height);
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
int32_t alloc_out_buf_res = AllocOutputBuffer(vpc_input_info, &width, &height, &sub_sample);
|
||||
if (alloc_out_buf_res != decodeSucc) {
|
||||
JPEGD_LOGE("alloc output buffer failed!");
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
int32_t decode_res =
|
||||
tjDecompressToYUV2(handle, soft_dp_process_info->input_buffer, soft_dp_process_info->input_buffer_size,
|
||||
soft_decode_out_buf_, width, decodePadding, height, JDCT_ISLOW);
|
||||
if (decode_res != decodeSucc) {
|
||||
JPEGD_LOGE("Decompress jpeg failed.");
|
||||
delete[] soft_decode_out_buf_;
|
||||
soft_decode_out_buf_ = nullptr;
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeErr;
|
||||
}
|
||||
|
||||
int32_t config_vpc_res = ConfigVpcInputData(vpc_input_info, &width, &height);
|
||||
if (config_vpc_res != decodeSucc) {
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeErr;
|
||||
}
|
||||
DestoryLibjpegSource(&libjpeg_handler, handle);
|
||||
return decodeSucc;
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_JPEGD_H
|
||||
#define SOFT_JPEGD_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include "./jpeglib.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/external_soft_dp.h"
|
||||
|
||||
class SoftJpegd {
|
||||
public:
|
||||
SoftJpegd();
|
||||
|
||||
~SoftJpegd() {}
|
||||
|
||||
/*
|
||||
* @brief : decode interface
|
||||
* @param [in] VpcInfo& vpc_input_info : vpc input information
|
||||
* @param [in] SoftDpProcsessInfo& soft_dp_process_info : softDp process info
|
||||
* @return : decodeSucc:decode success, decodeErr:decode failed.
|
||||
*/
|
||||
uint32_t JpegdSoftwareDecodeProcess(struct VpcInfo *vpc_input_info, struct SoftDpProcsessInfo *soft_dp_process_info);
|
||||
|
||||
private:
|
||||
uint8_t *soft_decode_out_buf_;
|
||||
|
||||
/*
|
||||
* @brief : alloc output buffer
|
||||
* @param [in] VpcInfo& vpc_input_info : vpc input information
|
||||
* @param [in] int32_t& width : output width
|
||||
* @param [in] int32_t& height : output height
|
||||
* @param [in] int32_t& sub_sample : level of chrominance subsampling in the image
|
||||
* @param [in] int32_t& color_spase : pointer to an integer variable that will receive one of the JPEG
|
||||
* constants, indicating the colorspace of the JPEG image.
|
||||
* @return : decodeSucc:alloc output buf success, decodeErr:alloc output buf failed.
|
||||
*/
|
||||
uint32_t AllocOutputBuffer(struct VpcInfo *vpc_input_info, int32_t *width, int32_t *height, int32_t *sub_sample);
|
||||
|
||||
/*
|
||||
* @brief : config decode output
|
||||
* @param [in] VpcInfo& vpc_input_info : vpc input information
|
||||
* @param [in] int32_t& width : output width
|
||||
* @param [in] int32_t& height : output height
|
||||
* @return : decodeSucc:config output buf succes, decodeErr:config output buf failed.
|
||||
*/
|
||||
uint32_t ConfigVpcInputData(struct VpcInfo *vpc_input_info, int32_t *width, int32_t *height);
|
||||
};
|
||||
|
||||
#endif // SOFT_JPEGD_H
|
|
@ -0,0 +1,780 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_vpc.h"
|
||||
#include <securec.h>
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_check.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_tools.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/yuv_scaler_para_set.h"
|
||||
|
||||
constexpr int32_t dpSucc = 0;
|
||||
constexpr int32_t dpFail = -1;
|
||||
constexpr uint32_t yuvCoeffiNum4 = 4;
|
||||
constexpr uint32_t yuvCoeffiNum5 = 5;
|
||||
constexpr uint32_t uvReductCoeffNum = 5;
|
||||
constexpr int32_t uvReductCoeff[uvReductCoeffNum] = {13, 65, 100, 65, 13}; // yuv444 dimension reduction filter.
|
||||
constexpr uint32_t scalerTap4 = 4;
|
||||
constexpr uint32_t scalerTap6 = 6;
|
||||
constexpr uint32_t scalerCoeff = 16; // yuv conversion coefficient
|
||||
constexpr uint32_t low3BitVal = 0x7;
|
||||
constexpr int32_t low16BitVal = 0xffff;
|
||||
constexpr uint32_t bit8Offset = 8;
|
||||
constexpr uint32_t bit13Offset = 13;
|
||||
constexpr uint32_t bit16Offset = 16;
|
||||
constexpr uint32_t maxCoeff = 65536;
|
||||
constexpr uint32_t num2 = 2;
|
||||
constexpr int32_t scalerTap2 = 2;
|
||||
|
||||
// yuv convert rgb coefficient table
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR0c0 = (256);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR0c1 = (0);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR0c2 = (359);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR1c0 = (256);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR1c1 = (-88);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR1c2 = (-183);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR2c0 = (256);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR2c1 = (454);
|
||||
constexpr int32_t rtAippYuv2RgbCscMatrixR2c2 = (0);
|
||||
constexpr int32_t rtAippYuv2RgbCscInputBias0 = (0);
|
||||
constexpr int32_t rtAippYuv2RgbCscInputBias1 = (128);
|
||||
constexpr int32_t rtAippYuv2RgbCscInputBias2 = (128);
|
||||
constexpr int32_t rtAippConverCoeffi = (256);
|
||||
|
||||
SoftVpc::SoftVpc()
|
||||
: in_format_(INPUT_VPC_UNKNOWN),
|
||||
in_width_(0),
|
||||
in_height_(0),
|
||||
in_data_(nullptr),
|
||||
in_y_data_(nullptr),
|
||||
in_u_data_(nullptr),
|
||||
in_v_data_(nullptr),
|
||||
left_(0),
|
||||
right_(0),
|
||||
up_(0),
|
||||
down_(0),
|
||||
out_width_(0),
|
||||
out_height_(0),
|
||||
out_data_(nullptr),
|
||||
out_y_data_(nullptr),
|
||||
out_u_data_(nullptr),
|
||||
out_v_data_(nullptr),
|
||||
pre_scaler_num_(0),
|
||||
half_line_mode_(false),
|
||||
horizon_coeff_(0),
|
||||
vertical_coeff_(0),
|
||||
horizon_bypass_(false),
|
||||
vertical_bypass_(false),
|
||||
y_horizon_tap_(nullptr),
|
||||
uv_horizon_tap_(nullptr),
|
||||
vertical_tap_(nullptr) {}
|
||||
|
||||
void SoftVpc::SetYuv422OutBuffer() {
|
||||
out_y_data_ = out_data_;
|
||||
out_u_data_ = out_y_data_ + out_width_ * out_height_;
|
||||
out_v_data_ = out_u_data_ + out_width_ * out_height_ / yuvCoeffiNum2;
|
||||
}
|
||||
|
||||
int32_t SoftVpc::CheckParamter() {
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((left_ < right_), dpFail, "left(%u) should be < right(%u).", left_, right_);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((right_ < in_width_), dpFail, "right(%u) should be < inWidth(%u).", right_,
|
||||
in_width_);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((up_ < down_), dpFail, "up(%u) should be < down(%u).", up_, down_);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((down_ < in_height_), dpFail, "down_(%u) should be < in_height(%u).", down_,
|
||||
in_height_);
|
||||
|
||||
uint32_t crop_width = right_ - left_ + 1;
|
||||
uint32_t crop_height = down_ - up_ + 1;
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((crop_width >= 10), dpFail, // mini width is 10
|
||||
"right(%u) - left(%u) + 1 = crop_width(%u) should be >= 10.", right_, left_,
|
||||
crop_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((in_width_ <= 8192), dpFail, // max width is 8192
|
||||
"inWidth(%u) should be <= 8192.", in_width_);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((crop_height >= 6), dpFail, // mini height is 6
|
||||
"down(%u) - up(%u) + 1 = crop_height(%u) should be >= 6.", down_, up_, crop_height);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((in_height_ <= 8192), dpFail, // max height is 8192
|
||||
"inHeight(%u) should be <= 8192.", in_height_);
|
||||
|
||||
uint32_t out_width = out_width_;
|
||||
uint32_t out_height = out_height_;
|
||||
bool flag = (out_width * 16 >= crop_width) ? true : false; // Up to 16x magnification
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN(flag, dpFail,
|
||||
"Max magnification is 16. Please check left(%u), right(%u), out_width(%u).", left_,
|
||||
right_, out_width);
|
||||
flag = (crop_width * 32 >= out_width) ? true : false; // A maximum of 32x zoom-out
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN(flag, dpFail,
|
||||
"Max reduction multiple is 32. Please check left(%u), right(%u), out_width(%u).",
|
||||
left_, right_, out_width);
|
||||
flag = (out_height * 16 >= crop_height) ? true : false; // Up to 16x magnification
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN(
|
||||
flag, dpFail, "Max magnification is 16. Please check up(%u), down(%u), out_height(%u).", up_, down_, out_height);
|
||||
flag = (crop_height * 32 >= out_height) ? true : false; // A maximum of 32x zoom-out
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN(flag, dpFail,
|
||||
"Max reduction multiple is 32. Please check up(%u), down(%u), out_height(%u).", up_,
|
||||
down_, out_height);
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
void SoftVpc::Init(VpcInfo input, SoftDpCropInfo crop, VpcInfo output) {
|
||||
in_info_ = input;
|
||||
out_info_ = output;
|
||||
left_ = (crop.left & 0x1) ? (crop.left + 1) : crop.left; // Round up the value to an even number.
|
||||
right_ = (crop.right & 0x1) ? crop.right : (crop.right - 1); // Take an odd number downwards.
|
||||
up_ = (crop.up & 0x1) ? (crop.up + 1) : crop.up; // Round up the value to an even number.
|
||||
down_ = (crop.down & 0x1) ? crop.down : (crop.down - 1); // Take an odd number downwards.
|
||||
|
||||
in_format_ = input.format;
|
||||
in_width_ = input.width;
|
||||
in_height_ = input.height;
|
||||
|
||||
in_data_ = input.addr;
|
||||
// Offset the start address of each channel to the cropped address.
|
||||
in_y_data_ = in_data_ + up_ * in_width_ + left_;
|
||||
in_u_data_ = in_data_ + in_width_ * in_height_ + up_ * in_width_ / yuvCoeffiNum4 + left_ / yuvCoeffiNum2;
|
||||
in_v_data_ = in_data_ + in_width_ * in_height_ * yuvCoeffiNum5 / yuvCoeffiNum4 + up_ * in_width_ / yuvCoeffiNum4 +
|
||||
left_ / yuvCoeffiNum2;
|
||||
|
||||
if (in_format_ == INPUT_YUV422_PLANNER) {
|
||||
in_u_data_ = in_data_ + in_width_ * in_height_ + up_ * in_width_ / yuvCoeffiNum2 + left_ / yuvCoeffiNum2;
|
||||
in_v_data_ = in_data_ + in_width_ * in_height_ * yuvCoeffiNum3 / yuvCoeffiNum2 + up_ * in_width_ / yuvCoeffiNum2 +
|
||||
left_ / yuvCoeffiNum2;
|
||||
}
|
||||
|
||||
if (in_format_ == INPUT_YUV444_PLANNER) {
|
||||
in_u_data_ = in_data_ + in_width_ * in_height_ + up_ * in_width_ + left_;
|
||||
in_v_data_ = in_data_ + in_width_ * in_height_ * yuvCoeffiNum2 + up_ * in_width_ + left_;
|
||||
}
|
||||
|
||||
out_width_ = output.width;
|
||||
out_height_ = output.height;
|
||||
}
|
||||
|
||||
// Converts the input result of the chip sub-module to the input of the next level and releases the input memory.
|
||||
void SoftVpc::OutputChangeToInput() {
|
||||
in_width_ = out_width_;
|
||||
in_height_ = out_height_;
|
||||
left_ = 0;
|
||||
right_ = in_width_ - 1;
|
||||
up_ = 0;
|
||||
down_ = in_height_ - 1;
|
||||
delete[] in_data_;
|
||||
in_data_ = out_data_;
|
||||
in_y_data_ = out_y_data_;
|
||||
in_u_data_ = out_u_data_;
|
||||
in_v_data_ = out_v_data_;
|
||||
}
|
||||
|
||||
// For the tasks that cannot be processed by the chip at a time, split the tasks whose scaling coefficients in the
|
||||
// horizontal direction are greater than those in the vertical direction.
|
||||
void SoftVpc::HorizonSplit(ResizeUnit *pre_unit, ResizeUnit *can_process_unit) {
|
||||
uint32_t in_width = pre_unit->in_width;
|
||||
uint32_t out_width = pre_unit->out_width;
|
||||
uint32_t in_height = pre_unit->in_height;
|
||||
uint32_t out_height = pre_unit->out_height;
|
||||
|
||||
if (out_width > 4 * in_width) { // The horizontal scaling ratio is greater than 4x.
|
||||
// Ensure that the output is less than four times of the input and the input is an even number.
|
||||
can_process_unit->in_width = AlignUp(out_width, 8) / 4;
|
||||
if (out_height > 4 * in_height) { // The vertical scaling ratio is greater than 4x.
|
||||
// Ensure that the output is less than four times of the input and the input is an even number.
|
||||
can_process_unit->in_height = AlignUp(out_height, 8) / 4;
|
||||
} else if (out_height >= in_height) { // The vertical scaling range is [1, 4].
|
||||
can_process_unit->in_height = in_height;
|
||||
} else if (out_height * 4 >= in_height) { // The vertical scaling range is [1/4, 1)
|
||||
can_process_unit->in_height = out_height;
|
||||
} else {
|
||||
can_process_unit->in_height = out_height * 4; // vertical scaling range is smaller than 1/4x
|
||||
}
|
||||
} else { // The horizontal scaling ratio is less than or equal to 4x.
|
||||
can_process_unit->in_width = in_width;
|
||||
can_process_unit->in_height = out_height * 4; // The vertical scaling ratio is less than 1/4.
|
||||
}
|
||||
|
||||
can_process_unit->out_width = out_width;
|
||||
can_process_unit->out_height = out_height;
|
||||
pre_unit->out_width = can_process_unit->in_width;
|
||||
pre_unit->out_height = can_process_unit->in_height;
|
||||
}
|
||||
|
||||
// For the tasks that cannot be processed by the chip at a time, split the tasks whose vertical scaling coefficients
|
||||
// are greater than the horizontal scaling coefficients.
|
||||
void SoftVpc::VerticalSplit(ResizeUnit *pre_unit, ResizeUnit *can_process_unit) {
|
||||
uint32_t in_width = pre_unit->in_width;
|
||||
uint32_t out_width = pre_unit->out_width;
|
||||
uint32_t in_height = pre_unit->in_height;
|
||||
uint32_t out_height = pre_unit->out_height;
|
||||
|
||||
if (out_height > 4 * in_height) { // The vertical scaling ratio is greater than 4x.
|
||||
// // Ensure that the output is less than four times of the input and the input is an even number.
|
||||
can_process_unit->in_height = AlignUp(out_height, 8) / 4;
|
||||
if (out_width > 4 * in_width) {
|
||||
can_process_unit->in_width = AlignUp(out_width, 8) / 4;
|
||||
} else if (out_width >= in_width) {
|
||||
can_process_unit->in_width = in_width;
|
||||
} else if (out_width * 4 >= in_width) {
|
||||
can_process_unit->in_width = out_width;
|
||||
} else {
|
||||
can_process_unit->in_width = out_width * 4;
|
||||
}
|
||||
} else {
|
||||
// If the vertical scaling ratio is less than or equal to 4x, the horizontal scaling
|
||||
// ratio must be less than 1/4.
|
||||
can_process_unit->in_height = in_height;
|
||||
can_process_unit->in_width = out_width * 4; // The horizontal scaling ratio is less than 1/4.
|
||||
}
|
||||
|
||||
can_process_unit->out_width = out_width;
|
||||
can_process_unit->out_height = out_height;
|
||||
pre_unit->out_width = can_process_unit->in_width;
|
||||
pre_unit->out_height = can_process_unit->in_height;
|
||||
}
|
||||
|
||||
// Check whether the VPC chip can complete the processing at a time based on the input and output sizes.
|
||||
bool SoftVpc::CanVpcChipProcess(const ResizeUnit &pre_unit) {
|
||||
uint32_t input_width = pre_unit.in_width;
|
||||
uint32_t output_width = pre_unit.out_width;
|
||||
uint32_t input_height = pre_unit.in_height;
|
||||
uint32_t output_height = pre_unit.out_height;
|
||||
uint32_t pre_scaler_num = 0;
|
||||
|
||||
// 4 and 16 inorder to check whether the aspect ratio ranges from 1/4 to 4.
|
||||
while (!(IsInTheScope(4 * output_width, input_width, 16 * input_width)) ||
|
||||
!(IsInTheScope(4 * output_height, input_height, 16 * input_height))) {
|
||||
// The number of used prescalers increases by 1.
|
||||
++pre_scaler_num;
|
||||
// Each time the prescaler is used, the input size is reduced to 1/2 of the original size divided by 2,
|
||||
// and the size must be 2-pixel aligned.
|
||||
input_width = AlignDown(input_width / 2, 2);
|
||||
// The value divided by 2 indicates that the input size is reduced to half of
|
||||
// the original size and must be 2-pixel aligned.
|
||||
input_height = AlignDown(input_height / 2, 2);
|
||||
// If the scaling coefficient is still greater than 4 after prescaler, false is returned. If the
|
||||
// scaling coefficient is greater than 4 or the number of prescalers is greater than 3, false is returned.
|
||||
if ((output_width > (4 * input_width)) || (output_height > (4 * input_height)) || (pre_scaler_num > 3)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Creates a scaling parameter stack based on the user input and output information. The elements in the stack are
|
||||
// the input and output information, and the input and output information stores the scaling information.
|
||||
void SoftVpc::BuildResizeStack() {
|
||||
uint32_t in_width = right_ - left_ + 1;
|
||||
uint32_t in_height_ = down_ - up_ + 1;
|
||||
ResizeUnit pre_unit = {in_width, in_height_, out_width_, out_height_}; // Scaling information to be split.
|
||||
|
||||
while (!CanVpcChipProcess(pre_unit)) {
|
||||
uint32_t input_width = pre_unit.in_width;
|
||||
uint32_t output_width = pre_unit.out_width;
|
||||
uint32_t input_height = pre_unit.in_height;
|
||||
uint32_t output_height = pre_unit.out_height;
|
||||
ResizeUnit can_process_unit = {0, 0, 0, 0}; // Scaling information that can be processed by the chip.
|
||||
|
||||
// Split the input and output, the horizontal scaling coefficient is greater than
|
||||
// the vertical scaling coefficient.
|
||||
if (output_width * input_height > output_height * input_width) {
|
||||
HorizonSplit(&pre_unit, &can_process_unit);
|
||||
} else { // The horizontal scaling coefficient is less than the vertical scaling coefficient.
|
||||
VerticalSplit(&pre_unit, &can_process_unit);
|
||||
}
|
||||
|
||||
can_process_unit.out_width = output_width;
|
||||
can_process_unit.out_height = output_height;
|
||||
pre_unit.out_width = can_process_unit.in_width;
|
||||
pre_unit.out_height = can_process_unit.in_height;
|
||||
|
||||
// Pushes a set of scaled information that can be processed into a stack.
|
||||
resize_stack_.push(can_process_unit);
|
||||
}
|
||||
|
||||
// Push the information that can be processed by the chip for one time into the stack.
|
||||
resize_stack_.push(pre_unit);
|
||||
}
|
||||
|
||||
int32_t SoftVpc::Yuv422pToYuv420p() {
|
||||
in_format_ = INPUT_YUV420_PLANNER;
|
||||
out_width_ = in_width_;
|
||||
out_height_ = in_height_;
|
||||
uint32_t buffer_size = out_width_ * out_height_ * yuvCoeffiNum3 / yuvCoeffiNum2;
|
||||
out_data_ = new (std::nothrow) uint8_t[buffer_size];
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((out_data_ != nullptr), dpFail, "alloc buffer fail.");
|
||||
out_y_data_ = out_data_;
|
||||
out_u_data_ = out_y_data_ + out_width_ * out_height_;
|
||||
out_v_data_ = out_u_data_ + out_width_ * out_height_ / yuvCoeffiNum4;
|
||||
|
||||
for (uint32_t i = 0; i < out_height_; i++) { // Y data remains unchanged.
|
||||
for (uint32_t j = 0; j < out_width_; j++) {
|
||||
out_y_data_[i * out_width_ + j] = in_y_data_[i * out_width_ + j];
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t yuv420_uv_w = out_width_ / yuvCoeffiNum2;
|
||||
uint32_t yuv420_uv_h = out_height_ / yuvCoeffiNum2;
|
||||
// The UV data is reduced by half. Only the UV data of 422 odd rows is obtained.
|
||||
for (uint32_t i = 0; i < yuv420_uv_h; i++) {
|
||||
for (uint32_t j = 0; j < yuv420_uv_w; j++) {
|
||||
out_u_data_[i * yuv420_uv_w + j] = in_u_data_[i * out_width_ + j];
|
||||
out_v_data_[i * yuv420_uv_w + j] = in_v_data_[i * out_width_ + j];
|
||||
}
|
||||
}
|
||||
OutputChangeToInput();
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
void SoftVpc::ChipPreProcess() {
|
||||
pre_scaler_num_ = 0;
|
||||
uint32_t crop_width = (right_ - left_ + 1);
|
||||
uint32_t crop_height = (down_ - up_ + 1);
|
||||
// The minimum scaling ratio of the scaler module is 1/4. If the scaling ratio is less than 1/4, the prescaler is
|
||||
// used for scaling. One prescaler is scaled by 1/2.
|
||||
while ((out_width_ * scalerTap4 < crop_width) || (out_height_ * scalerTap4 < crop_height)) {
|
||||
pre_scaler_num_++;
|
||||
crop_width /= yuvCoeffiNum2;
|
||||
crop_width = AlignDown(crop_width, yuvCoeffiNum2);
|
||||
crop_height /= yuvCoeffiNum2;
|
||||
crop_height = AlignDown(crop_height, yuvCoeffiNum2);
|
||||
}
|
||||
// Each time a prescaler is used, the alignment value needs to be doubled.
|
||||
uint32_t align_size = (yuvCoeffiNum2 << pre_scaler_num_);
|
||||
crop_width = (right_ - left_ + 1);
|
||||
uint32_t gap = crop_width % align_size;
|
||||
left_ += AlignDown(gap / yuvCoeffiNum2, yuvCoeffiNum2);
|
||||
right_ -= AlignUp(gap / yuvCoeffiNum2, yuvCoeffiNum2);
|
||||
crop_width -= gap;
|
||||
|
||||
crop_height = (down_ - up_ + 1);
|
||||
gap = crop_height % align_size;
|
||||
up_ += AlignDown(gap / yuvCoeffiNum2, yuvCoeffiNum2);
|
||||
down_ -= AlignUp(gap / yuvCoeffiNum2, yuvCoeffiNum2);
|
||||
crop_height -= gap;
|
||||
|
||||
uint32_t move_step = scalerCoeff - pre_scaler_num_;
|
||||
horizon_coeff_ = (crop_width << move_step) / out_width_;
|
||||
horizon_bypass_ = (horizon_coeff_ == maxCoeff) ? true : false;
|
||||
vertical_coeff_ = (crop_height << move_step) / out_height_;
|
||||
vertical_bypass_ = (vertical_coeff_ == maxCoeff) ? true : false;
|
||||
|
||||
half_line_mode_ = false;
|
||||
// If the width is less than 2048, the half mode is used.
|
||||
if ((vertical_coeff_ >= 0x2aab) && (vertical_coeff_ <= 0x8000) && (out_width_ <= 2048)) {
|
||||
half_line_mode_ = true;
|
||||
}
|
||||
|
||||
YuvWPara *yuv_scaler_paraset = YuvScalerParaSet::GetInstance();
|
||||
YuvScalerPara *scale = yuv_scaler_paraset->scale;
|
||||
int32_t index = GetScalerParamterIndex(horizon_coeff_, yuv_scaler_paraset);
|
||||
y_horizon_tap_ = scale[index].taps_6;
|
||||
uv_horizon_tap_ = scale[index].taps_4;
|
||||
|
||||
index = GetScalerParamterIndex(vertical_coeff_, yuv_scaler_paraset);
|
||||
vertical_tap_ = (half_line_mode_) ? scale[index].taps_6 : scale[index].taps_4;
|
||||
}
|
||||
|
||||
void SoftVpc::SetUvValue(int32_t *u_value, int32_t *v_value, int32_t y, int32_t pos) {
|
||||
int32_t crop_width = right_ - left_ + 1;
|
||||
int32_t in_w_stride = in_width_;
|
||||
// 5-order filtering dimension reduction algorithm.
|
||||
for (uint32_t i = 0; i < uvReductCoeffNum; i++) {
|
||||
int32_t index = pos + i - uvReductCoeffNum / yuvCoeffiNum2;
|
||||
if ((index + static_cast<int32_t>(left_) % 0x80) < 0) {
|
||||
index = -index;
|
||||
}
|
||||
if (index > (crop_width - 1)) {
|
||||
index = yuvCoeffiNum2 * (crop_width - 1) - index;
|
||||
}
|
||||
*u_value += in_u_data_[y * in_w_stride + index] * uvReductCoeff[i];
|
||||
*v_value += in_v_data_[y * in_w_stride + index] * uvReductCoeff[i];
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SoftVpc::Yuv444PackedToYuv422Packed() {
|
||||
int32_t in_w_stride = in_width_;
|
||||
int32_t crop_width = right_ - left_ + 1;
|
||||
int32_t crop_height = down_ - up_ + 1;
|
||||
out_width_ = crop_width;
|
||||
out_height_ = crop_height;
|
||||
|
||||
out_data_ = new (std::nothrow) uint8_t[out_width_ * out_height_ * yuvCoeffiNum2];
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((out_data_ != nullptr), dpFail, "alloc buffer fail.");
|
||||
SetYuv422OutBuffer();
|
||||
|
||||
for (int32_t i = 0; i < crop_height; i++) { // 拷贝y数据
|
||||
int32_t ret = memcpy_s(out_y_data_ + i * crop_width, crop_width, in_y_data_ + i * in_w_stride, crop_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
}
|
||||
|
||||
int32_t uv_width = crop_width / yuvCoeffiNum2;
|
||||
// Reduces the dimension of the UV data. The 5-order filtering algorithm is used for dimension reduction.
|
||||
for (int32_t y = 0; y < crop_height; y++) {
|
||||
for (int32_t x = 0; x < uv_width; x++) {
|
||||
int32_t pos = static_cast<uint32_t>(x) << 1;
|
||||
int32_t u_value = 0;
|
||||
int32_t v_value = 0;
|
||||
|
||||
SetUvValue(&u_value, &v_value, y, pos);
|
||||
// The most significant eight bits of the dimension reduction result are used.
|
||||
u_value = static_cast<uint32_t>(u_value + 0x80) >> 8;
|
||||
v_value = static_cast<uint32_t>(v_value + 0x80) >> 8;
|
||||
if (u_value > 0xff) u_value = 0xff;
|
||||
if (v_value > 0xff) v_value = 0xff;
|
||||
out_u_data_[y * uv_width + x] = u_value;
|
||||
out_v_data_[y * uv_width + x] = v_value;
|
||||
}
|
||||
}
|
||||
|
||||
in_format_ = INPUT_YUV422_PLANNER;
|
||||
OutputChangeToInput();
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
// For the YUV420 input, the output width and height are reduced by 1/2, the output format is YUV422,
|
||||
// and the amount of output UV data is reduced by only half.
|
||||
void SoftVpc::Yuv420PlannerUvPrescaler(uint8_t *(&in_uv_data)[yuvCoeffiNum2], uint8_t *(&out_uv_data)[yuvCoeffiNum2],
|
||||
uint32_t in_w_stride) {
|
||||
for (uint32_t k = 0; k < yuvCoeffiNum2; k++) {
|
||||
for (uint32_t i = 0; i < out_height_; i++) {
|
||||
for (uint32_t j = 0; j < out_width_ / yuvCoeffiNum2; j++) { // Zoom out by 1/2
|
||||
uint8_t a = in_uv_data[k][i * in_w_stride / yuvCoeffiNum2 + yuvCoeffiNum2 * j];
|
||||
uint8_t b = in_uv_data[k][i * in_w_stride / yuvCoeffiNum2 + yuvCoeffiNum2 * j + 1];
|
||||
out_uv_data[k][i * out_width_ / yuvCoeffiNum2 + j] = (a + b + 1) / yuvCoeffiNum2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For the YUV420 input, the output width and height are reduced by 1/2, the output format is YUV422, and the
|
||||
// amount of output UV data is reduced by 3/4. The prescaler scaling algorithm is a bilinear interpolation
|
||||
// algorithm. The scaling ratio is 1/2 horizontally and vertically. That is, two horizontal points are combined
|
||||
// into one point, and two vertical points are combined into one point.
|
||||
void SoftVpc::Yuv422PackedUvPrescaler(uint8_t *(&in_uv_data)[yuvCoeffiNum2], uint8_t *(&out_uv_data)[yuvCoeffiNum2],
|
||||
uint32_t in_w_stride) {
|
||||
for (uint32_t k = 0; k < yuvCoeffiNum2; k++) {
|
||||
for (uint32_t i = 0; i < out_height_; i++) {
|
||||
for (uint32_t j = 0; j < out_width_ / yuvCoeffiNum2; j++) {
|
||||
uint8_t a = in_uv_data[k][i * in_w_stride + yuvCoeffiNum2 * j];
|
||||
uint8_t b = in_uv_data[k][i * in_w_stride + yuvCoeffiNum2 * j + 1];
|
||||
uint8_t aa = (a + b + 1) / yuvCoeffiNum2;
|
||||
uint8_t c = in_uv_data[k][(yuvCoeffiNum2 * i + 1) * in_w_stride / yuvCoeffiNum2 + yuvCoeffiNum2 * j];
|
||||
uint8_t d = in_uv_data[k][(yuvCoeffiNum2 * i + 1) * in_w_stride / yuvCoeffiNum2 + yuvCoeffiNum2 * j + 1];
|
||||
uint8_t bb = (c + d + 1) / yuvCoeffiNum2;
|
||||
out_uv_data[k][i * out_width_ / yuvCoeffiNum2 + j] = (aa + bb + 1) / yuvCoeffiNum2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoftVpc::UvPrescaler() {
|
||||
uint32_t in_w_stride = in_width_;
|
||||
uint8_t *in_uv_data[yuvCoeffiNum2] = {in_u_data_, in_v_data_};
|
||||
uint8_t *out_uv_data[yuvCoeffiNum2] = {out_u_data_, out_v_data_};
|
||||
if (in_format_ == INPUT_YUV420_PLANNER) {
|
||||
Yuv420PlannerUvPrescaler(in_uv_data, out_uv_data, in_w_stride);
|
||||
} else {
|
||||
Yuv422PackedUvPrescaler(in_uv_data, out_uv_data, in_w_stride);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SoftVpc::PreScaler() {
|
||||
uint32_t in_w_stride = in_width_;
|
||||
uint32_t crop_width = right_ - left_ + 1;
|
||||
uint32_t crop_height = down_ - up_ + 1;
|
||||
out_width_ = crop_width / yuvCoeffiNum2;
|
||||
out_height_ = crop_height / yuvCoeffiNum2;
|
||||
out_data_ = new (std::nothrow) uint8_t[out_width_ * out_height_ * yuvCoeffiNum2];
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((out_data_ != nullptr), dpFail, "alloc buffer fail.");
|
||||
SetYuv422OutBuffer();
|
||||
|
||||
// The scaling algorithm of the rescaler is a bilinear interpolation algorithm. The scaling ratio is 1/2
|
||||
// horizontally and vertically. That is, two horizontal points are combined into one point,
|
||||
// and two vertical points are combined into one point.
|
||||
for (uint32_t i = 0; i < out_height_; i++) {
|
||||
for (uint32_t j = 0; j < out_width_; j++) {
|
||||
uint8_t a = in_y_data_[yuvCoeffiNum2 * i * in_w_stride + yuvCoeffiNum2 * j];
|
||||
uint8_t b = in_y_data_[yuvCoeffiNum2 * i * in_w_stride + yuvCoeffiNum2 * j + 1];
|
||||
uint8_t aa = (a + b + 1) / yuvCoeffiNum2;
|
||||
uint8_t c = in_y_data_[(yuvCoeffiNum2 * i + 1) * in_w_stride + yuvCoeffiNum2 * j];
|
||||
uint8_t d = in_y_data_[(yuvCoeffiNum2 * i + 1) * in_w_stride + yuvCoeffiNum2 * j + 1];
|
||||
uint8_t bb = (c + d + 1) / yuvCoeffiNum2;
|
||||
out_y_data_[i * out_width_ + j] = (aa + bb + 1) / yuvCoeffiNum2;
|
||||
}
|
||||
}
|
||||
UvPrescaler();
|
||||
|
||||
in_format_ = INPUT_YUV422_PLANNER;
|
||||
OutputChangeToInput();
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
int32_t SoftVpc::BypassHorizonScaler() {
|
||||
uint32_t in_w_stride = in_width_;
|
||||
uint32_t crop_width = right_ - left_ + 1;
|
||||
uint32_t crop_height = down_ - up_ + 1;
|
||||
for (uint32_t i = 0; i < crop_height; i++) {
|
||||
int32_t ret = memcpy_s(out_y_data_ + i * crop_width, crop_width, in_y_data_ + i * in_w_stride, crop_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
}
|
||||
|
||||
uint32_t uv_w_stride = in_w_stride / yuvCoeffiNum2;
|
||||
uint32_t uv_width = crop_width / yuvCoeffiNum2;
|
||||
|
||||
// The input format is 420. After the format is converted to 422, the UV data is doubled.
|
||||
// Therefore, the data needs to be copied twice.
|
||||
if (in_format_ == INPUT_YUV420_PLANNER) {
|
||||
uint32_t uv_height = crop_height / yuvCoeffiNum2;
|
||||
for (uint32_t i = 0; i < uv_height; i++) {
|
||||
int32_t ret =
|
||||
memcpy_s(out_u_data_ + uv_width * i * yuvCoeffiNum2, uv_width, in_u_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
ret =
|
||||
memcpy_s(out_u_data_ + uv_width * (i * yuvCoeffiNum2 + 1), uv_width, in_u_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
|
||||
ret = memcpy_s(out_v_data_ + uv_width * i * yuvCoeffiNum2, uv_width, in_v_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
ret =
|
||||
memcpy_s(out_v_data_ + uv_width * (i * yuvCoeffiNum2 + 1), uv_width, in_v_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
}
|
||||
} else {
|
||||
uint32_t uv_height = crop_height;
|
||||
for (uint32_t i = 0; i < uv_height; i++) {
|
||||
int32_t ret = memcpy_s(out_u_data_ + uv_width * i, uv_width, in_u_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
ret = memcpy_s(out_v_data_ + uv_width * i, uv_width, in_v_data_ + uv_w_stride * i, uv_width);
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "memcpy fail.");
|
||||
}
|
||||
}
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
void SoftVpc::StartHorizonScalerEx(uint32_t width_index, uint32_t tmp_offset, uint8_t *(&in_data)[yuvCoeffiNum3],
|
||||
uint8_t *(&out_data)[yuvCoeffiNum3]) {
|
||||
int16_t *taps[yuvCoeffiNum3] = {y_horizon_tap_, uv_horizon_tap_, uv_horizon_tap_};
|
||||
int32_t crop_w = right_ - left_;
|
||||
int32_t in_w[yuvCoeffiNum3] = {crop_w, crop_w / scalerTap2, crop_w / scalerTap2};
|
||||
uint32_t taps_num[yuvCoeffiNum3] = {scalerTap6, scalerTap4, scalerTap4};
|
||||
uint32_t out_w[yuvCoeffiNum3] = {out_width_, out_width_ / yuvCoeffiNum2, out_width_ / yuvCoeffiNum2};
|
||||
uint32_t mid_num = (taps_num[width_index] >> 1) - 1;
|
||||
uint32_t acc = 0;
|
||||
|
||||
// higher order filter algorithm
|
||||
// Map the output position to the input position, calculate the phase based on the input position, and find the
|
||||
// corresponding filter (6-order or 4-order filter window) based on the phase.
|
||||
// The input data and the filter perform convolution operation to obtain the output data.
|
||||
for (uint32_t j = 0; j < out_w[width_index]; j++) {
|
||||
uint32_t pos = acc >> bit16Offset;
|
||||
uint32_t phase = (acc >> bit13Offset) & low3BitVal;
|
||||
int16_t *coeffs = taps[width_index] + taps_num[width_index] * phase;
|
||||
|
||||
int32_t value = 0;
|
||||
for (uint32_t k = 0; k < taps_num[width_index]; k++) { // convolution operation
|
||||
int32_t index = pos + k - mid_num;
|
||||
index = TruncatedFunc(index, 0, in_w[width_index]);
|
||||
int32_t v1 = static_cast<int32_t>(in_data[width_index][tmp_offset + index]);
|
||||
int32_t v2 = static_cast<int32_t>(coeffs[k]);
|
||||
value += v1 * v2;
|
||||
}
|
||||
|
||||
value = TruncatedFunc((value + 0x80), 0, low16BitVal);
|
||||
value = static_cast<uint32_t>(value) >> bit8Offset;
|
||||
|
||||
*out_data[width_index]++ = static_cast<uint8_t>(value);
|
||||
acc += horizon_coeff_;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void SoftVpc::HorizonScalerEx() {
|
||||
uint8_t *in_data[yuvCoeffiNum3] = {in_y_data_, in_u_data_, in_v_data_};
|
||||
uint8_t *out_data[yuvCoeffiNum3] = {out_y_data_, out_u_data_, out_v_data_};
|
||||
uint32_t in_w_stride[yuvCoeffiNum3] = {in_width_, in_width_ / yuvCoeffiNum2, in_width_ / yuvCoeffiNum2};
|
||||
|
||||
for (uint32_t m = 0; m < yuvCoeffiNum3; m++) {
|
||||
for (uint32_t i = 0; i < out_height_; i++) {
|
||||
auto tmp_offset = i * in_w_stride[m]; // Offset of each row of data relative to the start position.
|
||||
if ((m > 0) && (in_format_ == INPUT_YUV420_PLANNER)) {
|
||||
// The width of the UV channel is half of that of the Y channel.
|
||||
tmp_offset = i / yuvCoeffiNum2 * in_w_stride[m];
|
||||
}
|
||||
StartHorizonScalerEx(m, tmp_offset, in_data, out_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t SoftVpc::HorizonScaler() {
|
||||
uint32_t crop_width = right_ - left_ + 1;
|
||||
uint32_t crop_height = down_ - up_ + 1;
|
||||
out_width_ = (crop_width << scalerCoeff) / horizon_coeff_;
|
||||
out_height_ = crop_height;
|
||||
out_data_ = new (std::nothrow) uint8_t[out_width_ * out_height_ * yuvCoeffiNum2];
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((out_data_ != nullptr), dpFail, "alloc buffer fail.");
|
||||
SetYuv422OutBuffer();
|
||||
|
||||
// in bypass mode, the input and output sizes are the same.
|
||||
// To be compatible with the YUV420 output, the YUV422 format is used.
|
||||
if (horizon_bypass_) {
|
||||
int32_t ret = BypassHorizonScaler();
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "BypassHorizonScaler fail.");
|
||||
} else {
|
||||
HorizonScalerEx();
|
||||
}
|
||||
|
||||
in_format_ = INPUT_YUV422_PLANNER;
|
||||
OutputChangeToInput();
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
void SoftVpc::StartVerticalScaler(uint32_t yuv_index, uint32_t out_w[], uint8_t *(&in_data)[yuvCoeffiNum3],
|
||||
uint8_t *(&out_data)[yuvCoeffiNum3]) {
|
||||
uint32_t num_taps = half_line_mode_ ? scalerTap6 : scalerTap4;
|
||||
uint32_t mid_num = (num_taps >> 1) - 1;
|
||||
int32_t max_offset = in_height_ - 1;
|
||||
|
||||
// higher order filter algorithm
|
||||
// Map the output position to the input position, calculate the phase based on the input position, and find the
|
||||
// corresponding filter (6-order or 4-order filter window) based on the phase. The input data and the filter
|
||||
// perform convolution operation to obtain the output data.
|
||||
for (uint32_t i = 0; i < out_height_; i++) {
|
||||
uint32_t acc = i * vertical_coeff_;
|
||||
uint32_t pos = acc >> bit16Offset;
|
||||
uint32_t phase = (acc >> bit13Offset) & low3BitVal;
|
||||
int16_t *coeffs = vertical_tap_ + num_taps * phase;
|
||||
for (uint32_t j = 0; j < out_w[yuv_index]; j++) {
|
||||
int32_t value = 0;
|
||||
for (uint32_t k = 0; k < num_taps; k++) { // convolution operation
|
||||
int32_t index = pos + k - mid_num;
|
||||
index = TruncatedFunc(index, 0, max_offset);
|
||||
int32_t v1 = in_data[yuv_index][index * out_w[yuv_index] + j];
|
||||
int32_t v2 = coeffs[k];
|
||||
value += v1 * v2;
|
||||
}
|
||||
value = TruncatedFunc((value + 0x80), 0, low16BitVal);
|
||||
value = static_cast<uint32_t>(value) >> bit8Offset;
|
||||
*out_data[yuv_index]++ = static_cast<uint8_t>(value);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t SoftVpc::VerticalScaler() {
|
||||
out_width_ = in_width_;
|
||||
out_height_ = (in_height_ << scalerCoeff) / vertical_coeff_;
|
||||
out_data_ = new (std::nothrow) uint8_t[out_width_ * out_height_ * yuvCoeffiNum2];
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((out_data_ != nullptr), dpFail, "alloc buffer fail.");
|
||||
SetYuv422OutBuffer();
|
||||
|
||||
uint8_t *in_data[yuvCoeffiNum3] = {in_y_data_, in_u_data_, in_v_data_};
|
||||
uint8_t *out_data[yuvCoeffiNum3] = {out_y_data_, out_u_data_, out_v_data_};
|
||||
uint32_t out_w[yuvCoeffiNum3] = {out_width_, out_width_ / yuvCoeffiNum2, out_width_ / yuvCoeffiNum2};
|
||||
for (uint32_t m = 0; m < yuvCoeffiNum3; m++) {
|
||||
StartVerticalScaler(m, out_w, in_data, out_data);
|
||||
}
|
||||
|
||||
OutputChangeToInput();
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
// yuv scalser is core scaler, The high-order filtering and scaling algorithm is used.
|
||||
int32_t SoftVpc::YuvScaler() {
|
||||
int32_t ret = HorizonScaler();
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "HorizonScaler fail.");
|
||||
if (!vertical_bypass_) {
|
||||
ret = VerticalScaler();
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "VerticalScaler fail.");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int32_t SoftVpc::ChipProcess() {
|
||||
ChipPreProcess();
|
||||
// Determine whether dimension reduction is required.
|
||||
if (in_format_ == INPUT_YUV444_PLANNER) {
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((Yuv444PackedToYuv422Packed() == dpSucc), dpFail,
|
||||
"Yuv444PackedToYuv422Packed fail.");
|
||||
}
|
||||
|
||||
// Analog chip PreScaler function
|
||||
for (uint32_t i = 0; i < pre_scaler_num_; i++) {
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((PreScaler() == dpSucc), dpFail, "PreScaler fail.");
|
||||
}
|
||||
|
||||
// Analog chip Yuv Scaler function
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((YuvScaler() == dpSucc), dpFail, "YuvScaler fail.");
|
||||
return dpSucc;
|
||||
}
|
||||
|
||||
void SoftVpc::YuvToRgb() {
|
||||
uint8_t *out_data = out_info_.addr;
|
||||
int32_t yy, uu, vv;
|
||||
int32_t rr, gg, bb;
|
||||
for (uint32_t j = 0; j < in_height_; j++) {
|
||||
for (uint32_t i = 0; i < in_width_; i++) {
|
||||
yy = in_y_data_[(j * in_width_) + i];
|
||||
uu = in_u_data_[((j - (j % num2)) * (in_width_ / yuvCoeffiNum2)) + (i / yuvCoeffiNum2)];
|
||||
vv = in_v_data_[((j - (j % num2)) * (in_width_ / yuvCoeffiNum2)) + (i / yuvCoeffiNum2)];
|
||||
|
||||
// yuv convert rgb formula
|
||||
rr = ((yy - rtAippYuv2RgbCscInputBias0) * rtAippYuv2RgbCscMatrixR0c0 +
|
||||
(uu - rtAippYuv2RgbCscInputBias1) * rtAippYuv2RgbCscMatrixR0c1 +
|
||||
(vv - rtAippYuv2RgbCscInputBias2) * rtAippYuv2RgbCscMatrixR0c2) /
|
||||
rtAippConverCoeffi;
|
||||
gg = ((yy - rtAippYuv2RgbCscInputBias0) * rtAippYuv2RgbCscMatrixR1c0 +
|
||||
(uu - rtAippYuv2RgbCscInputBias1) * rtAippYuv2RgbCscMatrixR1c1 +
|
||||
(vv - rtAippYuv2RgbCscInputBias2) * rtAippYuv2RgbCscMatrixR1c2) /
|
||||
rtAippConverCoeffi;
|
||||
bb = ((yy - rtAippYuv2RgbCscInputBias0) * rtAippYuv2RgbCscMatrixR2c0 +
|
||||
(uu - rtAippYuv2RgbCscInputBias1) * rtAippYuv2RgbCscMatrixR2c1 +
|
||||
(vv - rtAippYuv2RgbCscInputBias2) * rtAippYuv2RgbCscMatrixR2c2) /
|
||||
rtAippConverCoeffi;
|
||||
|
||||
*out_data++ = (rr < 0) ? 0 : ((rr < 0xff) ? rr : 0xff);
|
||||
*out_data++ = (gg < 0) ? 0 : ((gg < 0xff) ? gg : 0xff);
|
||||
*out_data++ = (bb < 0) ? 0 : ((bb < 0xff) ? bb : 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] in_data_;
|
||||
in_data_ = nullptr;
|
||||
}
|
||||
|
||||
int32_t SoftVpc::Process(VpcInfo input, const SoftDpCropInfo crop, const VpcInfo output) {
|
||||
Init(input, crop, output);
|
||||
int32_t ret = CheckParamter();
|
||||
if (ret != dpSucc) {
|
||||
delete[] input.addr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BuildResizeStack();
|
||||
while (!resize_stack_.empty()) {
|
||||
ResizeUnit &unit = resize_stack_.top();
|
||||
resize_stack_.pop();
|
||||
|
||||
out_width_ = unit.out_width;
|
||||
out_height_ = unit.out_height;
|
||||
|
||||
ret = ChipProcess();
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "ChipProcess fail.");
|
||||
|
||||
if (!resize_stack_.empty()) {
|
||||
ret = Yuv422pToYuv420p();
|
||||
VPC_CHECK_COND_FAIL_PRINT_RETURN((ret == dpSucc), dpFail, "Yuv422pToYuv420p fail.");
|
||||
}
|
||||
}
|
||||
YuvToRgb();
|
||||
|
||||
return dpSucc;
|
||||
}
|
|
@ -0,0 +1,256 @@
|
|||
/**
|
||||
* Copyright 2020 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 SOFT_VPC_H
|
||||
#define SOFT_VPC_H
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp.h"
|
||||
#include <stack>
|
||||
|
||||
constexpr uint32_t yuvCoeffiNum2 = 2;
|
||||
constexpr uint32_t yuvCoeffiNum3 = 3;
|
||||
|
||||
struct ResizeUnit {
|
||||
uint32_t in_width;
|
||||
uint32_t in_height;
|
||||
uint32_t out_width;
|
||||
uint32_t out_height;
|
||||
};
|
||||
|
||||
class SoftVpc {
|
||||
public:
|
||||
SoftVpc();
|
||||
|
||||
~SoftVpc() {}
|
||||
|
||||
/*
|
||||
* @brief : vpc Cropping and Scaling APIs.
|
||||
* @param [in] VpcInfo input : Structure input to the VPC for processing.
|
||||
* @param [in] SoftDpCropInfo crop : crop struct.
|
||||
* @param [in] VpcInfo output : vpc output struct.
|
||||
* @return : dpSucc:vpc process succ,dpFail:vpc process failed.
|
||||
*/
|
||||
int32_t Process(VpcInfo input, SoftDpCropInfo crop, VpcInfo output);
|
||||
|
||||
private:
|
||||
enum JpegdToVpcFormat in_format_;
|
||||
uint32_t in_width_;
|
||||
uint32_t in_height_;
|
||||
uint8_t *in_data_;
|
||||
uint8_t *in_y_data_;
|
||||
uint8_t *in_u_data_;
|
||||
uint8_t *in_v_data_;
|
||||
|
||||
// crop area
|
||||
uint32_t left_;
|
||||
uint32_t right_;
|
||||
uint32_t up_;
|
||||
uint32_t down_;
|
||||
|
||||
// output config
|
||||
uint32_t out_width_;
|
||||
uint32_t out_height_;
|
||||
uint8_t *out_data_;
|
||||
uint8_t *out_y_data_;
|
||||
uint8_t *out_u_data_;
|
||||
uint8_t *out_v_data_;
|
||||
|
||||
// resize config
|
||||
uint32_t pre_scaler_num_;
|
||||
|
||||
// If the image is amplified by 2x or more and the output width is less than 2048 pixels,
|
||||
// the half-line mode is required.
|
||||
bool half_line_mode_;
|
||||
uint32_t horizon_coeff_; // Horizontal scaling coefficient
|
||||
uint32_t vertical_coeff_; // Vertical scaling coefficient.
|
||||
bool horizon_bypass_;
|
||||
bool vertical_bypass_;
|
||||
int16_t *y_horizon_tap_; // Filtering coefficients for horizontal scaling of channel y
|
||||
int16_t *uv_horizon_tap_; // Filtering coefficients of the horizontal scaling UV channel.
|
||||
int16_t *vertical_tap_; // Filtering coefficient table for vertical scaling. Y and UV signals share the same table.
|
||||
|
||||
// Scaling unit stack, used to store the input and output information processed by the chip at a time.
|
||||
std::stack<ResizeUnit> resize_stack_;
|
||||
VpcInfo in_info_; // Original input information.
|
||||
VpcInfo out_info_; // Original output information.
|
||||
|
||||
/*
|
||||
* @brief : set output format is YUV422
|
||||
*/
|
||||
void SetYuv422OutBuffer();
|
||||
|
||||
/*
|
||||
* @brief : check params
|
||||
* @return : dpSucc:check succ, dpFail:check failed.
|
||||
*/
|
||||
int32_t CheckParamter();
|
||||
|
||||
/*
|
||||
* @brief : init vpc output info struct
|
||||
* @param [in] VpcInfo input : Structure input to the VPC for processing.
|
||||
* @param [in] SoftDpCropInfo crop : crop struct.
|
||||
* @param [in] VpcInfo output : vpc output struct.
|
||||
*/
|
||||
void Init(VpcInfo input, SoftDpCropInfo crop, VpcInfo output);
|
||||
|
||||
void OutputChangeToInput();
|
||||
|
||||
/*
|
||||
* @brief : For the tasks that cannot be processed by the chip at a time, split the tasks whose scaling
|
||||
* coefficients in the horizontal direction are greater than those in the vertical direction.
|
||||
* @param [in] ResizeUnit *pre_unit : input resize unit.
|
||||
* @param [in] ResizeUnit *can_process_unit : chip can process resize unit.
|
||||
*/
|
||||
void HorizonSplit(ResizeUnit *pre_unit, ResizeUnit *can_process_unit);
|
||||
|
||||
/*
|
||||
* @brief : For the tasks that cannot be processed by the chip at a time, split the tasks whose vertical scaling
|
||||
* coefficients are greater than the horizontal scaling coefficients.
|
||||
* @param [in] ResizeUnit *pre_unit : input resize unit.
|
||||
* @param [in] ResizeUnit *can_process_unit : chip can process resize unit.
|
||||
*/
|
||||
void VerticalSplit(ResizeUnit *pre_unit, ResizeUnit *can_process_unit);
|
||||
|
||||
/*
|
||||
* @brief : Check whether the VPC chip can complete the processing at a time based on the input and output sizes.
|
||||
* @param [in] const ResizeUnit& pre_unit : input resize unit.
|
||||
* @return : true:vpc process succ, false:vpc process failed.
|
||||
*/
|
||||
bool CanVpcChipProcess(const ResizeUnit &pre_unit);
|
||||
|
||||
/*
|
||||
* @brief : Creates a scaling parameter stack based on the user input and output information. The elements
|
||||
* in the stack are the input and output information. The input and output information stores the
|
||||
* scaling information task.
|
||||
*/
|
||||
void BuildResizeStack();
|
||||
|
||||
/*
|
||||
* @brief : YUV422 planner format convert YUV420 format
|
||||
* @return : dpSucc: downsampling success, dpFail: downsampling failed
|
||||
*/
|
||||
int32_t Yuv422pToYuv420p();
|
||||
|
||||
/*
|
||||
* @brief : Preprocesses the chip, calculates the number of chip prescalers, and adjusts the cropping area based on
|
||||
* the input and output information.
|
||||
*/
|
||||
void ChipPreProcess();
|
||||
|
||||
/*
|
||||
* @brief : when YUV444 packed format convert YUV422 packed, Calculate the conversion of UV.
|
||||
* @param [in] int32_t *u_value : u value.
|
||||
* @param [in] int32_t *v_value : v value.
|
||||
* @param [in] int32_t y :y value.
|
||||
* @param [in] int32_t pos :
|
||||
*/
|
||||
void SetUvValue(int32_t *u_value, int32_t *v_value, int32_t y, int32_t pos);
|
||||
|
||||
/*
|
||||
* @brief : YUV444 packed convert YUV422 packed.
|
||||
* @return : dpSucc:Downsampling succ, dpFail:Downsampling failed.
|
||||
*/
|
||||
int32_t Yuv444PackedToYuv422Packed();
|
||||
|
||||
/*
|
||||
* @brief : Pre-scaling the UV image.
|
||||
*/
|
||||
void UvPrescaler();
|
||||
|
||||
/*
|
||||
* @brief : Prescaling the UV in YUV420 format.
|
||||
* @param [in] uint8_t* (&in_uv_data)[yuvCoeffiNum2] : input uv data
|
||||
* @param [in] uint8_t* (&out_uv_data)[yuvCoeffiNum2] : output uv data
|
||||
* @param [in] uint32_t in_w_stride : input stride
|
||||
*/
|
||||
void Yuv420PlannerUvPrescaler(uint8_t *(&in_uv_data)[yuvCoeffiNum2], uint8_t *(&out_uv_data)[yuvCoeffiNum2],
|
||||
uint32_t in_w_stride);
|
||||
|
||||
/*
|
||||
* @brief : Prescaling the UV in YUV422 format.
|
||||
* @param [in] uint8_t* (&in_uv_data)[yuvCoeffiNum2] : input uv data
|
||||
* @param [in] uint8_t* (&out_uv_data)[yuvCoeffiNum2]: output uv data
|
||||
* @param [in] uint32_t in_w_stride : input stride
|
||||
*/
|
||||
void Yuv422PackedUvPrescaler(uint8_t *(&in_uv_data)[yuvCoeffiNum2], uint8_t *(&out_uv_data)[yuvCoeffiNum2],
|
||||
uint32_t in_w_stride);
|
||||
|
||||
/*
|
||||
* @brief : Chip prescaler processing.
|
||||
*/
|
||||
int32_t PreScaler();
|
||||
|
||||
/*
|
||||
* @brief : Horizontal scaling bypass.
|
||||
*/
|
||||
int32_t BypassHorizonScaler();
|
||||
|
||||
/*
|
||||
* @brief : Single-channel horizontal scaling of the chip.
|
||||
* @param [in] uint32_t width_index : index of output width array.
|
||||
* @param [in] uint32_t tmp_offset : Offset of each row of data relative to the start position.
|
||||
* @param [in] uint8_t* (&in_data)[yuvCoeffiNum3] : input y,u,v data array.
|
||||
* @param [in] uint8_t* (&out_data)[yuvCoeffiNum3] : output y,u,v data array.
|
||||
*/
|
||||
void StartHorizonScalerEx(uint32_t width_index, uint32_t tmp_offset, uint8_t *(&in_data)[yuvCoeffiNum3],
|
||||
uint8_t *(&out_data)[yuvCoeffiNum3]);
|
||||
|
||||
/*
|
||||
* @brief : Horizontal scaling.
|
||||
*/
|
||||
void HorizonScalerEx();
|
||||
|
||||
/*
|
||||
* @brief : Horizontal scaling.
|
||||
* @return : dpSucc : Horizontal scaling succ, dpFail:Horizontal scaling failed.
|
||||
*/
|
||||
int32_t HorizonScaler();
|
||||
|
||||
/*
|
||||
* @brief : start Vertical scaling.
|
||||
* @param [in] uint32_t yuv_index : index of output width array.
|
||||
* @param [in] uint32_t out_w[] : output width array.
|
||||
* @param [in] uint8_t* (&in_data)[yuvCoeffiNum3] : input y,u,v data array.
|
||||
* @param [in] uint8_t* (&out_data)[yuvCoeffiNum3] : output y,u,v data array.
|
||||
*/
|
||||
void StartVerticalScaler(uint32_t yuv_index, uint32_t out_w[], uint8_t *(&in_data)[yuvCoeffiNum3],
|
||||
uint8_t *(&out_data)[yuvCoeffiNum3]);
|
||||
|
||||
/*
|
||||
* @brief : Vertical scaling
|
||||
* @return : dpSucc : Vertical scaling succ, dpFail : Vertical scaling failed.
|
||||
*/
|
||||
int32_t VerticalScaler();
|
||||
|
||||
/*
|
||||
* @brief : Yuv Scaler Horizontal scaling and vertical scaling.
|
||||
* @return : dpSucc:yuv scaler succ. dpFail:yuv scaler failed.
|
||||
*/
|
||||
int32_t YuvScaler();
|
||||
|
||||
/*
|
||||
* @brief : Software Implementation of the Simulation Chip PreScaler and Yuv Scaler function.
|
||||
* @return : dpSucc : Analog chip scaling succ, dpFail: Analog chip scaling failed.
|
||||
*/
|
||||
int32_t ChipProcess();
|
||||
|
||||
/*
|
||||
* @brief : YUV planner convert RGB format.
|
||||
*/
|
||||
void YuvToRgb();
|
||||
};
|
||||
|
||||
#endif // SOFT_VPC_H
|
|
@ -0,0 +1,280 @@
|
|||
/**
|
||||
* Copyright 2020 Huawei Technologies Co., Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/yuv_scaler_para_set.h"
|
||||
#include <securec.h>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_check.h"
|
||||
#include "minddata/dataset/kernels/image/soft_dvpp/utils/soft_dp_tools.h"
|
||||
|
||||
pthread_mutex_t YuvScalerParaSet::g_mutex_ = PTHREAD_MUTEX_INITIALIZER;
|
||||
YuvWPara *YuvScalerParaSet::g_m_instance_ = nullptr;
|
||||
YuvScalerParaSet::GarbageCollector YuvScalerParaSet::g_collector_;
|
||||
|
||||
const int32_t dpSucc = 0;
|
||||
const int32_t dpFail = -1;
|
||||
|
||||
/*
|
||||
* @brief : Replaces the specified symbol in a string with another symbol.
|
||||
* @param [in] const string &strSrc : src string.
|
||||
* @param [in] const string &strDst : dest string.
|
||||
*/
|
||||
void StringReplace(std::string *str_big, const std::string &str_src, const std::string &str_dst) {
|
||||
std::string::size_type pos = 0;
|
||||
std::string::size_type src_len = str_src.size();
|
||||
std::string::size_type dst_len = str_dst.size();
|
||||
while ((pos = str_big->find(str_src, pos)) != std::string::npos) {
|
||||
str_big->replace(pos, src_len, str_dst);
|
||||
pos += dst_len;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief : Parse the data in the character string and transfer the data to the structure.
|
||||
* @param [in] string strLine : parsed string.
|
||||
* @param [in] int32_t *flagCtl : the number of char.
|
||||
* @param [in] int32_t *flagTap : the flag of char.
|
||||
* @param [in] YuvWPara *yuvScalerParaSet : yuv scaler param sets.
|
||||
* @param [in] ScalerCoefficientIndex *index : scaler index.
|
||||
*/
|
||||
void GetParaSet(std::string str_line, int32_t *flag_ctl, int32_t *flag_tap, YuvWPara *yuv_scaler_paraset,
|
||||
ScalerCoefficientIndex *index) {
|
||||
std::stringstream ss;
|
||||
StringReplace(&str_line, ",", " "); // Replaces commas in a string with spaces.
|
||||
ss.str(str_line);
|
||||
int32_t cnt = yuv_scaler_paraset->real_count; // Number of saved arrays.
|
||||
const int32_t arrTypeNum = 3;
|
||||
const int32_t initBracketNum = 3;
|
||||
|
||||
// {start,end}
|
||||
if ((*flag_ctl - initBracketNum) % arrTypeNum == 1) {
|
||||
char chTmp;
|
||||
ss >> chTmp >> yuv_scaler_paraset->scale[cnt].range.start >> yuv_scaler_paraset->scale[cnt].range.end;
|
||||
|
||||
if (ss.fail()) { // read failed.
|
||||
#ifndef DVPP_UTST
|
||||
ss.clear();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// taps_4, the second character in the square brackets is the start address of the array block.
|
||||
if ((*flag_ctl - initBracketNum) % arrTypeNum == 2) {
|
||||
while (1) {
|
||||
ss >> yuv_scaler_paraset->scale[cnt].taps_4[index->first_index++];
|
||||
if (ss.fail()) { // rerad failed.
|
||||
index->first_index = index->first_index - 1;
|
||||
ss.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (index->first_index == kScalerCoffNb4) { // read finish
|
||||
index->first_index = 0;
|
||||
*flag_tap = 0;
|
||||
ss.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// taps_6
|
||||
if ((*flag_ctl - initBracketNum) % arrTypeNum == 0) {
|
||||
while (1) {
|
||||
ss >> yuv_scaler_paraset->scale[cnt].taps_6[index->second_index++];
|
||||
if (ss.fail()) { // read failed.
|
||||
index->second_index = index->second_index - 1;
|
||||
ss.clear();
|
||||
break;
|
||||
}
|
||||
|
||||
if (index->second_index == kScalerCoffNb6) { // read finish.
|
||||
index->second_index = 0;
|
||||
*flag_tap = 0;
|
||||
ss.clear();
|
||||
++(yuv_scaler_paraset->real_count);
|
||||
*flag_ctl = *flag_ctl - 4; // The filtering parameter set has four large blocks.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int32_t CheckParamater(std::pair<bool, std::string> rlt, uint32_t i) {
|
||||
int32_t ret = dpSucc;
|
||||
if (rlt.first == false) {
|
||||
API_LOGE("Get real path failed. index = %u", i);
|
||||
return dpFail;
|
||||
}
|
||||
|
||||
if (IsDirectory(rlt.second)) {
|
||||
API_LOGE("It is a directory, not file path. index = %u", i);
|
||||
return dpFail;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Read the parameter set file and skip the comments in the file.
|
||||
int32_t ParseFileToVar(std::string *para_set_name, uint32_t yuv_scaler_paraset_size, YuvWPara *yuv_scaler_paraset) {
|
||||
int32_t ret = dpSucc;
|
||||
|
||||
VPC_CHECK_COND_FAIL_RETURN(para_set_name != nullptr, dpFail);
|
||||
VPC_CHECK_COND_FAIL_RETURN(yuv_scaler_paraset != nullptr, dpFail);
|
||||
|
||||
uint32_t i = 0;
|
||||
while (i < yuv_scaler_paraset_size && i < maxFileCount && (!para_set_name[i].empty())) {
|
||||
std::string str_line;
|
||||
|
||||
// Standardize the file path and check whether the path exists.
|
||||
std::pair<bool, std::string> rlt = GetRealpath(para_set_name[i]);
|
||||
ret = CheckParamater(rlt, i);
|
||||
if (ret != dpSucc) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::ifstream inFile(rlt.second);
|
||||
|
||||
int32_t flag_tap = 1;
|
||||
int32_t flag_ctl = 0;
|
||||
int32_t flag_anno = 0;
|
||||
ScalerCoefficientIndex index;
|
||||
const int32_t initBracketNum = 3;
|
||||
yuv_scaler_paraset[i].real_count = 0;
|
||||
|
||||
while (getline(inFile, str_line)) { // read each row of data.
|
||||
// Skip the comments.
|
||||
if (str_line.find("/*") != std::string::npos) {
|
||||
flag_anno = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flag_anno) {
|
||||
if (str_line.find("*/") != std::string::npos) {
|
||||
flag_anno = 0;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (str_line.find("//") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// cale the number of "{",check the location of the data.
|
||||
if (str_line.find("{") != std::string::npos) {
|
||||
flag_ctl++;
|
||||
flag_tap = 1;
|
||||
}
|
||||
|
||||
if (flag_ctl > initBracketNum && flag_tap == 1) { // parse params
|
||||
GetParaSet(str_line, &flag_ctl, &flag_tap, &yuv_scaler_paraset[i], &index);
|
||||
}
|
||||
}
|
||||
|
||||
inFile.close();
|
||||
++i;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
YuvWPara *YuvScalerParaSet::GetInstance(std::string *paraset_name, uint32_t yuv_scaler_paraset_size) {
|
||||
if (g_m_instance_ == nullptr) {
|
||||
(void)pthread_mutex_lock(&g_mutex_);
|
||||
if (g_m_instance_ == nullptr) {
|
||||
if (paraset_name == nullptr) {
|
||||
#ifndef API_MAR_UT
|
||||
#ifdef DVPP_UTST
|
||||
YuvWPara p_tmp[10]; // 10: 滤波参数集最大数
|
||||
p_tmp[0] = YUV_W_PARA;
|
||||
g_m_instance_ = p_tmp;
|
||||
#else
|
||||
auto p_tmp = static_cast<YuvWPara *>(malloc(sizeof(YuvWPara) * maxFileCount));
|
||||
if (p_tmp == nullptr) {
|
||||
API_LOGE("malloc YuvWPara fail!");
|
||||
g_m_instance_ = nullptr;
|
||||
(void)pthread_mutex_unlock(&g_mutex_);
|
||||
return g_m_instance_;
|
||||
}
|
||||
|
||||
uint32_t ret = memcpy_s(&p_tmp[0], sizeof(p_tmp[0]), &YUV_W_PARA, sizeof(YUV_W_PARA));
|
||||
if (ret != EOK) {
|
||||
API_LOGE("memcpy_s p_tmp[0] fail!");
|
||||
g_m_instance_ = nullptr;
|
||||
free(p_tmp);
|
||||
p_tmp = nullptr;
|
||||
(void)pthread_mutex_unlock(&g_mutex_);
|
||||
return g_m_instance_;
|
||||
}
|
||||
|
||||
g_m_instance_ = p_tmp;
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
auto p_tmp = static_cast<YuvWPara *>(malloc(sizeof(YuvWPara) * maxFileCount));
|
||||
if (p_tmp == nullptr) {
|
||||
#ifndef DVPP_UTST
|
||||
API_LOGE("malloc YuvWPara fail!");
|
||||
g_m_instance_ = nullptr;
|
||||
(void)pthread_mutex_unlock(&g_mutex_);
|
||||
return g_m_instance_;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ParseFileToVar(paraset_name, yuv_scaler_paraset_size, p_tmp) == -1) {
|
||||
free(p_tmp);
|
||||
g_m_instance_ = nullptr;
|
||||
} else {
|
||||
g_m_instance_ = p_tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
(void)pthread_mutex_unlock(&g_mutex_);
|
||||
}
|
||||
return g_m_instance_;
|
||||
}
|
||||
|
||||
// Searching for the index number of the filtering parameter by using the dichotomy
|
||||
int32_t GetScalerParamterIndex(uint32_t paramter, YuvWPara *paramterset) {
|
||||
int32_t count = paramterset->real_count;
|
||||
int32_t left = 0;
|
||||
int32_t right = count - 1;
|
||||
YuvScalerPara *scaler = paramterset->scale;
|
||||
int32_t index = 0;
|
||||
|
||||
if (paramter <= scalerRadio1Time) {
|
||||
index = 0;
|
||||
} else {
|
||||
paramter = paramter >> paramterInterval;
|
||||
while (left <= right) {
|
||||
index = (left + right) / 2; // 2-point search
|
||||
if (paramter > scaler[index].range.start && paramter <= scaler[index].range.end) {
|
||||
break;
|
||||
}
|
||||
if (paramter > scaler[index].range.end) {
|
||||
left = index + 1;
|
||||
} else if (paramter <= scaler[index].range.start) {
|
||||
right = index - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (left > right) {
|
||||
index = count - 1;
|
||||
}
|
||||
return index;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -121,6 +121,8 @@ constexpr char kResizeOp[] = "ResizeOp";
|
|||
constexpr char kResizeWithBBoxOp[] = "ResizeWithBBoxOp";
|
||||
constexpr char kSwapRedBlueOp[] = "SwapRedBlueOp";
|
||||
constexpr char kUniformAugOp[] = "UniformAugOp";
|
||||
constexpr char kSoftDvppDecodeRandomCropResizeJpegOp[] = "SoftDvppDecodeRandomCropResizeJpegOp";
|
||||
constexpr char kSoftDvppDecodeReiszeJpegOp[] = "SoftDvppDecodeReiszeJpegOp";
|
||||
|
||||
// text
|
||||
constexpr char kBasicTokenizerOp[] = "BasicTokenizerOp";
|
||||
|
|
|
@ -48,7 +48,7 @@ from .validators import check_prob, check_crop, check_resize_interpolation, chec
|
|||
check_mix_up_batch_c, check_normalize_c, check_random_crop, check_random_color_adjust, check_random_rotation, \
|
||||
check_range, check_resize, check_rescale, check_pad, check_cutout, check_uniform_augment_cpp, \
|
||||
check_bounding_box_augment_cpp, check_random_select_subpolicy_op, check_auto_contrast, check_random_affine, \
|
||||
FLOAT_MAX_INTEGER
|
||||
check_soft_dvpp_decode_random_crop_resize_jpeg, FLOAT_MAX_INTEGER
|
||||
|
||||
DE_C_INTER_MODE = {Inter.NEAREST: cde.InterpolationMode.DE_INTER_NEAREST_NEIGHBOUR,
|
||||
Inter.LINEAR: cde.InterpolationMode.DE_INTER_LINEAR,
|
||||
|
@ -878,3 +878,57 @@ class RandomSelectSubpolicy(cde.RandomSelectSubpolicyOp):
|
|||
@check_random_select_subpolicy_op
|
||||
def __init__(self, policy):
|
||||
super().__init__(policy)
|
||||
|
||||
|
||||
class SoftDvppDecodeResizeJpeg(cde.SoftDvppDecodeResizeJpegOp):
|
||||
"""
|
||||
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.
|
||||
|
||||
Args:
|
||||
size (Union[int, sequence]): The output size of the resized image.
|
||||
If size is an int, smaller edge of the image will be resized to this value with
|
||||
the same image aspect ratio.
|
||||
If size is a sequence of length 2, it should be (height, width).
|
||||
"""
|
||||
|
||||
@check_resize
|
||||
def __init__(self, size):
|
||||
if isinstance(size, int):
|
||||
size = (size, size)
|
||||
self.size = size
|
||||
super().__init__(*size)
|
||||
|
||||
|
||||
class SoftDvppDecodeRandomCropResizeJpeg(cde.SoftDvppDecodeRandomCropResizeJpegOp):
|
||||
"""
|
||||
Tensor operation to decode, random crop and resize jpeg image using the simulation algorithm of
|
||||
ascend series chip DVPP module.
|
||||
|
||||
The usage scenario is consistent with SoftDvppDecodeReiszeJpeg.
|
||||
|
||||
Args:
|
||||
size (Union[int, sequence], optional): The size of the output image.
|
||||
If size is an int, a square crop of size (size, size) is returned.
|
||||
If size is a sequence of length 2, it should be (height, width).
|
||||
scale (tuple, optional): Range (min, max) of respective size of the
|
||||
original size to be cropped (default=(0.08, 1.0)).
|
||||
ratio (tuple, optional): Range (min, max) of aspect ratio to be
|
||||
cropped (default=(3. / 4., 4. / 3.)).
|
||||
max_attempts (int, optional): The maximum number of attempts to propose a valid crop_area (default=10).
|
||||
If exceeded, fall back to use center_crop instead.
|
||||
"""
|
||||
|
||||
@check_soft_dvpp_decode_random_crop_resize_jpeg
|
||||
def __init__(self, size, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.), max_attempts=10):
|
||||
if isinstance(size, int):
|
||||
size = (size, size)
|
||||
self.size = size
|
||||
self.scale = scale
|
||||
self.ratio = ratio
|
||||
self.max_attempts = max_attempts
|
||||
super().__init__(*size, *scale, *ratio, max_attempts)
|
||||
|
|
|
@ -175,30 +175,35 @@ def check_resize(method):
|
|||
return new_method
|
||||
|
||||
|
||||
def check_size_scale_ration_max_attempts_paras(size, scale, ratio, max_attempts):
|
||||
"""Wrapper method to check the parameters of RandomCropDecodeResize and SoftDvppDecodeRandomCropResizeJpeg."""
|
||||
|
||||
check_crop_size(size)
|
||||
if scale is not None:
|
||||
type_check(scale, (tuple,), "scale")
|
||||
type_check_list(scale, (float, int), "scale")
|
||||
check_range(scale, [0, FLOAT_MAX_INTEGER])
|
||||
if scale[0] > scale[1]:
|
||||
raise ValueError("scale should be in (min,max) format. Got (max,min).")
|
||||
if ratio is not None:
|
||||
type_check(ratio, (tuple,), "ratio")
|
||||
type_check_list(ratio, (float, int), "ratio")
|
||||
check_range(ratio, [0, FLOAT_MAX_INTEGER])
|
||||
if ratio[0] > ratio[1]:
|
||||
raise ValueError("ratio should be in (min,max) format. Got (max,min).")
|
||||
if max_attempts is not None:
|
||||
check_value(max_attempts, (1, FLOAT_MAX_INTEGER))
|
||||
|
||||
|
||||
def check_random_resize_crop(method):
|
||||
"""A wrapper that wraps a parameter checker to the original function(random resize crop operation)."""
|
||||
|
||||
@wraps(method)
|
||||
def new_method(self, *args, **kwargs):
|
||||
[size, scale, ratio, interpolation, max_attempts], _ = parse_user_args(method, *args, **kwargs)
|
||||
check_crop_size(size)
|
||||
|
||||
if scale is not None:
|
||||
type_check(scale, (tuple,), "scale")
|
||||
type_check_list(scale, (float, int), "scale")
|
||||
check_range(scale, [0, FLOAT_MAX_INTEGER])
|
||||
if scale[0] > scale[1]:
|
||||
raise ValueError("scale should be in (min,max) format. Got (max,min).")
|
||||
if ratio is not None:
|
||||
type_check(ratio, (tuple,), "ratio")
|
||||
type_check_list(ratio, (float, int), "ratio")
|
||||
check_range(ratio, [0, FLOAT_MAX_INTEGER])
|
||||
if ratio[0] > ratio[1]:
|
||||
raise ValueError("ratio should be in (min,max) format. Got (max,min).")
|
||||
if interpolation is not None:
|
||||
type_check(interpolation, (Inter,), "interpolation")
|
||||
if max_attempts is not None:
|
||||
check_value(max_attempts, (1, FLOAT_MAX_INTEGER))
|
||||
check_size_scale_ration_max_attempts_paras(size, scale, ratio, max_attempts)
|
||||
|
||||
return method(self, *args, **kwargs)
|
||||
|
||||
|
@ -658,3 +663,15 @@ def check_random_select_subpolicy_op(method):
|
|||
return method(self, *args, **kwargs)
|
||||
|
||||
return new_method
|
||||
|
||||
|
||||
def check_soft_dvpp_decode_random_crop_resize_jpeg(method):
|
||||
"""Wrapper method to check the parameters of SoftDvppDecodeRandomCropResizeJpeg."""
|
||||
|
||||
@wraps(method)
|
||||
def new_method(self, *args, **kwargs):
|
||||
[size, scale, ratio, max_attempts], _ = parse_user_args(method, *args, **kwargs)
|
||||
check_size_scale_ration_max_attempts_paras(size, scale, ratio, max_attempts)
|
||||
|
||||
return method(self, *args, **kwargs)
|
||||
return new_method
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
# Copyright 2020 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.
|
||||
# ==============================================================================
|
||||
"""
|
||||
Testing soft dvpp SoftDvppDecodeResizeJpeg and SoftDvppDecodeRandomCropResizeJpeg in DE
|
||||
"""
|
||||
import mindspore.dataset as ds
|
||||
import mindspore.dataset.transforms.vision.c_transforms as vision
|
||||
from mindspore import log as logger
|
||||
from util import diff_mse, visualize_image
|
||||
|
||||
DATA_DIR = ["../data/dataset/test_tf_file_3_images/train-0000-of-0001.data"]
|
||||
SCHEMA_DIR = "../data/dataset/test_tf_file_3_images/datasetSchema.json"
|
||||
|
||||
|
||||
def test_soft_dvpp_decode_resize_jpeg(plot=False):
|
||||
"""
|
||||
Test SoftDvppDecodeResizeJpeg op
|
||||
"""
|
||||
logger.info("test_random_decode_resize_op")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
decode_op = vision.Decode()
|
||||
resize_op = vision.Resize((256, 512))
|
||||
data1 = data1.map(input_columns=["image"], operations=[decode_op, resize_op])
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
soft_dvpp_decode_resize_op = vision.SoftDvppDecodeResizeJpeg((256, 512))
|
||||
data2 = data2.map(input_columns=["image"], operations=soft_dvpp_decode_resize_op)
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(), data2.create_dict_iterator()):
|
||||
if num_iter > 0:
|
||||
break
|
||||
image1 = item1["image"]
|
||||
image2 = item2["image"]
|
||||
mse = diff_mse(image1, image2)
|
||||
assert mse <= 0.02
|
||||
logger.info("random_crop_decode_resize_op_{}, mse: {}".format(num_iter + 1, mse))
|
||||
if plot:
|
||||
visualize_image(image1, image2, mse)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
def test_soft_dvpp_decode_random_crop_resize_jpeg(plot=False):
|
||||
"""
|
||||
Test SoftDvppDecodeRandomCropResizeJpeg op
|
||||
"""
|
||||
logger.info("test_random_decode_resize_op")
|
||||
|
||||
# First dataset
|
||||
data1 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
random_crop_decode_resize_op = vision.RandomCropDecodeResize((256, 512), (1, 1), (0.5, 0.5))
|
||||
data1 = data1.map(input_columns=["image"], operations=random_crop_decode_resize_op)
|
||||
|
||||
# Second dataset
|
||||
data2 = ds.TFRecordDataset(DATA_DIR, SCHEMA_DIR, columns_list=["image"], shuffle=False)
|
||||
soft_dvpp_random_crop_decode_resize_op = vision.SoftDvppDecodeRandomCropResizeJpeg((256, 512), (1, 1), (0.5, 0.5))
|
||||
data2 = data2.map(input_columns=["image"], operations=soft_dvpp_random_crop_decode_resize_op)
|
||||
|
||||
num_iter = 0
|
||||
for item1, item2 in zip(data1.create_dict_iterator(), data2.create_dict_iterator()):
|
||||
if num_iter > 0:
|
||||
break
|
||||
image1 = item1["image"]
|
||||
image2 = item2["image"]
|
||||
mse = diff_mse(image1, image2)
|
||||
assert mse <= 0.06
|
||||
logger.info("random_crop_decode_resize_op_{}, mse: {}".format(num_iter + 1, mse))
|
||||
if plot:
|
||||
visualize_image(image1, image2, mse)
|
||||
num_iter += 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_soft_dvpp_decode_resize_jpeg(plot=True)
|
||||
test_soft_dvpp_decode_random_crop_resize_jpeg(plot=True)
|
Loading…
Reference in New Issue