forked from mindspore-Ecosystem/mindspore
add warp affine
This commit is contained in:
parent
da92f1affb
commit
de6356ebfa
|
@ -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)
|
||||
add_library(lite-cv OBJECT
|
||||
image_process.cc
|
||||
warp_affine.cc
|
||||
lite_mat.cc)
|
|
@ -28,11 +28,34 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#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))
|
||||
|
||||
namespace mindspore {
|
||||
namespace dataset {
|
||||
|
||||
#define Equ(a, b) ((std::fabs((a) - (b)) < 1e-6))
|
||||
|
||||
static inline void InitBilinearWeight(int *data_ptr, int16_t *weight_ptr, double scale, int dst_length, int src_length,
|
||||
int a) {
|
||||
const int RESIZE_SCALE = 1 << 11;
|
||||
|
@ -374,6 +397,79 @@ static bool ConvertYUV420SPToBGR(const uint8_t *data, LDataType data_type, bool
|
|||
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) {
|
||||
if (data_type == 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;
|
||||
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 x = 0; x < w; x++) {
|
||||
*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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -30,22 +30,6 @@ namespace dataset {
|
|||
#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));
|
||||
|
||||
#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 };
|
||||
|
||||
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,
|
||||
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 mindspore
|
||||
#endif // IMAGE_PROCESS_H_
|
||||
|
|
|
@ -39,6 +39,7 @@ LiteMat::LiteMat() {
|
|||
size_ = 0;
|
||||
data_type_ = LDataType::UINT8;
|
||||
ref_count_ = nullptr;
|
||||
setSteps(0, 0, 0);
|
||||
}
|
||||
|
||||
LiteMat::LiteMat(int width, LDataType data_type) {
|
||||
|
@ -52,6 +53,7 @@ LiteMat::LiteMat(int width, LDataType data_type) {
|
|||
data_type_ = LDataType::UINT8;
|
||||
ref_count_ = nullptr;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
Init(width, data_type);
|
||||
}
|
||||
|
||||
|
@ -66,6 +68,7 @@ LiteMat::LiteMat(int width, int height, LDataType data_type) {
|
|||
data_type_ = LDataType::UINT8;
|
||||
ref_count_ = nullptr;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
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;
|
||||
ref_count_ = nullptr;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
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;
|
||||
ref_count_ = nullptr;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
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;
|
||||
ref_count_ = nullptr;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
Init(width, height, channel, p_data, data_type);
|
||||
}
|
||||
|
||||
|
@ -130,11 +136,18 @@ LiteMat::LiteMat(const LiteMat &m) {
|
|||
data_type_ = m.data_type_;
|
||||
ref_count_ = m.ref_count_;
|
||||
size_ = 0;
|
||||
setSteps(m.steps_[0], m.steps_[1], m.steps_[2]);
|
||||
if (ref_count_) {
|
||||
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) {
|
||||
if (this == &m) {
|
||||
return *this;
|
||||
|
@ -154,7 +167,8 @@ LiteMat &LiteMat::operator=(const LiteMat &m) {
|
|||
dims_ = m.dims_;
|
||||
data_type_ = m.data_type_;
|
||||
ref_count_ = m.ref_count_;
|
||||
size_ = 0;
|
||||
setSteps(m.steps_[0], m.steps_[1], m.steps_[2]);
|
||||
size_ = m.size_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -171,6 +185,7 @@ void LiteMat::Init(int width, LDataType data_type) {
|
|||
data_ptr_ = AlignMalloc(size_);
|
||||
ref_count_ = new int[1];
|
||||
*ref_count_ = 1;
|
||||
steps_[0] = elem_size_;
|
||||
}
|
||||
|
||||
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_);
|
||||
ref_count_ = new int[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) {
|
||||
|
@ -199,6 +216,8 @@ void LiteMat::Init(int width, int height, void *p_data, LDataType data_type) {
|
|||
size_ = c_step_ * channel_ * elem_size_;
|
||||
data_ptr_ = p_data;
|
||||
ref_count_ = nullptr;
|
||||
steps_[1] = elem_size_;
|
||||
steps_[0] = width_ * steps_[1];
|
||||
}
|
||||
|
||||
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_);
|
||||
ref_count_ = new int[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) {
|
||||
|
@ -227,6 +250,9 @@ void LiteMat::Init(int width, int height, int channel, void *p_data, LDataType d
|
|||
size_ = c_step_ * channel_ * elem_size_;
|
||||
data_ptr_ = p_data;
|
||||
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; }
|
||||
|
@ -248,6 +274,7 @@ void LiteMat::Release() {
|
|||
c_step_ = 0;
|
||||
ref_count_ = 0;
|
||||
size_ = 0;
|
||||
setSteps(0, 0, 0);
|
||||
}
|
||||
|
||||
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(); }
|
||||
|
||||
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>
|
||||
inline void SubtractImpl(const T *src0, const T *src1, T *dst, int64_t total_size) {
|
||||
for (int64_t i = 0; i < total_size; i++) {
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace mindspore {
|
|||
namespace dataset {
|
||||
|
||||
#define ALIGN 16
|
||||
#define MAX_DIMS 3
|
||||
|
||||
template <typename T>
|
||||
struct Chn1 {
|
||||
|
@ -121,6 +122,8 @@ enum LPixelType {
|
|||
NV122BGR = 7,
|
||||
};
|
||||
|
||||
enum WARP_BORDER_MODE { WARP_BORDER_MODE_CONSTANT };
|
||||
|
||||
class LDataType {
|
||||
public:
|
||||
enum Type : uint8_t {
|
||||
|
@ -137,6 +140,7 @@ class LDataType {
|
|||
FLOAT16,
|
||||
FLOAT32,
|
||||
FLOAT64,
|
||||
DOUBLE,
|
||||
NUM_OF_TYPES
|
||||
};
|
||||
|
||||
|
@ -179,6 +183,7 @@ class LDataType {
|
|||
2, // FLOAT16
|
||||
4, // FLOAT32
|
||||
8, // FLOAT64
|
||||
8, // DOUBLE
|
||||
};
|
||||
|
||||
Type type_;
|
||||
|
@ -213,6 +218,8 @@ class LiteMat {
|
|||
|
||||
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;
|
||||
|
||||
void Release();
|
||||
|
@ -229,6 +236,14 @@ class LiteMat {
|
|||
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:
|
||||
/// \brief apply for memory alignment
|
||||
void *AlignMalloc(unsigned int size);
|
||||
|
@ -241,6 +256,8 @@ class LiteMat {
|
|||
/// \brief add reference
|
||||
int addRef(int *p, int value);
|
||||
|
||||
void setSteps(int c0, int c1, int c2);
|
||||
|
||||
public:
|
||||
void *data_ptr_ = nullptr;
|
||||
int elem_size_;
|
||||
|
@ -252,6 +269,7 @@ class LiteMat {
|
|||
size_t size_;
|
||||
LDataType data_type_;
|
||||
int *ref_count_;
|
||||
size_t steps_[MAX_DIMS];
|
||||
};
|
||||
|
||||
/// \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_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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue