From: @xulei2020 Reviewed-by: Signed-off-by:tags/v1.2.0-rc1
| @@ -2,4 +2,5 @@ file(GLOB_RECURSE _CURRENT_SRC_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc" | |||||
| set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD) | set_property(SOURCE ${_CURRENT_SRC_FILES} PROPERTY COMPILE_DEFINITIONS SUBMODULE_ID=mindspore::SubModuleId::SM_MD) | ||||
| add_library(lite-cv OBJECT | add_library(lite-cv OBJECT | ||||
| image_process.cc | image_process.cc | ||||
| warp_affine.cc | |||||
| lite_mat.cc) | lite_mat.cc) | ||||
| @@ -28,11 +28,34 @@ | |||||
| #endif | #endif | ||||
| #endif | #endif | ||||
| namespace mindspore { | |||||
| namespace dataset { | |||||
| #ifdef PLATFORM_ARM64 | |||||
| #define R2GRAY 9798 | |||||
| #define G2GRAY 19235 | |||||
| #define B2GRAY 3735 | |||||
| #define GRAYSHIFT 15 | |||||
| #define GRAYSHIFT_DELTA (1 << (GRAYSHIFT - 1)) | |||||
| #else | |||||
| #define R2GRAY 77 | |||||
| #define G2GRAY 150 | |||||
| #define B2GRAY 29 | |||||
| #define GRAYSHIFT 8 | |||||
| #endif | |||||
| #define YSCALE 0x0101 | |||||
| #define UTOB (-128) | |||||
| #define UTOG 25 | |||||
| #define VTOR (-102) | |||||
| #define VTOG 52 | |||||
| #define YTOG 18997 | |||||
| #define YTOGB (-1160) | |||||
| #define BTOB (UTOB * 128 + YTOGB) | |||||
| #define BTOG (UTOG * 128 + VTOG * 128 + YTOGB) | |||||
| #define BTOR (VTOR * 128 + YTOGB) | |||||
| #define Equ(a, b) ((std::fabs((a) - (b)) < 1e-6)) | #define Equ(a, b) ((std::fabs((a) - (b)) < 1e-6)) | ||||
| namespace mindspore { | |||||
| namespace dataset { | |||||
| static inline void InitBilinearWeight(int *data_ptr, int16_t *weight_ptr, double scale, int dst_length, int src_length, | static inline void InitBilinearWeight(int *data_ptr, int16_t *weight_ptr, double scale, int dst_length, int src_length, | ||||
| int a) { | int a) { | ||||
| const int RESIZE_SCALE = 1 << 11; | const int RESIZE_SCALE = 1 << 11; | ||||
| @@ -374,6 +397,79 @@ static bool ConvertYUV420SPToBGR(const uint8_t *data, LDataType data_type, bool | |||||
| return true; | return true; | ||||
| } | } | ||||
| #ifdef PLATFORM_ARM64 | |||||
| static uint8x8_t RGBToGray(const uint16x8_t &r_value, const uint16x8_t &g_value, const uint16x8_t &b_value, | |||||
| const uint16x4_t &r2y_value, const uint16x4_t &g2y_value, const uint16x4_t &b2y_value) { | |||||
| uint32x4_t dst0_value = vmull_u16(vget_low_u16(g_value), g2y_value); | |||||
| uint32x4_t dst1_value = vmull_u16(vget_high_u16(g_value), g2y_value); | |||||
| dst0_value = vmlal_u16(dst0_value, vget_low_u16(r_value), r2y_value); | |||||
| dst1_value = vmlal_u16(dst1_value, vget_high_u16(r_value), r2y_value); | |||||
| dst0_value = vmlal_u16(dst0_value, vget_low_u16(b_value), b2y_value); | |||||
| dst1_value = vmlal_u16(dst1_value, vget_high_u16(b_value), b2y_value); | |||||
| uint8x8_t v_gray = vqmovn_u16(vcombine_u16(vrshrn_n_u32(dst0_value, GRAYSHIFT), vrshrn_n_u32(dst1_value, GRAYSHIFT))); | |||||
| return v_gray; | |||||
| } | |||||
| static bool ConvertRGBAToGRAY_Neon(const uint8_t *srcBase, uint8_t *dstBase, int w, int h) { | |||||
| const uint32_t r_to_gray = R2GRAY; | |||||
| const uint32_t g_to_gray = G2GRAY; | |||||
| const uint32_t b_to_gray = B2GRAY; | |||||
| uint16x4_t r2y_value = vdup_n_u16(R2GRAY); | |||||
| uint16x4_t g2y_value = vdup_n_u16(G2GRAY); | |||||
| uint16x4_t b2y_value = vdup_n_u16(B2GRAY); | |||||
| size_t w16b = w >= 15 ? w - 15 : 0; | |||||
| size_t w8b = w >= 7 ? w - 7 : 0; | |||||
| for (size_t i = 0; i < h; ++i) { | |||||
| const uint8_t *src_ptr = srcBase + w * i * 4; | |||||
| uint8_t *dst_ptr = dstBase + w * i * 4; | |||||
| size_t src_j = 0u; | |||||
| size_t dst_j = 0u; | |||||
| for (; dst_j < w16b; src_j += 64, dst_j += 16) { | |||||
| uint8x16x4_t src_value0 = vld4q_u8(src_ptr + src_j); | |||||
| // 0 | |||||
| uint16x8_t r_value = vmovl_u8(vget_low_u8(src_value0.val[0])); | |||||
| uint16x8_t g_value = vmovl_u8(vget_low_u8(src_value0.val[1])); | |||||
| uint16x8_t b_value = vmovl_u8(vget_low_u8(src_value0.val[2])); | |||||
| uint8x8_t gray_value0 = RGBToGray(r_value, g_value, b_value, r2y_value, g2y_value, b2y_value); | |||||
| r_value = vmovl_u8(vget_high_u8(src_value0.val[0])); | |||||
| g_value = vmovl_u8(vget_high_u8(src_value0.val[1])); | |||||
| b_value = vmovl_u8(vget_high_u8(src_value0.val[2])); | |||||
| uint8x8_t gray_value1 = RGBToGray(r_value, g_value, b_value, r2y_value, g2y_value, b2y_value); | |||||
| vst1q_u8(dst_ptr + dst_j, vcombine_u8(gray_value0, gray_value1)); | |||||
| } | |||||
| if (dst_j < w8b) { | |||||
| uint8x8x4_t v_src = vld4_u8(src_ptr + src_j); | |||||
| uint16x8_t r_value = vmovl_u8(v_src.val[0]); | |||||
| uint16x8_t g_value = vmovl_u8(v_src.val[1]); | |||||
| uint16x8_t b_value = vmovl_u8(v_src.val[2]); | |||||
| uint8x8_t gray_value = RGBToGray(r_value, g_value, b_value, r2y_value, g2y_value, b2y_value); | |||||
| vst1_u8(dst_ptr + dst_j, gray_value); | |||||
| src_j += 32; | |||||
| dst_j += 8; | |||||
| } | |||||
| for (; dst_j < w; src_j += 4, dst_j++) { | |||||
| uint32_t val = src_ptr[src_j] * r_to_gray + src_ptr[src_j + 1] * g_to_gray + src_ptr[src_j + 2] * b_to_gray; | |||||
| dst_ptr[dst_j] = U32TOU8CAST((val + GRAYSHIFT_DELTA) >> GRAYSHIFT); | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| #endif | |||||
| static bool ConvertRGBAToGRAY(const unsigned char *data, LDataType data_type, int w, int h, LiteMat &mat) { | static bool ConvertRGBAToGRAY(const unsigned char *data, LDataType data_type, int w, int h, LiteMat &mat) { | ||||
| if (data_type == LDataType::UINT8) { | if (data_type == LDataType::UINT8) { | ||||
| mat.Init(w, h, 1, LDataType::UINT8); | mat.Init(w, h, 1, LDataType::UINT8); | ||||
| @@ -382,6 +478,9 @@ static bool ConvertRGBAToGRAY(const unsigned char *data, LDataType data_type, in | |||||
| } | } | ||||
| unsigned char *ptr = mat; | unsigned char *ptr = mat; | ||||
| const unsigned char *data_ptr = data; | const unsigned char *data_ptr = data; | ||||
| #ifdef PLATFORM_ARM64 | |||||
| ConvertRGBAToGRAY_Neon(data_ptr, ptr, w, h); | |||||
| #else | |||||
| for (int y = 0; y < h; y++) { | for (int y = 0; y < h; y++) { | ||||
| for (int x = 0; x < w; x++) { | for (int x = 0; x < w; x++) { | ||||
| *ptr = (data_ptr[2] * B2GRAY + data_ptr[1] * G2GRAY + data_ptr[0] * R2GRAY) >> GRAYSHIFT; | *ptr = (data_ptr[2] * B2GRAY + data_ptr[1] * G2GRAY + data_ptr[0] * R2GRAY) >> GRAYSHIFT; | ||||
| @@ -389,6 +488,7 @@ static bool ConvertRGBAToGRAY(const unsigned char *data, LDataType data_type, in | |||||
| data_ptr += 4; | data_ptr += 4; | ||||
| } | } | ||||
| } | } | ||||
| #endif | |||||
| } else { | } else { | ||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -30,22 +30,6 @@ namespace dataset { | |||||
| #define INT16_CAST(X) \ | #define INT16_CAST(X) \ | ||||
| static_cast<int16_t>(::std::min(::std::max(static_cast<int>(X + (X >= 0.f ? 0.5f : -0.5f)), -32768), 32767)); | static_cast<int16_t>(::std::min(::std::max(static_cast<int>(X + (X >= 0.f ? 0.5f : -0.5f)), -32768), 32767)); | ||||
| #define R2GRAY 77 | |||||
| #define G2GRAY 150 | |||||
| #define B2GRAY 29 | |||||
| #define GRAYSHIFT 8 | |||||
| #define YSCALE 0x0101 | |||||
| #define UTOB (-128) | |||||
| #define UTOG 25 | |||||
| #define VTOR (-102) | |||||
| #define VTOG 52 | |||||
| #define YTOG 18997 | |||||
| #define YTOGB (-1160) | |||||
| #define BTOB (UTOB * 128 + YTOGB) | |||||
| #define BTOG (UTOG * 128 + VTOG * 128 + YTOGB) | |||||
| #define BTOR (VTOR * 128 + YTOGB) | |||||
| enum PaddBorderType { PADD_BORDER_CONSTANT = 0, PADD_BORDER_REPLICATE = 1 }; | enum PaddBorderType { PADD_BORDER_CONSTANT = 0, PADD_BORDER_REPLICATE = 1 }; | ||||
| struct BoxesConfig { | struct BoxesConfig { | ||||
| @@ -107,6 +91,14 @@ void ConvertBoxes(std::vector<std::vector<float>> &boxes, const std::vector<std: | |||||
| std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std::vector<float> &all_scores, float thres, | std::vector<int> ApplyNms(const std::vector<std::vector<float>> &all_boxes, std::vector<float> &all_scores, float thres, | ||||
| int max_boxes); | int max_boxes); | ||||
| /// \brief affine image by linear | |||||
| bool WarpAffineBilinear(const LiteMat &src, LiteMat &dst, const LiteMat &M, int dst_w, int dst_h, | |||||
| PaddBorderType borderType, std::vector<uint8_t> &borderValue); | |||||
| /// \brief perspective image by linear | |||||
| bool WarpPerspectiveBilinear(const LiteMat &src, LiteMat &dst, const LiteMat &M, int dst_w, int dst_h, | |||||
| PaddBorderType borderType, std::vector<uint8_t> &borderValue); | |||||
| } // namespace dataset | } // namespace dataset | ||||
| } // namespace mindspore | } // namespace mindspore | ||||
| #endif // IMAGE_PROCESS_H_ | #endif // IMAGE_PROCESS_H_ | ||||
| @@ -39,6 +39,7 @@ LiteMat::LiteMat() { | |||||
| size_ = 0; | size_ = 0; | ||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| setSteps(0, 0, 0); | |||||
| } | } | ||||
| LiteMat::LiteMat(int width, LDataType data_type) { | LiteMat::LiteMat(int width, LDataType data_type) { | ||||
| @@ -52,6 +53,7 @@ LiteMat::LiteMat(int width, LDataType data_type) { | |||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| Init(width, data_type); | Init(width, data_type); | ||||
| } | } | ||||
| @@ -66,6 +68,7 @@ LiteMat::LiteMat(int width, int height, LDataType data_type) { | |||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| Init(width, height, data_type); | Init(width, height, data_type); | ||||
| } | } | ||||
| @@ -80,6 +83,7 @@ LiteMat::LiteMat(int width, int height, void *p_data, LDataType data_type) { | |||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| Init(width, height, p_data, data_type); | Init(width, height, p_data, data_type); | ||||
| } | } | ||||
| @@ -94,6 +98,7 @@ LiteMat::LiteMat(int width, int height, int channel, LDataType data_type) { | |||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| Init(width, height, channel, data_type); | Init(width, height, channel, data_type); | ||||
| } | } | ||||
| @@ -108,6 +113,7 @@ LiteMat::LiteMat(int width, int height, int channel, void *p_data, LDataType dat | |||||
| data_type_ = LDataType::UINT8; | data_type_ = LDataType::UINT8; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| Init(width, height, channel, p_data, data_type); | Init(width, height, channel, p_data, data_type); | ||||
| } | } | ||||
| @@ -130,11 +136,18 @@ LiteMat::LiteMat(const LiteMat &m) { | |||||
| data_type_ = m.data_type_; | data_type_ = m.data_type_; | ||||
| ref_count_ = m.ref_count_; | ref_count_ = m.ref_count_; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(m.steps_[0], m.steps_[1], m.steps_[2]); | |||||
| if (ref_count_) { | if (ref_count_) { | ||||
| addRef(ref_count_, 1); | addRef(ref_count_, 1); | ||||
| } | } | ||||
| } | } | ||||
| void LiteMat::setSteps(int c0, int c1, int c2) { | |||||
| steps_[0] = c0; | |||||
| steps_[1] = c1; | |||||
| steps_[2] = c2; | |||||
| } | |||||
| LiteMat &LiteMat::operator=(const LiteMat &m) { | LiteMat &LiteMat::operator=(const LiteMat &m) { | ||||
| if (this == &m) { | if (this == &m) { | ||||
| return *this; | return *this; | ||||
| @@ -154,7 +167,8 @@ LiteMat &LiteMat::operator=(const LiteMat &m) { | |||||
| dims_ = m.dims_; | dims_ = m.dims_; | ||||
| data_type_ = m.data_type_; | data_type_ = m.data_type_; | ||||
| ref_count_ = m.ref_count_; | ref_count_ = m.ref_count_; | ||||
| size_ = 0; | |||||
| setSteps(m.steps_[0], m.steps_[1], m.steps_[2]); | |||||
| size_ = m.size_; | |||||
| return *this; | return *this; | ||||
| } | } | ||||
| @@ -171,6 +185,7 @@ void LiteMat::Init(int width, LDataType data_type) { | |||||
| data_ptr_ = AlignMalloc(size_); | data_ptr_ = AlignMalloc(size_); | ||||
| ref_count_ = new int[1]; | ref_count_ = new int[1]; | ||||
| *ref_count_ = 1; | *ref_count_ = 1; | ||||
| steps_[0] = elem_size_; | |||||
| } | } | ||||
| void LiteMat::Init(int width, int height, LDataType data_type) { | void LiteMat::Init(int width, int height, LDataType data_type) { | ||||
| @@ -186,6 +201,8 @@ void LiteMat::Init(int width, int height, LDataType data_type) { | |||||
| data_ptr_ = AlignMalloc(size_); | data_ptr_ = AlignMalloc(size_); | ||||
| ref_count_ = new int[1]; | ref_count_ = new int[1]; | ||||
| *ref_count_ = 1; | *ref_count_ = 1; | ||||
| steps_[1] = elem_size_; | |||||
| steps_[0] = width_ * steps_[1]; | |||||
| } | } | ||||
| void LiteMat::Init(int width, int height, void *p_data, LDataType data_type) { | void LiteMat::Init(int width, int height, void *p_data, LDataType data_type) { | ||||
| @@ -199,6 +216,8 @@ void LiteMat::Init(int width, int height, void *p_data, LDataType data_type) { | |||||
| size_ = c_step_ * channel_ * elem_size_; | size_ = c_step_ * channel_ * elem_size_; | ||||
| data_ptr_ = p_data; | data_ptr_ = p_data; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| steps_[1] = elem_size_; | |||||
| steps_[0] = width_ * steps_[1]; | |||||
| } | } | ||||
| void LiteMat::Init(int width, int height, int channel, LDataType data_type) { | void LiteMat::Init(int width, int height, int channel, LDataType data_type) { | ||||
| @@ -214,6 +233,10 @@ void LiteMat::Init(int width, int height, int channel, LDataType data_type) { | |||||
| data_ptr_ = AlignMalloc(size_); | data_ptr_ = AlignMalloc(size_); | ||||
| ref_count_ = new int[1]; | ref_count_ = new int[1]; | ||||
| *ref_count_ = 1; | *ref_count_ = 1; | ||||
| steps_[2] = elem_size_; | |||||
| steps_[1] = channel * steps_[2]; | |||||
| steps_[0] = width_ * steps_[1]; | |||||
| } | } | ||||
| void LiteMat::Init(int width, int height, int channel, void *p_data, LDataType data_type) { | void LiteMat::Init(int width, int height, int channel, void *p_data, LDataType data_type) { | ||||
| @@ -227,6 +250,9 @@ void LiteMat::Init(int width, int height, int channel, void *p_data, LDataType d | |||||
| size_ = c_step_ * channel_ * elem_size_; | size_ = c_step_ * channel_ * elem_size_; | ||||
| data_ptr_ = p_data; | data_ptr_ = p_data; | ||||
| ref_count_ = nullptr; | ref_count_ = nullptr; | ||||
| steps_[2] = elem_size_; | |||||
| steps_[1] = channel * steps_[2]; | |||||
| steps_[0] = width_ * steps_[1]; | |||||
| } | } | ||||
| bool LiteMat::IsEmpty() const { return data_ptr_ == nullptr || c_step_ * channel_ == 0; } | bool LiteMat::IsEmpty() const { return data_ptr_ == nullptr || c_step_ * channel_ == 0; } | ||||
| @@ -248,6 +274,7 @@ void LiteMat::Release() { | |||||
| c_step_ = 0; | c_step_ = 0; | ||||
| ref_count_ = 0; | ref_count_ = 0; | ||||
| size_ = 0; | size_ = 0; | ||||
| setSteps(0, 0, 0); | |||||
| } | } | ||||
| void *LiteMat::AlignMalloc(unsigned int size) { | void *LiteMat::AlignMalloc(unsigned int size) { | ||||
| @@ -271,6 +298,31 @@ void LiteMat::AlignFree(void *ptr) { | |||||
| inline void LiteMat::InitElemSize(LDataType data_type) { elem_size_ = data_type.SizeInBytes(); } | inline void LiteMat::InitElemSize(LDataType data_type) { elem_size_ = data_type.SizeInBytes(); } | ||||
| bool LiteMat::GetROI(int x, int y, int w, int h, LiteMat &m) { | |||||
| if (x < 0 || y < 0 || x + w > width_ || h + y > height_) { | |||||
| return false; | |||||
| } | |||||
| if (!m.IsEmpty()) { | |||||
| m.Release(); | |||||
| } | |||||
| if (ref_count_) { | |||||
| addRef(ref_count_, 1); | |||||
| } | |||||
| m.height_ = h; | |||||
| m.width_ = w; | |||||
| m.dims_ = dims_; | |||||
| m.elem_size_ = elem_size_; | |||||
| m.data_ptr_ = reinterpret_cast<uint8_t *>(data_ptr_) + y * steps_[0] + x * elem_size_ * channel_; | |||||
| m.channel_ = channel_; | |||||
| m.c_step_ = c_step_; | |||||
| m.data_type_ = data_type_; | |||||
| m.ref_count_ = ref_count_; | |||||
| m.setSteps(steps_[0], steps_[1], steps_[2]); | |||||
| return true; | |||||
| } | |||||
| template <typename T> | template <typename T> | ||||
| inline void SubtractImpl(const T *src0, const T *src1, T *dst, int64_t total_size) { | inline void SubtractImpl(const T *src0, const T *src1, T *dst, int64_t total_size) { | ||||
| for (int64_t i = 0; i < total_size; i++) { | for (int64_t i = 0; i < total_size; i++) { | ||||
| @@ -24,6 +24,7 @@ namespace mindspore { | |||||
| namespace dataset { | namespace dataset { | ||||
| #define ALIGN 16 | #define ALIGN 16 | ||||
| #define MAX_DIMS 3 | |||||
| template <typename T> | template <typename T> | ||||
| struct Chn1 { | struct Chn1 { | ||||
| @@ -121,6 +122,8 @@ enum LPixelType { | |||||
| NV122BGR = 7, | NV122BGR = 7, | ||||
| }; | }; | ||||
| enum WARP_BORDER_MODE { WARP_BORDER_MODE_CONSTANT }; | |||||
| class LDataType { | class LDataType { | ||||
| public: | public: | ||||
| enum Type : uint8_t { | enum Type : uint8_t { | ||||
| @@ -137,6 +140,7 @@ class LDataType { | |||||
| FLOAT16, | FLOAT16, | ||||
| FLOAT32, | FLOAT32, | ||||
| FLOAT64, | FLOAT64, | ||||
| DOUBLE, | |||||
| NUM_OF_TYPES | NUM_OF_TYPES | ||||
| }; | }; | ||||
| @@ -179,6 +183,7 @@ class LDataType { | |||||
| 2, // FLOAT16 | 2, // FLOAT16 | ||||
| 4, // FLOAT32 | 4, // FLOAT32 | ||||
| 8, // FLOAT64 | 8, // FLOAT64 | ||||
| 8, // DOUBLE | |||||
| }; | }; | ||||
| Type type_; | Type type_; | ||||
| @@ -213,6 +218,8 @@ class LiteMat { | |||||
| void Init(int width, int height, int channel, void *p_data, LDataType data_type = LDataType::UINT8); | void Init(int width, int height, int channel, void *p_data, LDataType data_type = LDataType::UINT8); | ||||
| bool GetROI(int x, int y, int w, int h, LiteMat &dst); // NOLINT | |||||
| bool IsEmpty() const; | bool IsEmpty() const; | ||||
| void Release(); | void Release(); | ||||
| @@ -229,6 +236,14 @@ class LiteMat { | |||||
| return reinterpret_cast<const T *>(data_ptr_); | return reinterpret_cast<const T *>(data_ptr_); | ||||
| } | } | ||||
| template <typename T> | |||||
| inline T *ptr(int w) const { | |||||
| if (IsEmpty()) { | |||||
| return nullptr; | |||||
| } | |||||
| return reinterpret_cast<T *>(reinterpret_cast<unsigned char *>(data_ptr_) + steps_[0] * w); | |||||
| } | |||||
| private: | private: | ||||
| /// \brief apply for memory alignment | /// \brief apply for memory alignment | ||||
| void *AlignMalloc(unsigned int size); | void *AlignMalloc(unsigned int size); | ||||
| @@ -241,6 +256,8 @@ class LiteMat { | |||||
| /// \brief add reference | /// \brief add reference | ||||
| int addRef(int *p, int value); | int addRef(int *p, int value); | ||||
| void setSteps(int c0, int c1, int c2); | |||||
| public: | public: | ||||
| void *data_ptr_ = nullptr; | void *data_ptr_ = nullptr; | ||||
| int elem_size_; | int elem_size_; | ||||
| @@ -252,6 +269,7 @@ class LiteMat { | |||||
| size_t size_; | size_t size_; | ||||
| LDataType data_type_; | LDataType data_type_; | ||||
| int *ref_count_; | int *ref_count_; | ||||
| size_t steps_[MAX_DIMS]; | |||||
| }; | }; | ||||
| /// \brief Calculates the difference between the two images for each element | /// \brief Calculates the difference between the two images for each element | ||||
| @@ -0,0 +1,522 @@ | |||||
| /** | |||||
| * Copyright 2021 Huawei Technologies Co., Ltd | |||||
| * | |||||
| * Licensed under the Apache License, Version 2.0 (the "License"); | |||||
| * you may not use this file except in compliance with the License. | |||||
| * You may obtain a copy of the License at | |||||
| * | |||||
| * http://www.apache.org/licenses/LICENSE-2.0 | |||||
| * | |||||
| * Unless required by applicable law or agreed to in writing, software | |||||
| * distributed under the License is distributed on an "AS IS" BASIS, | |||||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
| * See the License for the specific language governing permissions and | |||||
| * limitations under the License. | |||||
| */ | |||||
| #include <limits.h> | |||||
| #include <math.h> | |||||
| #include <vector> | |||||
| #include "lite_cv/lite_mat.h" | |||||
| #include "lite_cv/image_process.h" | |||||
| #ifdef ENABLE_ANDROID | |||||
| #if defined(__arm__) || defined(__aarch64__) || defined(_M_ARM) || defined(_M_ARM64) | |||||
| #define USE_NEON | |||||
| #include <arm_neon.h> | |||||
| #endif | |||||
| #endif | |||||
| #define BITS 5 | |||||
| #define BITS1 15 | |||||
| #define TAB_SZ (1 << BITS) | |||||
| #define TAB_SZ2 (TAB_SZ * TAB_SZ) | |||||
| #define U32TOU8CAST(value) ((uint8_t)std::min(value, (uint32_t)UCHAR_MAX)) | |||||
| #define FLOATTOSHORT(value) (IntCastShort(round(value))) | |||||
| #define REMAP_SCALE (1 << 15) | |||||
| #define INTTOUCHAR(v) ((uint8_t)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0)) | |||||
| #define SrcValue(y, x) (reinterpret_cast<double *>(src + y * 3))[x] | |||||
| #define DstValue(y, x) (reinterpret_cast<double *>(dst + y * 3))[x] | |||||
| namespace mindspore { | |||||
| namespace dataset { | |||||
| static int16_t BWBlock_i[TAB_SZ2][2][2]; | |||||
| static double GetDet3(double *src) { | |||||
| double a1 = SrcValue(0, 0) * (SrcValue(1, 1) * SrcValue(2, 2) - SrcValue(1, 2) * SrcValue(2, 1)); | |||||
| double a2 = SrcValue(0, 1) * (SrcValue(1, 0) * SrcValue(2, 2) - SrcValue(1, 2) * SrcValue(2, 0)); | |||||
| double a3 = SrcValue(0, 2) * (SrcValue(1, 0) * SrcValue(2, 1) - SrcValue(1, 1) * SrcValue(2, 0)); | |||||
| return a1 - a2 + a3; | |||||
| } | |||||
| static int16_t IntCastShort(int value) { | |||||
| return (int16_t)((unsigned)(value - SHRT_MIN) <= (unsigned)USHRT_MAX ? value : value > 0 ? SHRT_MAX : SHRT_MIN); | |||||
| } | |||||
| static void InitWBlockInter(float *wBlock, int wBlockSz) { | |||||
| float scale = 1.f / wBlockSz; | |||||
| for (int i = 0; i < wBlockSz; i++, wBlock += 2) { | |||||
| float value = (i * scale); | |||||
| wBlock[0] = 1.f - value; | |||||
| wBlock[1] = value; | |||||
| } | |||||
| } | |||||
| static const void *InitWBlock() { | |||||
| static bool initWB = false; | |||||
| int16_t *iWBlock = 0; | |||||
| int ks = 2; | |||||
| iWBlock = BWBlock_i[0][0]; | |||||
| if (!initWB) { | |||||
| float *_wblock = new float[8 * TAB_SZ]; | |||||
| int i, j, h1, h2; | |||||
| InitWBlockInter(_wblock, TAB_SZ); | |||||
| for (i = 0; i < TAB_SZ; i++) { | |||||
| for (j = 0; j < TAB_SZ; j++, iWBlock += ks * ks) { | |||||
| int sum_i = 0; | |||||
| for (h1 = 0; h1 < ks; h1++) { | |||||
| float vy = _wblock[i * ks + h1]; | |||||
| for (h2 = 0; h2 < ks; h2++) { | |||||
| float v = vy * _wblock[j * ks + h2]; | |||||
| sum_i += iWBlock[h1 * ks + h2] = FLOATTOSHORT(v * REMAP_SCALE); | |||||
| } | |||||
| } | |||||
| if (sum_i != REMAP_SCALE) { | |||||
| int df = sum_i - REMAP_SCALE; | |||||
| int ks2 = 1; | |||||
| int tk1 = ks2; | |||||
| int tk2 = ks2; | |||||
| int mtk1 = ks2; | |||||
| int mtk2 = ks2; | |||||
| for (h1 = ks2; h1 < ks2 + 2; h1++) { | |||||
| for (h2 = ks2; h2 < ks2 + 2; h2++) { | |||||
| if (iWBlock[h1 * ks + h2] < iWBlock[mtk1 * ks + mtk2]) { | |||||
| mtk1 = h1, mtk2 = h2; | |||||
| } else if (iWBlock[h1 * ks + h2] > iWBlock[tk1 * ks + tk2]) { | |||||
| tk1 = h1, tk2 = h2; | |||||
| } | |||||
| } | |||||
| } | |||||
| if (df < 0) { | |||||
| iWBlock[tk1 * ks + tk2] = (int16_t)(iWBlock[tk1 * ks + tk2] - df); | |||||
| } else { | |||||
| iWBlock[mtk1 * ks + mtk2] = (int16_t)(iWBlock[mtk1 * ks + mtk2] - df); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| iWBlock -= TAB_SZ2 * ks * ks; | |||||
| delete[] _wblock; | |||||
| initWB = true; | |||||
| } | |||||
| return (const void *)iWBlock; | |||||
| } | |||||
| static uint8_t CastToFixed(int v) { return INTTOUCHAR(((v + (1 << (BITS1 - 1))) >> BITS1)); } | |||||
| static int BorderPolate(int value, int length, PaddBorderType borderType) { | |||||
| if ((unsigned)value < (unsigned)length) { | |||||
| return value; | |||||
| } else if (borderType == 0) { | |||||
| value = -1; | |||||
| } | |||||
| return value; | |||||
| } | |||||
| static void RemapBilinear(const LiteMat &_src, LiteMat &_dst, const LiteMat &_hw, const LiteMat &_fhw, // NOLINT | |||||
| const void *_wblock, const PaddBorderType borderType, | |||||
| const std::vector<uint8_t> &borderValue) { | |||||
| const int cn = _src.channel_; | |||||
| const int16_t *wblock = (const int16_t *)_wblock; | |||||
| const uint8_t *src_ptr = _src.ptr<uint8_t>(0); | |||||
| size_t src_step = _src.steps_[0]; | |||||
| unsigned src_width = std::max(_src.width_ - 1, 0); | |||||
| unsigned src_height = std::max(_src.height_ - 1, 0); | |||||
| for (int dy = 0; dy < _dst.height_; dy++) { | |||||
| uint8_t *dst_ptr = _dst.ptr<uint8_t>(dy); | |||||
| const int16_t *HW = _hw.ptr<int16_t>(dy); | |||||
| const uint16_t *FHW = _fhw.ptr<uint16_t>(dy); | |||||
| int tt = 0; | |||||
| bool prevLine = false; | |||||
| for (int dx = 0; dx <= _dst.width_; dx++) { | |||||
| bool curLine = | |||||
| dx < _dst.width_ ? (unsigned)HW[dx * 2] < src_width && (unsigned)HW[dx * 2 + 1] < src_height : !prevLine; | |||||
| if (curLine == prevLine) continue; | |||||
| int H1 = dx; | |||||
| dx = tt; | |||||
| tt = H1; | |||||
| prevLine = curLine; | |||||
| if (!curLine) { | |||||
| int length = 0; | |||||
| dst_ptr += length * cn; | |||||
| dx += length; | |||||
| if (cn == 1) { | |||||
| for (; dx < H1; dx++, dst_ptr++) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| const uint8_t *t_src_ptr = src_ptr + shy * src_step + shx; | |||||
| *dst_ptr = | |||||
| CastToFixed(reinterpret_cast<int>(t_src_ptr[0] * w_ptr[0] + t_src_ptr[1] * w_ptr[1] + | |||||
| t_src_ptr[src_step] * w_ptr[2] + t_src_ptr[src_step + 1] * w_ptr[3])); | |||||
| } | |||||
| } else if (cn == 2) { | |||||
| for (; dx < H1; dx++, dst_ptr += 2) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| const uint8_t *t_src_ptr = src_ptr + shy * src_step + shx * 2; | |||||
| int v0 = t_src_ptr[0] * w_ptr[0] + t_src_ptr[2] * w_ptr[1] + t_src_ptr[src_step] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 2] * w_ptr[3]; | |||||
| int v1 = t_src_ptr[1] * w_ptr[0] + t_src_ptr[3] * w_ptr[1] + t_src_ptr[src_step + 1] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 3] * w_ptr[3]; | |||||
| dst_ptr[0] = CastToFixed(v0); | |||||
| dst_ptr[1] = CastToFixed(v1); | |||||
| } | |||||
| } else if (cn == 3) { | |||||
| for (; dx < H1; dx++, dst_ptr += 3) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| const uint8_t *t_src_ptr = src_ptr + shy * src_step + shx * 3; | |||||
| int v0 = t_src_ptr[0] * w_ptr[0] + t_src_ptr[3] * w_ptr[1] + t_src_ptr[src_step] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 3] * w_ptr[3]; | |||||
| int v1 = t_src_ptr[1] * w_ptr[0] + t_src_ptr[4] * w_ptr[1] + t_src_ptr[src_step + 1] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 4] * w_ptr[3]; | |||||
| int v2 = t_src_ptr[2] * w_ptr[0] + t_src_ptr[5] * w_ptr[1] + t_src_ptr[src_step + 2] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 5] * w_ptr[3]; | |||||
| dst_ptr[0] = CastToFixed(v0); | |||||
| dst_ptr[1] = CastToFixed(v1); | |||||
| dst_ptr[2] = CastToFixed(v2); | |||||
| } | |||||
| } else if (cn == 4) { | |||||
| for (; dx < H1; dx++, dst_ptr += 4) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| const uint8_t *t_src_ptr = src_ptr + shy * src_step + shx * 4; | |||||
| int v0 = t_src_ptr[0] * w_ptr[0] + t_src_ptr[4] * w_ptr[1] + t_src_ptr[src_step] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 4] * w_ptr[3]; | |||||
| int v1 = t_src_ptr[1] * w_ptr[0] + t_src_ptr[5] * w_ptr[1] + t_src_ptr[src_step + 1] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 5] * w_ptr[3]; | |||||
| dst_ptr[0] = CastToFixed(v0); | |||||
| dst_ptr[1] = CastToFixed(v1); | |||||
| v0 = t_src_ptr[2] * w_ptr[0] + t_src_ptr[6] * w_ptr[1] + t_src_ptr[src_step + 2] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 6] * w_ptr[3]; | |||||
| v1 = t_src_ptr[3] * w_ptr[0] + t_src_ptr[7] * w_ptr[1] + t_src_ptr[src_step + 3] * w_ptr[2] + | |||||
| t_src_ptr[src_step + 7] * w_ptr[3]; | |||||
| dst_ptr[2] = CastToFixed(v0); | |||||
| dst_ptr[3] = CastToFixed(v1); | |||||
| } | |||||
| } else { | |||||
| for (; dx < H1; dx++, dst_ptr += cn) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| const uint8_t *t_src_ptr = src_ptr + shy * src_step + shx * cn; | |||||
| for (int k = 0; k < cn; k++) { | |||||
| int v0 = t_src_ptr[k] * w_ptr[0] + t_src_ptr[k + cn] * w_ptr[1] + t_src_ptr[src_step + k] * w_ptr[2] + | |||||
| t_src_ptr[src_step + k + cn] * w_ptr[3]; | |||||
| dst_ptr[k] = CastToFixed(v0); | |||||
| } | |||||
| } | |||||
| } | |||||
| } else { | |||||
| if (cn == 1) { | |||||
| for (; dx < H1; dx++, dst_ptr++) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| if (borderType == PADD_BORDER_CONSTANT && | |||||
| (shx >= _src.width_ || shx + 1 < 0 || shy >= _src.height_ || shy + 1 < 0)) { | |||||
| dst_ptr[0] = borderValue[0]; | |||||
| } else { | |||||
| int sv0; | |||||
| int sv1; | |||||
| int su0; | |||||
| int su1; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| sv0 = BorderPolate(shx, _src.width_, borderType); | |||||
| sv1 = BorderPolate(shx + 1, _src.width_, borderType); | |||||
| su0 = BorderPolate(shy, _src.height_, borderType); | |||||
| su1 = BorderPolate(shy + 1, _src.height_, borderType); | |||||
| uint8_t v0 = sv0 >= 0 && su0 >= 0 ? src_ptr[su0 * src_step + sv0] : borderValue[0]; | |||||
| uint8_t v1 = sv1 >= 0 && su0 >= 0 ? src_ptr[su0 * src_step + sv1] : borderValue[0]; | |||||
| uint8_t v2 = sv0 >= 0 && su1 >= 0 ? src_ptr[su1 * src_step + sv0] : borderValue[0]; | |||||
| uint8_t v3 = sv1 >= 0 && su1 >= 0 ? src_ptr[su1 * src_step + sv1] : borderValue[0]; | |||||
| dst_ptr[0] = | |||||
| CastToFixed(reinterpret_cast<int>(v0 * w_ptr[0] + v1 * w_ptr[1] + v2 * w_ptr[2] + v3 * w_ptr[3])); | |||||
| } | |||||
| } | |||||
| } else { | |||||
| for (; dx < H1; dx++, dst_ptr += cn) { | |||||
| int shx = HW[dx * 2]; | |||||
| int shy = HW[dx * 2 + 1]; | |||||
| if (borderType == PADD_BORDER_CONSTANT && | |||||
| (shx >= _src.width_ || shx + 1 < 0 || shy >= _src.height_ || shy + 1 < 0)) { | |||||
| for (int k = 0; k < cn; k++) dst_ptr[k] = borderValue[k]; | |||||
| } else { | |||||
| int sv0; | |||||
| int sv1; | |||||
| int su0; | |||||
| int su1; | |||||
| const int16_t *w_ptr = wblock + FHW[dx] * 4; | |||||
| sv0 = BorderPolate(shx, _src.width_, borderType); | |||||
| sv1 = BorderPolate(shx + 1, _src.width_, borderType); | |||||
| su0 = BorderPolate(shy, _src.height_, borderType); | |||||
| su1 = BorderPolate(shy + 1, _src.height_, borderType); | |||||
| const uint8_t *v0 = sv0 >= 0 && su0 >= 0 ? src_ptr + su0 * src_step + sv0 * cn : &borderValue[0]; | |||||
| const uint8_t *v1 = sv1 >= 0 && su0 >= 0 ? src_ptr + su0 * src_step + sv1 * cn : &borderValue[0]; | |||||
| const uint8_t *v2 = sv0 >= 0 && su1 >= 0 ? src_ptr + su1 * src_step + sv0 * cn : &borderValue[0]; | |||||
| const uint8_t *v3 = sv1 >= 0 && su1 >= 0 ? src_ptr + su1 * src_step + sv1 * cn : &borderValue[0]; | |||||
| for (int k = 0; k < cn; k++) | |||||
| dst_ptr[k] = CastToFixed( | |||||
| reinterpret_cast<int>(v0[k] * w_ptr[0] + v1[k] * w_ptr[1] + v2[k] * w_ptr[2] + v3[k] * w_ptr[3])); | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| } | |||||
| static void Remap(const LiteMat &src, LiteMat &dst, LiteMat &map1, const LiteMat &map2, // NOLINT | |||||
| const PaddBorderType borderType, const std::vector<uint8_t> &borderValue) { | |||||
| int x, y, x1, y1; | |||||
| const int buf_size = 1 << 14; | |||||
| int dst_height = std::min(128, dst.height_); | |||||
| int dst_width = std::min(buf_size / dst_height, dst.width_); | |||||
| dst_height = std::min(buf_size / dst_width, dst.height_); | |||||
| const void *wblock = InitWBlock(); | |||||
| LiteMat _xyblock(dst_width, dst_height, 2, LDataType::INT16); | |||||
| LiteMat _ablock(dst_width, dst_height, 1, LDataType::UINT16); | |||||
| for (y = 0; y < dst.height_; y += dst_height) { | |||||
| for (x = 0; x < dst.width_; x += dst_width) { | |||||
| int bheight = std::min(dst_height, dst.height_ - y); | |||||
| int bwidth = std::min(dst_width, dst.width_ - x); | |||||
| LiteMat lite_part; | |||||
| dst.GetROI(x, y, bwidth, bheight, lite_part); | |||||
| LiteMat xy_ptr; | |||||
| _xyblock.GetROI(0, 0, bwidth, bheight, xy_ptr); | |||||
| LiteMat a_ptr; | |||||
| _ablock.GetROI(0, 0, bwidth, bheight, a_ptr); | |||||
| for (y1 = 0; y1 < bheight; y1++) { | |||||
| uint16_t *t_a_ptr = a_ptr.ptr<uint16_t>(y1); | |||||
| map1.GetROI(x, y, bwidth, bheight, xy_ptr); | |||||
| const uint16_t *sa_ptr = map2.ptr<uint16_t>(y + y1) + x; | |||||
| x1 = 0; | |||||
| for (; x1 < bwidth; x1++) { | |||||
| t_a_ptr[x1] = (uint16_t)(sa_ptr[x1] & (TAB_SZ2 - 1)); | |||||
| } | |||||
| } | |||||
| RemapBilinear(src, lite_part, xy_ptr, a_ptr, wblock, borderType, borderValue); | |||||
| } | |||||
| } | |||||
| } | |||||
| bool WarpAffineBilinear(const LiteMat &src, LiteMat &dst, const LiteMat &M, int dst_w, int dst_h, // NOLINT | |||||
| PaddBorderType borderType, std::vector<uint8_t> &borderValue) { // NOLINT | |||||
| if (!(M.height_ == 2 && M.width_ == 3)) { | |||||
| return false; | |||||
| } | |||||
| if (borderType != PADD_BORDER_CONSTANT) { | |||||
| return false; | |||||
| } | |||||
| if (borderValue.size() != src.channel_) { | |||||
| return false; | |||||
| } | |||||
| if (dst.IsEmpty()) { | |||||
| (void)dst.Init(dst_w, dst_h, src.channel_, LDataType::UINT8); | |||||
| } else if (dst.height_ != dst_h || dst.width_ != dst_w || dst.channel_ != src.channel_) { | |||||
| return false; | |||||
| } else if (dst.data_type_ != LDataType::UINT8) { | |||||
| return false; | |||||
| } else { | |||||
| } | |||||
| double IM[6]; | |||||
| const double *M_Ptr = M; | |||||
| for (int i = 0; i < 6; i++) { | |||||
| IM[i] = M_Ptr[i]; | |||||
| } | |||||
| double D = IM[0] * IM[4] - IM[1] * IM[3]; | |||||
| D = D != 0 ? 1.0f / D : 0; | |||||
| double A11 = IM[4] * D, A22 = IM[0] * D; | |||||
| IM[0] = A11; | |||||
| IM[1] *= -D; | |||||
| IM[3] *= -D; | |||||
| IM[4] = A22; | |||||
| double b1 = -IM[0] * IM[2] - IM[1] * IM[5]; | |||||
| double b2 = -IM[3] * IM[2] - IM[4] * IM[5]; | |||||
| IM[2] = b1; | |||||
| IM[5] = b2; | |||||
| int *_a = new int[dst.width_ * 2]; | |||||
| int *a = &_a[0], *b = a + dst.width_; | |||||
| const int SCALE = 1 << 10; | |||||
| const int B_SIZE = 64; | |||||
| int16_t WH[B_SIZE * B_SIZE * 2]; | |||||
| int16_t A_Ptr[B_SIZE * B_SIZE]; | |||||
| int r_delta = SCALE / TAB_SZ / 2; | |||||
| int x, y, x1, y1; | |||||
| for (x = 0; x < dst.width_; x++) { | |||||
| a[x] = round(IM[0] * x * SCALE); | |||||
| b[x] = round(IM[3] * x * SCALE); | |||||
| } | |||||
| int t_bh0 = std::min(B_SIZE / 2, dst.height_); | |||||
| int t_bw0 = std::min(B_SIZE * B_SIZE / t_bh0, dst.width_); | |||||
| t_bh0 = std::min(B_SIZE * B_SIZE / t_bw0, dst.height_); | |||||
| for (y = 0; y < dst.height_; y += t_bh0) { | |||||
| for (x = 0; x < dst.width_; x += t_bw0) { | |||||
| int t_bw = std::min(t_bw0, dst.width_ - x); | |||||
| int t_bh = std::min(t_bh0, dst.height_ - y); | |||||
| LiteMat _HW(t_bw, t_bh, 2, WH, LDataType::INT16); | |||||
| LiteMat lite_part; | |||||
| dst.GetROI(x, y, t_bw, t_bh, lite_part); | |||||
| for (y1 = 0; y1 < t_bh; y1++) { | |||||
| int16_t *t_xy = WH + y1 * t_bw * 2; | |||||
| int X0 = round((IM[1] * (y + y1) + IM[2]) * SCALE) + r_delta; | |||||
| int Y0 = round((IM[4] * (y + y1) + IM[5]) * SCALE) + r_delta; | |||||
| int16_t *t_a = A_Ptr + y1 * t_bw; | |||||
| x1 = 0; | |||||
| for (; x1 < t_bw; x1++) { | |||||
| int X = (X0 + a[x + x1]) >> (10 - BITS); | |||||
| int Y = (Y0 + b[x + x1]) >> (10 - BITS); | |||||
| t_xy[x1 * 2] = IntCastShort(X >> BITS); | |||||
| t_xy[x1 * 2 + 1] = IntCastShort(Y >> BITS); | |||||
| t_a[x1] = (int16_t)((Y & (TAB_SZ - 1)) * TAB_SZ + (X & (TAB_SZ - 1))); | |||||
| } | |||||
| } | |||||
| LiteMat _matA(t_bw, t_bh, 1, A_Ptr, LDataType::UINT16); | |||||
| Remap(src, lite_part, _HW, _matA, borderType, borderValue); | |||||
| } | |||||
| } | |||||
| delete[] _a; | |||||
| return true; | |||||
| } | |||||
| static void PerspectiveInvert(double *src, double *dst) { | |||||
| double value = GetDet3(src); | |||||
| if (value != 0.) { | |||||
| value = 1. / value; | |||||
| double v[9]; | |||||
| v[0] = (SrcValue(1, 1) * SrcValue(2, 2) - SrcValue(1, 2) * SrcValue(2, 1)) * value; | |||||
| v[1] = (SrcValue(0, 2) * SrcValue(2, 1) - SrcValue(0, 1) * SrcValue(2, 2)) * value; | |||||
| v[2] = (SrcValue(0, 1) * SrcValue(1, 2) - SrcValue(0, 2) * SrcValue(1, 1)) * value; | |||||
| v[3] = (SrcValue(1, 2) * SrcValue(2, 0) - SrcValue(1, 0) * SrcValue(2, 2)) * value; | |||||
| v[4] = (SrcValue(0, 0) * SrcValue(2, 2) - SrcValue(0, 2) * SrcValue(2, 0)) * value; | |||||
| v[5] = (SrcValue(0, 2) * SrcValue(1, 0) - SrcValue(0, 0) * SrcValue(1, 2)) * value; | |||||
| v[6] = (SrcValue(1, 0) * SrcValue(2, 1) - SrcValue(1, 1) * SrcValue(2, 0)) * value; | |||||
| v[7] = (SrcValue(0, 1) * SrcValue(2, 0) - SrcValue(0, 0) * SrcValue(2, 1)) * value; | |||||
| v[8] = (SrcValue(0, 0) * SrcValue(1, 1) - SrcValue(0, 1) * SrcValue(1, 0)) * value; | |||||
| DstValue(0, 0) = v[0]; | |||||
| DstValue(0, 1) = v[1]; | |||||
| DstValue(0, 2) = v[2]; | |||||
| DstValue(1, 0) = v[3]; | |||||
| DstValue(1, 1) = v[4]; | |||||
| DstValue(1, 2) = v[5]; | |||||
| DstValue(2, 0) = v[6]; | |||||
| DstValue(2, 1) = v[7]; | |||||
| DstValue(2, 2) = v[8]; | |||||
| } | |||||
| } | |||||
| bool WarpPerspectiveBilinear(const LiteMat &src, LiteMat &dst, const LiteMat &M, int dst_w, int dst_h, // NOLINT | |||||
| PaddBorderType borderType, std::vector<uint8_t> &borderValue) { // NOLINT | |||||
| if (!(M.height_ == 3 && M.width_ == 3)) { | |||||
| return false; | |||||
| } | |||||
| if (borderType != PADD_BORDER_CONSTANT) { | |||||
| return false; | |||||
| } | |||||
| if (borderValue.size() != src.channel_) { | |||||
| return false; | |||||
| } | |||||
| if (dst.IsEmpty()) { | |||||
| (void)dst.Init(dst_w, dst_h, src.channel_, LDataType::UINT8); | |||||
| } else if (dst.height_ != dst_h || dst.width_ != dst_w || dst.channel_ != src.channel_) { | |||||
| return false; | |||||
| } else if (dst.data_type_ != LDataType::UINT8) { | |||||
| return false; | |||||
| } else { | |||||
| } | |||||
| double IM[9]; | |||||
| const double *M_Ptr = M; | |||||
| for (int i = 0; i < 9; i++) { | |||||
| IM[i] = M_Ptr[i]; | |||||
| } | |||||
| PerspectiveInvert(IM, IM); | |||||
| const int B_SZ = 32; | |||||
| int16_t HW[B_SZ * B_SZ * 2]; | |||||
| int16_t TA[B_SZ * B_SZ]; | |||||
| int x; | |||||
| int y; | |||||
| int y1; | |||||
| int width = dst.width_; | |||||
| int height = dst.height_; | |||||
| int bheight = std::min(B_SZ / 2, height); | |||||
| int bwidth = std::min(B_SZ * B_SZ / bheight, width); | |||||
| bheight = std::min(B_SZ * B_SZ / bwidth, height); | |||||
| for (y = 0; y < dst.height_; y += bheight) { | |||||
| for (x = 0; x < width; x += bwidth) { | |||||
| int tw = std::min(bwidth, width - x); | |||||
| int th = std::min(bheight, dst.height_ - y); | |||||
| LiteMat _HW(tw, th, 2, HW, LDataType::INT16); | |||||
| LiteMat lite_part; | |||||
| dst.GetROI(x, y, tw, th, lite_part); | |||||
| for (y1 = 0; y1 < th; y1++) { | |||||
| int16_t *xy = HW + y1 * tw * 2; | |||||
| double XV = IM[0] * x + IM[1] * (y + y1) + IM[2]; | |||||
| double YV = IM[3] * x + IM[4] * (y + y1) + IM[5]; | |||||
| double WV = IM[6] * x + IM[7] * (y + y1) + IM[8]; | |||||
| int16_t *t_a = TA + y1 * tw; | |||||
| for (int x1 = 0; x1 < tw; x1++) { | |||||
| double W = WV + IM[6] * x1; | |||||
| W = W ? TAB_SZ / W : 0; | |||||
| double fX = std::max((double)INT_MIN, std::min((double)INT_MAX, (XV + IM[0] * x1) * W)); // NOLINT | |||||
| double fY = std::max((double)INT_MIN, std::min((double)INT_MAX, (YV + IM[3] * x1) * W)); // NOLINT | |||||
| int X = round(fX); | |||||
| int Y = round(fY); | |||||
| xy[x1 * 2] = IntCastShort(X >> BITS); | |||||
| xy[x1 * 2 + 1] = IntCastShort(Y >> BITS); | |||||
| t_a[x1] = (int16_t)((Y & (TAB_SZ - 1)) * TAB_SZ + (X & (TAB_SZ - 1))); | |||||
| } | |||||
| } | |||||
| LiteMat _matA(tw, th, 1, TA, LDataType::UINT16); | |||||
| Remap(src, lite_part, _HW, _matA, borderType, borderValue); | |||||
| } | |||||
| } | |||||
| return true; | |||||
| } | |||||
| } // namespace dataset | |||||
| } // namespace mindspore | |||||
| @@ -886,4 +886,329 @@ TEST_F(MindDataImageProcess, TestExtractChannel) { | |||||
| EXPECT_FALSE(ExtractChannel(lite_mat, lite_single, 0)); | EXPECT_FALSE(ExtractChannel(lite_mat, lite_single, 0)); | ||||
| EXPECT_TRUE(lite_single.IsEmpty()); | EXPECT_TRUE(lite_single.IsEmpty()); | ||||
| } | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testROI3C) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Mat cv_roi = cv::Mat(src_image, cv::Rect(500, 500, 3000, 1500)); | |||||
| cv::imwrite("./cv_roi.jpg", cv_roi); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_bgr; | |||||
| ret = InitFromPixel(src_image.data, LPixelType::BGR, LDataType::UINT8, src_image.cols, src_image.rows, lite_mat_bgr); | |||||
| EXPECT_TRUE(ret); | |||||
| LiteMat lite_roi; | |||||
| ret = lite_mat_bgr.GetROI(500, 500, 3000, 1500, lite_roi); | |||||
| EXPECT_TRUE(ret); | |||||
| LiteMat lite_roi_save(3000, 1500, lite_roi.channel_, LDataType::UINT8); | |||||
| for (size_t i = 0; i < lite_roi.height_; i++) { | |||||
| const unsigned char *ptr = lite_roi.ptr<unsigned char>(i); | |||||
| size_t image_size = lite_roi.width_ * lite_roi.channel_ * sizeof(unsigned char); | |||||
| unsigned char *dst_ptr = (unsigned char *)lite_roi_save.data_ptr_ + image_size * i; | |||||
| (void)memcpy(dst_ptr, ptr, image_size); | |||||
| } | |||||
| cv::Mat dst_imageR(lite_roi_save.height_, lite_roi_save.width_, CV_8UC3, lite_roi_save.data_ptr_); | |||||
| cv::imwrite("./lite_roi.jpg", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testROI1C) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Mat gray_image; | |||||
| cv::cvtColor(src_image, gray_image, CV_BGR2GRAY); | |||||
| cv::Mat cv_roi_gray = cv::Mat(gray_image, cv::Rect(500, 500, 3000, 1500)); | |||||
| cv::imwrite("./cv_roi_gray.jpg", cv_roi_gray); | |||||
| cv::Mat rgba_mat; | |||||
| cv::cvtColor(src_image, rgba_mat, CV_BGR2RGBA); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_gray; | |||||
| ret = | |||||
| InitFromPixel(rgba_mat.data, LPixelType::RGBA2GRAY, LDataType::UINT8, rgba_mat.cols, rgba_mat.rows, lite_mat_gray); | |||||
| EXPECT_TRUE(ret); | |||||
| LiteMat lite_roi_gray; | |||||
| ret = lite_mat_gray.GetROI(500, 500, 3000, 1500, lite_roi_gray); | |||||
| EXPECT_TRUE(ret); | |||||
| LiteMat lite_roi_gray_save(3000, 1500, lite_roi_gray.channel_, LDataType::UINT8); | |||||
| for (size_t i = 0; i < lite_roi_gray.height_; i++) { | |||||
| const unsigned char *ptr = lite_roi_gray.ptr<unsigned char>(i); | |||||
| size_t image_size = lite_roi_gray.width_ * lite_roi_gray.channel_ * sizeof(unsigned char); | |||||
| unsigned char *dst_ptr = (unsigned char *)lite_roi_gray_save.data_ptr_ + image_size * i; | |||||
| (void)memcpy(dst_ptr, ptr, image_size); | |||||
| } | |||||
| cv::Mat dst_imageR(lite_roi_gray_save.height_, lite_roi_gray_save.width_, CV_8UC1, lite_roi_gray_save.data_ptr_); | |||||
| cv::imwrite("./lite_roi.jpg", dst_imageR); | |||||
| } | |||||
| //warp | |||||
| TEST_F(MindDataImageProcess, testWarpAffineBGR) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Point2f srcTri[3]; | |||||
| cv::Point2f dstTri[3]; | |||||
| srcTri[0] = cv::Point2f(0, 0); | |||||
| srcTri[1] = cv::Point2f(src_image.cols - 1, 0); | |||||
| srcTri[2] = cv::Point2f(0, src_image.rows - 1); | |||||
| dstTri[0] = cv::Point2f(src_image.cols * 0.0, src_image.rows * 0.33); | |||||
| dstTri[1] = cv::Point2f(src_image.cols * 0.85, src_image.rows * 0.25); | |||||
| dstTri[2] = cv::Point2f(src_image.cols * 0.15, src_image.rows * 0.7); | |||||
| cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri); | |||||
| ; | |||||
| cv::Mat warp_dstImage; | |||||
| cv::warpAffine(src_image, warp_dstImage, warp_mat, warp_dstImage.size()); | |||||
| cv::imwrite("./warpAffine_cv_bgr.png", warp_dstImage); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_bgr; | |||||
| ret = InitFromPixel(src_image.data, LPixelType::BGR, LDataType::UINT8, src_image.cols, src_image.rows, lite_mat_bgr); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = warp_mat.ptr<double>(0); | |||||
| LiteMat lite_M(3, 2, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| ret = WarpAffineBilinear(lite_mat_bgr, lite_warp, lite_M, lite_mat_bgr.width_, lite_mat_bgr.height_, PADD_BORDER_CONSTANT, borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC3, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpAffine_lite_bgr.png", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testWarpAffineBGRScale) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Point2f srcTri[3]; | |||||
| cv::Point2f dstTri[3]; | |||||
| srcTri[0] = cv::Point2f(10, 20); | |||||
| srcTri[1] = cv::Point2f(src_image.cols - 1 - 100, 0); | |||||
| srcTri[2] = cv::Point2f(0, src_image.rows - 1 - 300); | |||||
| dstTri[0] = cv::Point2f(src_image.cols * 0.22, src_image.rows * 0.33); | |||||
| dstTri[1] = cv::Point2f(src_image.cols * 0.87, src_image.rows * 0.75); | |||||
| dstTri[2] = cv::Point2f(src_image.cols * 0.35, src_image.rows * 0.37); | |||||
| cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri); | |||||
| ; | |||||
| cv::Mat warp_dstImage; | |||||
| cv::warpAffine(src_image, warp_dstImage, warp_mat, warp_dstImage.size()); | |||||
| cv::imwrite("./warpAffine_cv_bgr_scale.png", warp_dstImage); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_bgr; | |||||
| ret = InitFromPixel(src_image.data, LPixelType::BGR, LDataType::UINT8, src_image.cols, src_image.rows, lite_mat_bgr); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = warp_mat.ptr<double>(0); | |||||
| LiteMat lite_M(3, 2, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| ret = WarpAffineBilinear(lite_mat_bgr, lite_warp, lite_M, lite_mat_bgr.width_, lite_mat_bgr.height_, PADD_BORDER_CONSTANT, borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC3, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpAffine_lite_bgr_scale.png", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testWarpAffineBGRResize) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Point2f srcTri[3]; | |||||
| cv::Point2f dstTri[3]; | |||||
| srcTri[0] = cv::Point2f(10, 20); | |||||
| srcTri[1] = cv::Point2f(src_image.cols - 1 - 100, 0); | |||||
| srcTri[2] = cv::Point2f(0, src_image.rows - 1 - 300); | |||||
| dstTri[0] = cv::Point2f(src_image.cols * 0.22, src_image.rows * 0.33); | |||||
| dstTri[1] = cv::Point2f(src_image.cols * 0.87, src_image.rows * 0.75); | |||||
| dstTri[2] = cv::Point2f(src_image.cols * 0.35, src_image.rows * 0.37); | |||||
| cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri); | |||||
| ; | |||||
| cv::Mat warp_dstImage; | |||||
| cv::warpAffine(src_image, warp_dstImage, warp_mat, cv::Size(src_image.cols + 200, src_image.rows - 300)); | |||||
| cv::imwrite("./warpAffine_cv_bgr_resize.png", warp_dstImage); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_bgr; | |||||
| ret = InitFromPixel(src_image.data, LPixelType::BGR, LDataType::UINT8, src_image.cols, src_image.rows, lite_mat_bgr); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = warp_mat.ptr<double>(0); | |||||
| LiteMat lite_M(3, 2, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| ret = WarpAffineBilinear(lite_mat_bgr, lite_warp, lite_M, lite_mat_bgr.width_ + 200, lite_mat_bgr.height_ - 300, PADD_BORDER_CONSTANT, | |||||
| borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC3, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpAffine_lite_bgr_resize.png", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testWarpAffineGray) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Mat gray_image; | |||||
| cv::cvtColor(src_image, gray_image, CV_BGR2GRAY); | |||||
| cv::Point2f srcTri[3]; | |||||
| cv::Point2f dstTri[3]; | |||||
| srcTri[0] = cv::Point2f(0, 0); | |||||
| srcTri[1] = cv::Point2f(src_image.cols - 1, 0); | |||||
| srcTri[2] = cv::Point2f(0, src_image.rows - 1); | |||||
| dstTri[0] = cv::Point2f(src_image.cols * 0.0, src_image.rows * 0.33); | |||||
| dstTri[1] = cv::Point2f(src_image.cols * 0.85, src_image.rows * 0.25); | |||||
| dstTri[2] = cv::Point2f(src_image.cols * 0.15, src_image.rows * 0.7); | |||||
| cv::Mat warp_mat = cv::getAffineTransform(srcTri, dstTri); | |||||
| ; | |||||
| cv::Mat warp_gray_dstImage; | |||||
| cv::warpAffine(gray_image, warp_gray_dstImage, warp_mat, cv::Size(src_image.cols + 200, src_image.rows - 300)); | |||||
| cv::imwrite("./warpAffine_cv_gray.png", warp_gray_dstImage); | |||||
| cv::Mat rgba_mat; | |||||
| cv::cvtColor(src_image, rgba_mat, CV_BGR2RGBA); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_gray; | |||||
| ret = | |||||
| InitFromPixel(rgba_mat.data, LPixelType::RGBA2GRAY, LDataType::UINT8, rgba_mat.cols, rgba_mat.rows, lite_mat_gray); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = warp_mat.ptr<double>(0); | |||||
| LiteMat lite_M(3, 2, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| ret = WarpAffineBilinear(lite_mat_gray, lite_warp, lite_M, lite_mat_gray.width_ + 200, lite_mat_gray.height_ - 300, PADD_BORDER_CONSTANT, | |||||
| borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC1, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpAffine_lite_gray.png", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testWarpPerspectiveBGRResize) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Point2f srcQuad[4], dstQuad[4]; | |||||
| srcQuad[0].x = 0; | |||||
| srcQuad[0].y = 0; | |||||
| srcQuad[1].x = src_image.cols - 1.; | |||||
| srcQuad[1].y = 0; | |||||
| srcQuad[2].x = 0; | |||||
| srcQuad[2].y = src_image.rows - 1; | |||||
| srcQuad[3].x = src_image.cols - 1; | |||||
| srcQuad[3].y = src_image.rows - 1; | |||||
| dstQuad[0].x = src_image.cols * 0.05; | |||||
| dstQuad[0].y = src_image.rows * 0.33; | |||||
| dstQuad[1].x = src_image.cols * 0.9; | |||||
| dstQuad[1].y = src_image.rows * 0.25; | |||||
| dstQuad[2].x = src_image.cols * 0.2; | |||||
| dstQuad[2].y = src_image.rows * 0.7; | |||||
| dstQuad[3].x = src_image.cols * 0.8; | |||||
| dstQuad[3].y = src_image.rows * 0.9; | |||||
| cv::Mat ptran = cv::getPerspectiveTransform(srcQuad, dstQuad, cv::DECOMP_SVD); | |||||
| cv::Mat warp_dstImage; | |||||
| cv::warpPerspective(src_image, warp_dstImage, ptran, cv::Size(src_image.cols + 200, src_image.rows - 300)); | |||||
| cv::imwrite("./warpPerspective_cv_bgr.png", warp_dstImage); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_bgr; | |||||
| ret = InitFromPixel(src_image.data, LPixelType::BGR, LDataType::UINT8, src_image.cols, src_image.rows, lite_mat_bgr); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = ptran.ptr<double>(0); | |||||
| LiteMat lite_M(3, 3, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| borderValues.push_back(0); | |||||
| ret = WarpPerspectiveBilinear(lite_mat_bgr, lite_warp, lite_M, lite_mat_bgr.width_ + 200, lite_mat_bgr.height_ - 300, PADD_BORDER_CONSTANT, | |||||
| borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC3, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpPerspective_lite_bgr.png", dst_imageR); | |||||
| } | |||||
| TEST_F(MindDataImageProcess, testWarpPerspectiveGrayResize) { | |||||
| std::string filename = "data/dataset/apple.jpg"; | |||||
| cv::Mat src_image = cv::imread(filename, cv::ImreadModes::IMREAD_COLOR); | |||||
| cv::Mat gray_image; | |||||
| cv::cvtColor(src_image, gray_image, CV_BGR2GRAY); | |||||
| cv::Point2f srcQuad[4], dstQuad[4]; | |||||
| srcQuad[0].x = 0; | |||||
| srcQuad[0].y = 0; | |||||
| srcQuad[1].x = src_image.cols - 1.; | |||||
| srcQuad[1].y = 0; | |||||
| srcQuad[2].x = 0; | |||||
| srcQuad[2].y = src_image.rows - 1; | |||||
| srcQuad[3].x = src_image.cols - 1; | |||||
| srcQuad[3].y = src_image.rows - 1; | |||||
| dstQuad[0].x = src_image.cols * 0.05; | |||||
| dstQuad[0].y = src_image.rows * 0.33; | |||||
| dstQuad[1].x = src_image.cols * 0.9; | |||||
| dstQuad[1].y = src_image.rows * 0.25; | |||||
| dstQuad[2].x = src_image.cols * 0.2; | |||||
| dstQuad[2].y = src_image.rows * 0.7; | |||||
| dstQuad[3].x = src_image.cols * 0.8; | |||||
| dstQuad[3].y = src_image.rows * 0.9; | |||||
| cv::Mat ptran = cv::getPerspectiveTransform(srcQuad, dstQuad, cv::DECOMP_SVD); | |||||
| cv::Mat warp_dstImage; | |||||
| cv::warpPerspective(gray_image, warp_dstImage, ptran, cv::Size(gray_image.cols + 200, gray_image.rows - 300)); | |||||
| cv::imwrite("./warpPerspective_cv_gray.png", warp_dstImage); | |||||
| cv::Mat rgba_mat; | |||||
| cv::cvtColor(src_image, rgba_mat, CV_BGR2RGBA); | |||||
| bool ret = false; | |||||
| LiteMat lite_mat_gray; | |||||
| ret = | |||||
| InitFromPixel(rgba_mat.data, LPixelType::RGBA2GRAY, LDataType::UINT8, rgba_mat.cols, rgba_mat.rows, lite_mat_gray); | |||||
| EXPECT_TRUE(ret); | |||||
| double *mat_ptr = ptran.ptr<double>(0); | |||||
| LiteMat lite_M(3, 3, 1, mat_ptr, LDataType::DOUBLE); | |||||
| LiteMat lite_warp; | |||||
| std::vector<uint8_t> borderValues; | |||||
| borderValues.push_back(0); | |||||
| ret = WarpPerspectiveBilinear(lite_mat_gray, lite_warp, lite_M, lite_mat_gray.width_ + 200, lite_mat_gray.height_ - 300, PADD_BORDER_CONSTANT, | |||||
| borderValues); | |||||
| EXPECT_TRUE(ret); | |||||
| cv::Mat dst_imageR(lite_warp.height_, lite_warp.width_, CV_8UC1, lite_warp.data_ptr_); | |||||
| cv::imwrite("./warpPerspective_lite_gray.png", dst_imageR); | |||||
| } | |||||