Merge branch 4.x

This commit is contained in:
Alexander Smorkalov 2024-02-28 17:57:46 +03:00
commit a22130fbfa
14 changed files with 450 additions and 102 deletions

View File

@ -169,6 +169,6 @@ ocv_install_target(tbb EXPORT OpenCVModules
OPTIONAL
)
ocv_install_3rdparty_licenses(tbb "${tbb_src_dir}/LICENSE" "${tbb_src_dir}/README")
ocv_install_3rdparty_licenses(tbb "${tbb_src_dir}/LICENSE.txt" "${tbb_src_dir}/README.md")
ocv_tbb_read_version("${tbb_src_dir}/include" tbb)

View File

@ -11,7 +11,8 @@ int test()
_mm_storel_epi64((__m128i*)dst, v_dst);
return (int)dst[0];
}
#elif (defined __GNUC__ && (defined __arm__ || defined __aarch64__)) || (defined _MSC_VER && defined _M_ARM64)
#elif (defined __GNUC__ && (defined __arm__ || defined __aarch64__)) /*|| (defined _MSC_VER && defined _M_ARM64)*/
// Windows + ARM64 case disabled: https://github.com/opencv/opencv/issues/25052
#include "arm_neon.h"
int test()
{

View File

@ -934,8 +934,8 @@ cv::Vec3d cv::RQDecomp3x3( InputArray _Marr,
Qx = ( 0 c s ), c = m33/sqrt(m32^2 + m33^2), s = m32/sqrt(m32^2 + m33^2)
( 0 -s c )
*/
s = M(2, 1);
c = M(2, 2);
s = std::abs(M(2, 1)) > DBL_EPSILON ? M(2, 1): 0.;
c = std::abs(M(2, 1)) > DBL_EPSILON ? M(2, 2): 1.;
z = 1./std::sqrt(c * c + s * s + DBL_EPSILON);
c *= z;
s *= z;
@ -952,8 +952,8 @@ cv::Vec3d cv::RQDecomp3x3( InputArray _Marr,
Qy = ( 0 1 0 ), c = m33/sqrt(m31^2 + m33^2), s = -m31/sqrt(m31^2 + m33^2)
( s 0 c )
*/
s = -R(2, 0);
c = R(2, 2);
s = std::abs(R(2, 0)) > DBL_EPSILON ? -R(2, 0): 0.;
c = std::abs(R(2, 0)) > DBL_EPSILON ? R(2, 2): 1.;
z = 1./std::sqrt(c * c + s * s + DBL_EPSILON);
c *= z;
s *= z;
@ -971,8 +971,8 @@ cv::Vec3d cv::RQDecomp3x3( InputArray _Marr,
( 0 0 1 )
*/
s = M(1, 0);
c = M(1, 1);
s = std::abs(M(1, 0)) > DBL_EPSILON ? M(1, 0): 0.;
c = std::abs(M(1, 0)) > DBL_EPSILON ? M(1, 1): 1.;
z = 1./std::sqrt(c * c + s * s + DBL_EPSILON);
c *= z;
s *= z;

View File

@ -141,4 +141,23 @@ TEST(Calib3d_DecomposeProjectionMatrix, accuracy)
test.safe_run();
}
TEST(Calib3d_DecomposeProjectionMatrix, degenerate_cases)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 2; j++)
{
cv::Matx34d P;
P(0, i) = 1;
P(1, (i + j + 1) % 3) = 1;
P(2, (i + 2 * j + 2) % 3) = 1;
cv::Matx33d K, R;
cv::Vec4d t;
decomposeProjectionMatrix(P, K, R, t);
EXPECT_LT(cv::norm(K * R, P.get_minor<3, 3>(0, 0), cv::NORM_INF), 1e-6);
}
}
}
}} // namespace

View File

@ -83,6 +83,19 @@ class AttentionLayerImpl CV_FINAL : public AttentionLayer {
} else {
CV_Error(Error::StsBadArg, format("DNN/Attention: invalid output dimension %zu, valid value is 2 or 3", output_ndims));
}
const int batch_size_ = input_shape[0], seq_len_ = input_shape[1],
hidden_size_ = weight_shape.back(),
num_heads_ = static_cast<int>(num_heads),
v_head_size_ = static_cast<int>((hidden_size_ - qkv_hidden_sizes[0] - qkv_hidden_sizes[1]) / num_heads);
MatShape gemm_buffer_shape{batch_size_, seq_len_, hidden_size_},
attention_prob_shape{batch_size_ * num_heads_, seq_len_, seq_len_},
output_buffer_shape{batch_size_ * num_heads_, seq_len_, v_head_size_};
internals.assign(1, gemm_buffer_shape);
internals.push_back(attention_prob_shape);
internals.push_back(output_buffer_shape);
return false;
}
@ -112,9 +125,10 @@ class AttentionLayerImpl CV_FINAL : public AttentionLayer {
return;
}
std::vector<Mat> inputs, outputs;
std::vector<Mat> inputs, outputs, internals;
inputs_arr.getMatVector(inputs);
outputs_arr.getMatVector(outputs);
internals_arr.getMatVector(internals);
// prepack weights
if (!is_prepacked) {
@ -131,7 +145,8 @@ class AttentionLayerImpl CV_FINAL : public AttentionLayer {
float *packed_weights[3] = {packed_weight_q.data(), packed_weight_k.data(), packed_weight_v.data()};
size_t packed_weights_size[3] = {packed_weight_q.size() / num_heads, packed_weight_k.size() / num_heads, packed_weight_v.size() / num_heads};
Mat gemm_buffer = Mat::zeros(1, int(batch_size * seq_len * hidden_size), CV_32F);
// Compute Q/K/V
auto &gemm_buffer = internals[0];
auto *Q = gemm_buffer.ptr<float>();
auto *K = Q + batch_size * seq_len * qkv_hidden_sizes[0];
auto *V = K + batch_size * seq_len * qkv_hidden_sizes[1];
@ -177,9 +192,8 @@ class AttentionLayerImpl CV_FINAL : public AttentionLayer {
parallel_for_(Range(0, loops), fn, nstripes);
}
// Compute softmax(scale * matmul(Q, K))
std::vector<int> attention_prob_shape{int(batch_size * num_heads), int(seq_len), int(seq_len)};
Mat attention_prob = Mat::zeros(attention_prob_shape.size(), attention_prob_shape.data(), CV_32F);
// Compute Softmax(scale * MatMul(Q, K))
auto &attention_prob = internals[1];
{
auto *output = attention_prob.ptr<float>();
@ -202,12 +216,12 @@ class AttentionLayerImpl CV_FINAL : public AttentionLayer {
}
}, loops * seq_len * qk_head_size * seq_len * (1 / 1024.0));
// Compute softmax
softmax(attention_prob, attention_prob, attention_prob_shape.size() - 1);
// Compute softmax on the last dimension
softmax(attention_prob, attention_prob, shape(attention_prob).size() - 1);
}
// Compute np.matmul(attention_prob, V)
Mat output_buffer = Mat::zeros(1, int(batch_size * num_heads * seq_len * qkv_head_sizes[2]), CV_32F);
// Compute MatMul(attention_prob, V)
auto &output_buffer = internals[2];
{
auto *output = outputs[0].ptr<float>();
auto *output_buff = output_buffer.ptr<float>();

View File

@ -547,7 +547,7 @@ public:
MatShape realOutputDims = shape(result);
size_t realProd = std::accumulate(realOutputDims.begin(), realOutputDims.end(), 1, std::multiplies<int>());
CV_CheckEQ(reqProd, realProd, "Real output can not be shaped in to requred output");
CV_CheckEQ(reqProd, realProd, "Real output can not be shaped in to required output");
// reduce dimentions
result = result.reshape(1, einsumOutDims.size(), einsumOutDims.data());
@ -1280,11 +1280,12 @@ Mat LayerEinsumImpl::pairwiseOperandProcess(
// Covered by ExplicitEinsumAsTensorContractionReshapeFinal.
output = output.reshape(1, reshaped_dims.size(), reshaped_dims.data());
}
} else {
output = Transpose(
output,
outputDims,
outputPermutation);
else {
output = Transpose(
output,
outputDims,
outputPermutation);
}
}
} else { // This is the final pair - Transpose directly to the output ordering required and copy the contents to the op's output
// not sure if this finalize shape is needed at all

View File

@ -274,7 +274,8 @@ enum InterpolationFlags{
- flag is __not__ set: \f$dst( \rho , \phi ) = src(x,y)\f$
- flag is set: \f$dst(x,y) = src( \rho , \phi )\f$
*/
WARP_INVERSE_MAP = 16
WARP_INVERSE_MAP = 16,
WARP_RELATIVE_MAP = 32
};
/** \brief Specify the polar mapping mode
@ -2510,6 +2511,7 @@ CV_EXPORTS_W void warpPerspective( InputArray src, OutputArray dst,
The function remap transforms the source image using the specified map:
\f[\texttt{dst} (x,y) = \texttt{src} (map_x(x,y),map_y(x,y))\f]
\f[\texttt{dst} (x,y) = \texttt{src} (x+map_x(x,y),y+map_y(x,y))\f] with WARP_RELATIVE_MAP
where values of pixels with non-integer coordinates are computed using one of available
interpolation methods. \f$map_x\f$ and \f$map_y\f$ can be encoded as separate floating-point maps
@ -2529,7 +2531,9 @@ representation to fixed-point for speed.
@param map2 The second map of y values having the type CV_16UC1, CV_32FC1, or none (empty map
if map1 is (x,y) points), respectively.
@param interpolation Interpolation method (see #InterpolationFlags). The methods #INTER_AREA
and #INTER_LINEAR_EXACT are not supported by this function.
#INTER_LINEAR_EXACT and #INTER_NEAREST_EXACT are not supported by this function.
The extra flag WARP_RELATIVE_MAP that can be ORed to the interpolation method
(e.g. INTER_LINEAR | WARP_RELATIVE_MAP)
@param borderMode Pixel extrapolation method (see #BorderTypes). When
borderMode=#BORDER_TRANSPARENT, it means that the pixels in the destination image that
corresponds to the "outliers" in the source image are not modified by the function.

View File

@ -9,14 +9,15 @@ enum{HALF_SIZE=0, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH};
CV_ENUM(BorderMode, BORDER_CONSTANT, BORDER_REPLICATE)
CV_ENUM(InterType, INTER_NEAREST, INTER_LINEAR)
CV_ENUM(InterTypeExtended, INTER_NEAREST, INTER_LINEAR, WARP_RELATIVE_MAP)
CV_ENUM(RemapMode, HALF_SIZE, UPSIDE_DOWN, REFLECTION_X, REFLECTION_BOTH)
typedef TestBaseWithParam< tuple<Size, InterType, BorderMode> > TestWarpAffine;
typedef TestBaseWithParam< tuple<Size, InterType, BorderMode> > TestWarpPerspective;
typedef TestBaseWithParam< tuple<Size, InterType, BorderMode, MatType> > TestWarpPerspectiveNear_t;
typedef TestBaseWithParam< tuple<MatType, Size, InterType, BorderMode, RemapMode> > TestRemap;
typedef TestBaseWithParam< tuple<MatType, Size, InterTypeExtended, BorderMode, RemapMode> > TestRemap;
void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode );
void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode, bool relative = false );
PERF_TEST_P( TestWarpAffine, WarpAffine,
Combine(
@ -204,7 +205,7 @@ PERF_TEST_P( TestRemap, remap,
Combine(
Values( CV_8UC1, CV_8UC3, CV_8UC4, CV_32FC1 ),
Values( szVGA, sz1080p ),
InterType::all(),
InterTypeExtended::all(),
BorderMode::all(),
RemapMode::all()
)
@ -224,7 +225,7 @@ PERF_TEST_P( TestRemap, remap,
declare.in(source, WARMUP_RNG);
update_map(source, map_x, map_y, remapMode);
update_map(source, map_x, map_y, remapMode, ((interpolationType & WARP_RELATIVE_MAP) != 0));
TEST_CYCLE()
{
@ -234,7 +235,7 @@ PERF_TEST_P( TestRemap, remap,
SANITY_CHECK_NOTHING();
}
void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode )
void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode, bool relative )
{
for( int j = 0; j < src.rows; j++ )
{
@ -267,6 +268,12 @@ void update_map(const Mat& src, Mat& map_x, Mat& map_y, const int remapMode )
map_y.at<float>(j,i) = static_cast<float>(src.rows - j) ;
break;
} // end of switch
if( relative )
{
map_x.at<float>(j,i) -= static_cast<float>(i);
map_y.at<float>(j,i) -= static_cast<float>(j);
}
}
}
}

View File

@ -326,9 +326,9 @@ static inline int clip(int x, int a, int b)
* General warping (affine, perspective, remap) *
\****************************************************************************************/
template<typename T>
template<typename T, bool isRelative>
static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
int borderType, const Scalar& _borderValue )
int borderType, const Scalar& _borderValue, const Point& _offset )
{
Size ssize = _src.size(), dsize = _dst.size();
const int cn = _src.channels();
@ -341,7 +341,7 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
unsigned width1 = ssize.width, height1 = ssize.height;
if( _dst.isContinuous() && _xy.isContinuous() )
if( _dst.isContinuous() && _xy.isContinuous() && !isRelative )
{
dsize.width *= dsize.height;
dsize.height = 1;
@ -351,12 +351,13 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
{
T* D = _dst.ptr<T>(dy);
const short* XY = _xy.ptr<short>(dy);
const int off_y = isRelative ? (_offset.y+dy) : 0;
if( cn == 1 )
{
for(int dx = 0; dx < dsize.width; dx++ )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
const int off_x = isRelative ? (_offset.x+dx) : 0;
int sx = XY[dx*2]+off_x, sy = XY[dx*2+1]+off_y;
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
D[dx] = S0[sy*sstep + sx];
else
@ -382,7 +383,8 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
{
for(int dx = 0; dx < dsize.width; dx++, D += cn )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
const int off_x = isRelative ? (_offset.x+dx) : 0;
int sx = XY[dx*2]+off_x, sy = XY[dx*2+1]+off_y;
const T *S;
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
{
@ -427,11 +429,11 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
}
}
template<bool>
struct RemapNoVec
{
int operator()( const Mat&, void*, const short*, const ushort*,
const void*, int ) const { return 0; }
const void*, int, cv::Point& ) const { return 0; }
};
#if CV_SIMD128
@ -439,13 +441,13 @@ struct RemapNoVec
typedef unsigned short CV_DECL_ALIGNED(1) unaligned_ushort;
typedef int CV_DECL_ALIGNED(1) unaligned_int;
template<bool isRelative>
struct RemapVec_8u
{
int operator()( const Mat& _src, void* _dst, const short* XY,
const ushort* FXY, const void* _wtab, int width ) const
const ushort* FXY, const void* _wtab, int width, const Point& _offset ) const
{
int cn = _src.channels(), x = 0, sstep = (int)_src.step;
if( (cn != 1 && cn != 3 && cn != 4) || sstep >= 0x8000 )
return 0;
@ -493,12 +495,25 @@ struct RemapVec_8u
*(unaligned_ushort*)(base + offset[2]), *(unaligned_ushort*)(base + offset[3]), \
0, 0, 0, 0)
const short _rel_offset_x = static_cast<short>(_offset.x);
const short _rel_offset_y = static_cast<short>(_offset.y);
v_int16x8 v_dxy0(_rel_offset_x, _rel_offset_y, _rel_offset_x, _rel_offset_y, _rel_offset_x, _rel_offset_y, _rel_offset_x, _rel_offset_y);
v_int16x8 v_dxy1 = v_dxy0;
v_dxy0 = v_add(v_dxy0, v_int16x8(0, 0, 1, 0, 2, 0, 3, 0));
v_dxy1 = v_add(v_dxy1, v_int16x8(4, 0, 5, 0, 6, 0, 7, 0));
if( cn == 1 )
{
for( ; x <= width - 8; x += 8 )
{
v_int16x8 _xy0 = v_load(XY + x*2);
v_int16x8 _xy1 = v_load(XY + x*2 + 8);
if (isRelative)
{
const short x_s16 = static_cast<short>(x);
v_int16x8 v_dxy01(x_s16, 0, x_s16, 0, x_s16, 0, x_s16, 0);
_xy0 = v_add(_xy0, v_add(v_dxy01, v_dxy0));
_xy1 = v_add(_xy1, v_add(v_dxy01, v_dxy1));
}
v_int32x4 v0, v1, v2, v3, a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2;
v_int32x4 xy0 = v_dotprod( _xy0, xy2ofs );
@ -545,6 +560,12 @@ struct RemapVec_8u
{
v_int16x8 u0, v0, u1, v1;
v_int16x8 _xy0 = v_load(XY + x * 2);
if (isRelative)
{
const short x_s16 = static_cast<short>(x);
v_int16x8 v_dxy01(x_s16, 0, x_s16, 0, x_s16, 0, x_s16, 0);
_xy0 = v_add(_xy0, v_add(v_dxy01, v_dxy0));
}
v_int32x4 xy0 = v_dotprod(_xy0, xy2ofs);
v_store(iofs0, xy0);
@ -595,10 +616,17 @@ struct RemapVec_8u
for( ; x <= width - 4; x += 4, D += 16 )
{
v_int16x8 _xy0 = v_load(XY + x * 2);
if (isRelative)
{
const short x_s16 = static_cast<short>(x);
v_int16x8 v_dxy01(x_s16, 0, x_s16, 0, x_s16, 0, x_s16, 0);
_xy0 = v_add(_xy0, v_add(v_dxy01, v_dxy0));
}
v_int16x8 u0, v0, u1, v1;
v_int32x4 xy0 = v_dotprod( _xy0, xy2ofs );
v_store(iofs0, xy0);
int offset0 = FXY[x] * 16;
int offset1 = FXY[x + 1] * 16;
int offset2 = FXY[x + 2] * 16;
@ -640,15 +668,14 @@ struct RemapVec_8u
#else
typedef RemapNoVec RemapVec_8u;
template<bool isRelative> using RemapVec_8u = RemapNoVec<isRelative>;
#endif
template<class CastOp, class VecOp, typename AT>
template<class CastOp, class VecOp, typename AT, bool isRelative>
static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
const Mat& _fxy, const void* _wtab,
int borderType, const Scalar& _borderValue )
int borderType, const Scalar& _borderValue, const Point& _offset )
{
typedef typename CastOp::rtype T;
typedef typename CastOp::type1 WT;
@ -678,12 +705,12 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
const ushort* FXY = _fxy.ptr<ushort>(dy);
int X0 = 0;
bool prevInlier = false;
const int off_y = (isRelative ? (_offset.y+dy) : 0);
for(int dx = 0; dx <= dsize.width; dx++ )
{
bool curInlier = dx < dsize.width ?
(unsigned)XY[dx*2] < width1 &&
(unsigned)XY[dx*2+1] < height1 : !prevInlier;
(unsigned)XY[dx*2]+(isRelative ? (_offset.x+dx) : 0) < width1 &&
(unsigned)XY[dx*2+1]+off_y < height1 : !prevInlier;
if( curInlier == prevInlier )
continue;
@ -694,7 +721,8 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
if( !curInlier )
{
int len = vecOp( _src, D, XY + dx*2, FXY + dx, wtab, X1 - dx );
Point subOffset(_offset.x+dx, _offset.y+dy);
int len = vecOp( _src, D, XY + dx*2, FXY + dx, wtab, X1 - dx, subOffset );
D += len*cn;
dx += len;
@ -702,7 +730,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
{
for( ; dx < X1; dx++, D++ )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
const AT* w = wtab + FXY[dx]*4;
const T* S = S0 + sy*sstep + sx;
*D = castOp(WT(S[0]*w[0] + S[1]*w[1] + S[sstep]*w[2] + S[sstep+1]*w[3]));
@ -711,7 +739,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
else if( cn == 2 )
for( ; dx < X1; dx++, D += 2 )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
const AT* w = wtab + FXY[dx]*4;
const T* S = S0 + sy*sstep + sx*2;
WT t0 = S[0]*w[0] + S[2]*w[1] + S[sstep]*w[2] + S[sstep+2]*w[3];
@ -721,7 +749,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
else if( cn == 3 )
for( ; dx < X1; dx++, D += 3 )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
const AT* w = wtab + FXY[dx]*4;
const T* S = S0 + sy*sstep + sx*3;
WT t0 = S[0]*w[0] + S[3]*w[1] + S[sstep]*w[2] + S[sstep+3]*w[3];
@ -732,7 +760,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
else if( cn == 4 )
for( ; dx < X1; dx++, D += 4 )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
const AT* w = wtab + FXY[dx]*4;
const T* S = S0 + sy*sstep + sx*4;
WT t0 = S[0]*w[0] + S[4]*w[1] + S[sstep]*w[2] + S[sstep+4]*w[3];
@ -745,7 +773,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
else
for( ; dx < X1; dx++, D += cn )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
const AT* w = wtab + FXY[dx]*4;
const T* S = S0 + sy*sstep + sx*cn;
for(int k = 0; k < cn; k++ )
@ -760,7 +788,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
if (borderType == BORDER_TRANSPARENT) {
for (; dx < X1; dx++, D += cn) {
if (dx >= dsize.width) continue;
const int sx = XY[dx * 2], sy = XY[dx * 2 + 1];
const int sx = XY[dx * 2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx * 2 + 1]+off_y;
// If the mapped point is still within bounds, it did not get computed
// because it lacked 4 neighbors. Still, it can be computed with an
// approximate formula. If it is outside, the point is left untouched.
@ -791,7 +819,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
if( cn == 1 )
for( ; dx < X1; dx++, D++ )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
if( borderType == BORDER_CONSTANT &&
(sx >= ssize.width || sx+1 < 0 ||
sy >= ssize.height || sy+1 < 0) )
@ -831,7 +859,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
else
for( ; dx < X1; dx++, D += cn )
{
int sx = XY[dx*2], sy = XY[dx*2+1];
int sx = XY[dx*2]+(isRelative ? (_offset.x+dx) : 0), sy = XY[dx*2+1]+off_y;
if( borderType == BORDER_CONSTANT &&
(sx >= ssize.width || sx+1 < 0 ||
sy >= ssize.height || sy+1 < 0) )
@ -876,10 +904,10 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
}
template<class CastOp, typename AT, int ONE>
template<class CastOp, typename AT, int ONE, bool isRelative>
static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
const Mat& _fxy, const void* _wtab,
int borderType, const Scalar& _borderValue )
int borderType, const Scalar& _borderValue, const Point& _offset )
{
typedef typename CastOp::rtype T;
typedef typename CastOp::type1 WT;
@ -898,7 +926,7 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
unsigned width1 = std::max(ssize.width-3, 0), height1 = std::max(ssize.height-3, 0);
if( _dst.isContinuous() && _xy.isContinuous() && _fxy.isContinuous() )
if( _dst.isContinuous() && _xy.isContinuous() && _fxy.isContinuous() && !isRelative )
{
dsize.width *= dsize.height;
dsize.height = 1;
@ -909,10 +937,11 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
T* D = _dst.ptr<T>(dy);
const short* XY = _xy.ptr<short>(dy);
const ushort* FXY = _fxy.ptr<ushort>(dy);
const int off_y = isRelative ? (_offset.y+dy) : 0;
for(int dx = 0; dx < dsize.width; dx++, D += cn )
{
int sx = XY[dx*2]-1, sy = XY[dx*2+1]-1;
const int off_x = isRelative ? (_offset.x+dx) : 0;
int sx = XY[dx*2]-1+off_x, sy = XY[dx*2+1]-1+off_y;
const AT* w = wtab + FXY[dx]*16;
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
{
@ -980,10 +1009,10 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
}
template<class CastOp, typename AT, int ONE>
template<class CastOp, typename AT, int ONE, bool isRelative>
static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
const Mat& _fxy, const void* _wtab,
int borderType, const Scalar& _borderValue )
int borderType, const Scalar& _borderValue, const Point& _offset )
{
typedef typename CastOp::rtype T;
typedef typename CastOp::type1 WT;
@ -1002,7 +1031,7 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
unsigned width1 = std::max(ssize.width-7, 0), height1 = std::max(ssize.height-7, 0);
if( _dst.isContinuous() && _xy.isContinuous() && _fxy.isContinuous() )
if( _dst.isContinuous() && _xy.isContinuous() && _fxy.isContinuous() && !isRelative )
{
dsize.width *= dsize.height;
dsize.height = 1;
@ -1013,10 +1042,11 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
T* D = _dst.ptr<T>(dy);
const short* XY = _xy.ptr<short>(dy);
const ushort* FXY = _fxy.ptr<ushort>(dy);
const int off_y = isRelative ? (_offset.y+dy) : 0;
for(int dx = 0; dx < dsize.width; dx++, D += cn )
{
int sx = XY[dx*2]-3, sy = XY[dx*2+1]-3;
const int off_x = isRelative ? (_offset.x+dx) : 0;
int sx = XY[dx*2]-3+off_x, sy = XY[dx*2+1]-3+off_y;
const AT* w = wtab + FXY[dx]*64;
const T* S = S0 + sy*sstep + sx*cn;
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
@ -1091,11 +1121,11 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
typedef void (*RemapNNFunc)(const Mat& _src, Mat& _dst, const Mat& _xy,
int borderType, const Scalar& _borderValue );
int borderType, const Scalar& _borderValue, const Point& _offset);
typedef void (*RemapFunc)(const Mat& _src, Mat& _dst, const Mat& _xy,
const Mat& _fxy, const void* _wtab,
int borderType, const Scalar& _borderValue);
int borderType, const Scalar& _borderValue, const Point& _offset);
class RemapInvoker :
public ParallelLoopBody
@ -1186,7 +1216,7 @@ public:
}
}
}
nnfunc( *src, dpart, bufxy, borderType, borderValue );
nnfunc( *src, dpart, bufxy, borderType, borderValue, Point(x, y) );
continue;
}
@ -1293,7 +1323,7 @@ public:
}
}
}
ifunc(*src, dpart, bufxy, bufa, ctab, borderType, borderValue);
ifunc(*src, dpart, bufxy, bufa, ctab, borderType, borderValue, Point(x, y));
}
}
}
@ -1315,6 +1345,9 @@ private:
static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, InputArray _map2,
int interpolation, int borderType, const Scalar& borderValue)
{
const bool hasRelativeFlag = ((interpolation & cv::WARP_RELATIVE_MAP) != 0);
interpolation &= ~cv::WARP_RELATIVE_MAP;
const ocl::Device & dev = ocl::Device::getDefault();
int cn = _src.channels(), type = _src.type(), depth = _src.depth(),
rowsPerWI = dev.isIntel() ? 4 : 1;
@ -1354,9 +1387,10 @@ static bool ocl_remap(InputArray _src, OutputArray _dst, InputArray _map1, Input
static const char * const interMap[] = { "INTER_NEAREST", "INTER_LINEAR", "INTER_CUBIC", "INTER_LINEAR", "INTER_LANCZOS" };
static const char * const borderMap[] = { "BORDER_CONSTANT", "BORDER_REPLICATE", "BORDER_REFLECT", "BORDER_WRAP",
"BORDER_REFLECT_101", "BORDER_TRANSPARENT" };
String buildOptions = format("-D %s -D %s -D T=%s -D ROWS_PER_WI=%d",
String buildOptions = format("-D %s -D %s -D T=%s -D ROWS_PER_WI=%d -D WARP_RELATIVE=%d",
interMap[interpolation], borderMap[borderType],
ocl::typeToStr(type), rowsPerWI);
ocl::typeToStr(type), rowsPerWI,
hasRelativeFlag ? 1 : 0);
if (interpolation != INTER_NEAREST)
{
@ -1687,38 +1721,73 @@ void cv::remap( InputArray _src, OutputArray _dst,
{
CV_INSTRUMENT_REGION();
static RemapNNFunc nn_tab[CV_DEPTH_MAX] =
const bool hasRelativeFlag = ((interpolation & cv::WARP_RELATIVE_MAP) != 0);
static RemapNNFunc nn_tab[2][CV_DEPTH_MAX] =
{
remapNearest<uchar>, remapNearest<schar>, remapNearest<ushort>, remapNearest<short>,
remapNearest<int>, remapNearest<float>, remapNearest<double>, 0
{
remapNearest<uchar, false>, remapNearest<schar, false>, remapNearest<ushort, false>, remapNearest<short, false>,
remapNearest<int, false>, remapNearest<float, false>, remapNearest<double, false>, 0
},
{
remapNearest<uchar, true>, remapNearest<schar, true>, remapNearest<ushort, true>, remapNearest<short, true>,
remapNearest<int, true>, remapNearest<float, true>, remapNearest<double, true>, 0
}
};
static RemapFunc linear_tab[CV_DEPTH_MAX] =
static RemapFunc linear_tab[2][CV_DEPTH_MAX] =
{
remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u, short>, 0,
remapBilinear<Cast<float, ushort>, RemapNoVec, float>,
remapBilinear<Cast<float, short>, RemapNoVec, float>, 0,
remapBilinear<Cast<float, float>, RemapNoVec, float>,
remapBilinear<Cast<double, double>, RemapNoVec, float>, 0
{
remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u<false>, short, false>, 0,
remapBilinear<Cast<float, ushort>, RemapNoVec<false>, float, false>,
remapBilinear<Cast<float, short>, RemapNoVec<false>, float, false>, 0,
remapBilinear<Cast<float, float>, RemapNoVec<false>, float, false>,
remapBilinear<Cast<double, double>, RemapNoVec<false>, float, false>, 0
},
{
remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u<true>, short, true>, 0,
remapBilinear<Cast<float, ushort>, RemapNoVec<true>, float, true>,
remapBilinear<Cast<float, short>, RemapNoVec<true>, float, true>, 0,
remapBilinear<Cast<float, float>, RemapNoVec<true>, float, true>,
remapBilinear<Cast<double, double>, RemapNoVec<true>, float, true>, 0
}
};
static RemapFunc cubic_tab[CV_DEPTH_MAX] =
static RemapFunc cubic_tab[2][CV_DEPTH_MAX] =
{
remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE>, 0,
remapBicubic<Cast<float, ushort>, float, 1>,
remapBicubic<Cast<float, short>, float, 1>, 0,
remapBicubic<Cast<float, float>, float, 1>,
remapBicubic<Cast<double, double>, float, 1>, 0
};
{
remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, false>, 0,
remapBicubic<Cast<float, ushort>, float, 1, false>,
remapBicubic<Cast<float, short>, float, 1, false>, 0,
remapBicubic<Cast<float, float>, float, 1, false>,
remapBicubic<Cast<double, double>, float, 1, false>, 0
},
{
remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, true>, 0,
remapBicubic<Cast<float, ushort>, float, 1, true>,
remapBicubic<Cast<float, short>, float, 1, true>, 0,
remapBicubic<Cast<float, float>, float, 1, true>,
remapBicubic<Cast<double, double>, float, 1, true>, 0
}
};
static RemapFunc lanczos4_tab[CV_DEPTH_MAX] =
static RemapFunc lanczos4_tab[2][8] =
{
remapLanczos4<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE>, 0,
remapLanczos4<Cast<float, ushort>, float, 1>,
remapLanczos4<Cast<float, short>, float, 1>, 0,
remapLanczos4<Cast<float, float>, float, 1>,
remapLanczos4<Cast<double, double>, float, 1>, 0
};
{
remapLanczos4<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, false>, 0,
remapLanczos4<Cast<float, ushort>, float, 1, false>,
remapLanczos4<Cast<float, short>, float, 1, false>, 0,
remapLanczos4<Cast<float, float>, float, 1, false>,
remapLanczos4<Cast<double, double>, float, 1, false>, 0
},
{
remapLanczos4<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE, true>, 0,
remapLanczos4<Cast<float, ushort>, float, 1, true>,
remapLanczos4<Cast<float, short>, float, 1, true>, 0,
remapLanczos4<Cast<float, float>, float, 1, true>,
remapLanczos4<Cast<double, double>, float, 1, true>, 0
}
};
CV_Assert( !_map1.empty() );
CV_Assert( _map2.empty() || (_map2.size() == _map1.size()));
@ -1738,7 +1807,8 @@ void cv::remap( InputArray _src, OutputArray _dst,
((map1.type() == CV_32FC2 && map2.empty() && map1.size == dst.size) ||
(map1.type() == CV_32FC1 && map2.type() == CV_32FC1 && map1.size == dst.size && map2.size == dst.size) ||
(map1.empty() && map2.type() == CV_32FC2 && map2.size == dst.size)) &&
((borderType & BORDER_ISOLATED) != 0 || !src.isSubmatrix()),
((borderType & BORDER_ISOLATED) != 0 || !src.isSubmatrix()) &&
!hasRelativeFlag,
openvx_remap(src, dst, map1, map2, interpolation, borderValue));
CV_Assert( dst.cols < SHRT_MAX && dst.rows < SHRT_MAX && src.cols < SHRT_MAX && src.rows < SHRT_MAX );
@ -1746,6 +1816,7 @@ void cv::remap( InputArray _src, OutputArray _dst,
if( dst.data == src.data )
src = src.clone();
interpolation &= ~cv::WARP_RELATIVE_MAP;
if( interpolation == INTER_AREA )
interpolation = INTER_LINEAR;
@ -1798,21 +1869,22 @@ void cv::remap( InputArray _src, OutputArray _dst,
bool fixpt = depth == CV_8U;
bool planar_input = false;
const int relativeOptionIndex = (hasRelativeFlag ? 1 : 0);
if( interpolation == INTER_NEAREST )
{
nnfunc = nn_tab[depth];
nnfunc = nn_tab[relativeOptionIndex][depth];
CV_Assert( nnfunc != 0 );
}
else
{
if( interpolation == INTER_LINEAR )
ifunc = linear_tab[depth];
ifunc = linear_tab[relativeOptionIndex][depth];
else if( interpolation == INTER_CUBIC ){
ifunc = cubic_tab[depth];
ifunc = cubic_tab[relativeOptionIndex][depth];
CV_Assert( _src.channels() <= 4 );
}
else if( interpolation == INTER_LANCZOS4 ){
ifunc = lanczos4_tab[depth];
ifunc = lanczos4_tab[relativeOptionIndex][depth];
CV_Assert( _src.channels() <= 4 );
}
else

View File

@ -168,6 +168,10 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src
int gx = convert_int_sat_rte(map1[0]);
int gy = convert_int_sat_rte(map2[0]);
#if WARP_RELATIVE
gx += x;
gy += y;
#endif
if (NEED_EXTRAPOLATION(gx, gy))
{
@ -210,6 +214,11 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o
__global T * dst = (__global T *)(dstptr + dst_index);
int2 gxy = convert_int2_sat_rte(map[0]);
#if WARP_RELATIVE
gxy.x += x;
gxy.y += y;
#endif
int gx = gxy.x, gy = gxy.y;
if (NEED_EXTRAPOLATION(gx, gy))
@ -250,6 +259,11 @@ __kernel void remap_16SC2(__global const uchar * srcptr, int src_step, int src_o
__global T * dst = (__global T *)(dstptr + dst_index);
int2 gxy = convert_int2(map[0]);
#if WARP_RELATIVE
gxy.x += x;
gxy.y += y;
#endif
int gx = gxy.x, gy = gxy.y;
if (NEED_EXTRAPOLATION(gx, gy))
@ -296,6 +310,11 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int
int dx = (map2Value & (INTER_TAB_SIZE - 1)) < (INTER_TAB_SIZE >> 1) ? 1 : 0;
int dy = (map2Value >> INTER_BITS) < (INTER_TAB_SIZE >> 1) ? 1 : 0;
int2 gxy = convert_int2(map1[0]) + (int2)(dx, dy);
#if WARP_RELATIVE
gxy.x += x;
gxy.y += y;
#endif
int gx = gxy.x, gy = gxy.y;
if (NEED_EXTRAPOLATION(gx, gy))
@ -349,6 +368,10 @@ __kernel void remap_16SC2_16UC1(__global const uchar * srcptr, int src_step, int
__global T * dst = (__global T *)(dstptr + dst_index);
int2 map_dataA = convert_int2(map1[0]);
#if WARP_RELATIVE
map_dataA.x += x;
map_dataA.y += y;
#endif
int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y);
int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1);
int2 map_dataD = (int2)(map_dataA.x + 1, map_dataA.y + 1);
@ -414,8 +437,12 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src
#if defined BORDER_CONSTANT
float xf = map1[0], yf = map2[0];
int sx = convert_int_sat_rtz(mad(xf, (float)INTER_TAB_SIZE, 0.5f)) >> INTER_BITS;
int sy = convert_int_sat_rtz(mad(yf, (float)INTER_TAB_SIZE, 0.5f)) >> INTER_BITS;
int sx = (convert_int_sat_rtz(mad(xf, (float)INTER_TAB_SIZE, 0.5f)) >> INTER_BITS);
int sy = (convert_int_sat_rtz(mad(yf, (float)INTER_TAB_SIZE, 0.5f)) >> INTER_BITS);
#if WARP_RELATIVE
sx += x;
sy += y;
#endif
__constant float * coeffs_x = coeffs + ((convert_int_rte(xf * INTER_TAB_SIZE) & (INTER_TAB_SIZE - 1)) << 1);
__constant float * coeffs_y = coeffs + ((convert_int_rte(yf * INTER_TAB_SIZE) & (INTER_TAB_SIZE - 1)) << 1);
@ -456,6 +483,10 @@ __kernel void remap_2_32FC1(__global const uchar * srcptr, int src_step, int src
storepix(CONVERT_TO_T(sum), dst);
#else
float2 map_data = (float2)(map1[0], map2[0]);
#if WARP_RELATIVE
map_data.x += x;
map_data.y += y;
#endif
int2 map_dataA = convert_int2_sat_rtn(map_data);
int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y);
@ -520,6 +551,10 @@ __kernel void remap_32FC2(__global const uchar * srcptr, int src_step, int src_o
__global T * dst = (__global T *)(dstptr + dst_index);
float2 map_data = map[0];
#if WARP_RELATIVE
map_data.x += x;
map_data.y += y;
#endif
int2 map_dataA = convert_int2_sat_rtn(map_data);
int2 map_dataB = (int2)(map_dataA.x + 1, map_dataA.y);
int2 map_dataC = (int2)(map_dataA.x, map_dataA.y + 1);

View File

@ -438,6 +438,101 @@ OCL_TEST_P(Remap_INTER_LINEAR, Mat)
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
// remap relative
PARAM_TEST_CASE(RemapRelative, MatDepth, Channels, Interpolation, BorderType, bool)
{
int srcType;
int interpolation;
int borderType;
bool useFixedPoint;
Scalar val;
TEST_DECLARE_INPUT_PARAMETER(map1);
TEST_DECLARE_INPUT_PARAMETER(map2);
TEST_DECLARE_OUTPUT_PARAMETER(dst);
UMat uSrc;
UMat uMapRelativeX32F;
UMat uMapRelativeY32F;
UMat uMapAbsoluteX32F;
UMat uMapAbsoluteY32F;
UMat uMapRelativeX16S;
UMat uMapRelativeY16S;
UMat uMapAbsoluteX16S;
UMat uMapAbsoluteY16S;
virtual void SetUp()
{
srcType = CV_MAKE_TYPE(GET_PARAM(0), GET_PARAM(1));
interpolation = GET_PARAM(2);
borderType = GET_PARAM(3);
useFixedPoint = GET_PARAM(4);
const int nChannels = CV_MAT_CN(srcType);
const cv::Size size(127, 61);
cv::Mat data64FC1(1, size.area()*nChannels, CV_64FC1);
data64FC1.forEach<double>([&](double& pixel, const int* position) {pixel = static_cast<double>(position[1]);});
cv::Mat src;
data64FC1.reshape(nChannels, size.height).convertTo(src, srcType);
cv::Mat mapRelativeX32F(size, CV_32FC1);
mapRelativeX32F.setTo(cv::Scalar::all(-0.33));
cv::Mat mapRelativeY32F(size, CV_32FC1);
mapRelativeY32F.setTo(cv::Scalar::all(-0.33));
cv::Mat mapAbsoluteX32F = mapRelativeX32F.clone();
mapAbsoluteX32F.forEach<float>([&](float& pixel, const int* position) {
pixel += static_cast<float>(position[1]);
});
cv::Mat mapAbsoluteY32F = mapRelativeY32F.clone();
mapAbsoluteY32F.forEach<float>([&](float& pixel, const int* position) {
pixel += static_cast<float>(position[0]);
});
OCL_ON(src.copyTo(uSrc));
OCL_ON(mapRelativeX32F.copyTo(uMapRelativeX32F));
OCL_ON(mapRelativeY32F.copyTo(uMapRelativeY32F));
OCL_ON(mapAbsoluteX32F.copyTo(uMapAbsoluteX32F));
OCL_ON(mapAbsoluteY32F.copyTo(uMapAbsoluteY32F));
if (useFixedPoint)
{
const bool nninterpolation = (interpolation == cv::INTER_NEAREST) || (interpolation == cv::INTER_NEAREST_EXACT);
OCL_ON(cv::convertMaps(uMapAbsoluteX32F, uMapAbsoluteY32F, uMapAbsoluteX16S, uMapAbsoluteY16S, CV_16SC2, nninterpolation));
OCL_ON(cv::convertMaps(uMapRelativeX32F, uMapRelativeY32F, uMapRelativeX16S, uMapRelativeY16S, CV_16SC2, nninterpolation));
}
}
};
OCL_TEST_P(RemapRelative, Mat)
{
cv::UMat uDstAbsolute;
cv::UMat uDstRelative;
if (useFixedPoint)
{
OCL_ON(cv::remap(uSrc, uDstAbsolute, uMapAbsoluteX16S, uMapAbsoluteY16S, interpolation, borderType));
OCL_ON(cv::remap(uSrc, uDstRelative, uMapRelativeX16S, uMapRelativeY16S, interpolation | WARP_RELATIVE_MAP, borderType));
}
else
{
OCL_ON(cv::remap(uSrc, uDstAbsolute, uMapAbsoluteX32F, uMapAbsoluteY32F, interpolation, borderType));
OCL_ON(cv::remap(uSrc, uDstRelative, uMapRelativeX32F, uMapRelativeY32F, interpolation | WARP_RELATIVE_MAP, borderType));
}
cv::Mat dstAbsolute;
OCL_ON(uDstAbsolute.copyTo(dstAbsolute));
cv::Mat dstRelative;
OCL_ON(uDstRelative.copyTo(dstRelative));
EXPECT_MAT_NEAR(dstAbsolute, dstRelative, dstAbsolute.depth() == CV_32F ? 1e-3 : 1.0);
}
/////////////////////////////////////////////////////////////////////////////////////
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, WarpAffine, Combine(
@ -515,6 +610,20 @@ OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, Remap_INTER_NEAREST, Combine(
(BorderType)BORDER_REFLECT_101),
Bool()));
OCL_INSTANTIATE_TEST_CASE_P(ImgprocWarp, RemapRelative, Combine(
Values(CV_8U, CV_16U, CV_32F, CV_64F),
Values(1, 3, 4),
Values((Interpolation)INTER_NEAREST,
(Interpolation)INTER_LINEAR,
(Interpolation)INTER_CUBIC,
(Interpolation)INTER_LANCZOS4),
Values((BorderType)BORDER_CONSTANT,
(BorderType)BORDER_REPLICATE,
(BorderType)BORDER_WRAP,
(BorderType)BORDER_REFLECT,
(BorderType)BORDER_REFLECT_101),
Bool()));
} } // namespace opencv_test::ocl
#endif // HAVE_OPENCL

View File

@ -751,6 +751,73 @@ TEST(Imgproc_resize_area, regression_quarter_round)
check_resize_area<uchar>(expected, actual, 0.5);
}
typedef tuple<int, int, int, int, bool> RemapRelativeParam;
typedef testing::TestWithParam<RemapRelativeParam> Imgproc_RemapRelative;
TEST_P(Imgproc_RemapRelative, validity)
{
int srcType = CV_MAKE_TYPE(get<0>(GetParam()), get<1>(GetParam()));
int interpolation = get<2>(GetParam());
int borderType = get<3>(GetParam());
bool useFixedPoint = get<4>(GetParam());
const int nChannels = CV_MAT_CN(srcType);
const cv::Size size(127, 61);
cv::Mat data64FC1(1, size.area()*nChannels, CV_64FC1);
data64FC1.forEach<double>([&](double& pixel, const int* position) {pixel = static_cast<double>(position[1]);});
cv::Mat src;
data64FC1.reshape(nChannels, size.height).convertTo(src, srcType);
cv::Mat mapRelativeX32F(size, CV_32FC1);
mapRelativeX32F.setTo(cv::Scalar::all(-0.33));
cv::Mat mapRelativeY32F(size, CV_32FC1);
mapRelativeY32F.setTo(cv::Scalar::all(-0.33));
cv::Mat mapAbsoluteX32F = mapRelativeX32F.clone();
mapAbsoluteX32F.forEach<float>([&](float& pixel, const int* position) {
pixel += static_cast<float>(position[1]);
});
cv::Mat mapAbsoluteY32F = mapRelativeY32F.clone();
mapAbsoluteY32F.forEach<float>([&](float& pixel, const int* position) {
pixel += static_cast<float>(position[0]);
});
cv::Mat mapAbsoluteX16S;
cv::Mat mapAbsoluteY16S;
cv::Mat mapRelativeX16S;
cv::Mat mapRelativeY16S;
if (useFixedPoint)
{
const bool nninterpolation = (interpolation == cv::INTER_NEAREST) || (interpolation == cv::INTER_NEAREST_EXACT);
cv::convertMaps(mapAbsoluteX32F, mapAbsoluteY32F, mapAbsoluteX16S, mapAbsoluteY16S, CV_16SC2, nninterpolation);
cv::convertMaps(mapRelativeX32F, mapRelativeY32F, mapRelativeX16S, mapRelativeY16S, CV_16SC2, nninterpolation);
}
cv::Mat dstAbsolute;
cv::Mat dstRelative;
if (useFixedPoint)
{
cv::remap(src, dstAbsolute, mapAbsoluteX16S, mapAbsoluteY16S, interpolation, borderType);
cv::remap(src, dstRelative, mapRelativeX16S, mapRelativeY16S, interpolation | WARP_RELATIVE_MAP, borderType);
}
else
{
cv::remap(src, dstAbsolute, mapAbsoluteX32F, mapAbsoluteY32F, interpolation, borderType);
cv::remap(src, dstRelative, mapRelativeX32F, mapRelativeY32F, interpolation | WARP_RELATIVE_MAP, borderType);
}
EXPECT_EQ(cvtest::norm(dstAbsolute, dstRelative, NORM_INF), 0);
};
INSTANTIATE_TEST_CASE_P(ImgProc, Imgproc_RemapRelative, testing::Combine(
testing::Values(CV_8U, CV_16U, CV_32F, CV_64F),
testing::Values(1, 3, 4),
testing::Values((int)INTER_NEAREST, (int)INTER_LINEAR, (int)INTER_CUBIC, (int)INTER_LANCZOS4),
testing::Values((int)BORDER_CONSTANT, (int)BORDER_REPLICATE, (int)BORDER_WRAP, (int)BORDER_REFLECT, (int)BORDER_REFLECT_101),
testing::Values(false, true)));
//////////////////////////////////////////////////////////////////////////

View File

@ -200,6 +200,9 @@ private:
float score = std::sqrt(cls_score * obj_score);
face.at<float>(0, 14) = score;
// Checking if the score meets the threshold before adding the face
if (score < scoreThreshold)
continue;
// Get bounding box
float cx = ((c + bbox_v[idx * 4 + 0]) * strides[i]);
float cy = ((r + bbox_v[idx * 4 + 1]) * strides[i]);

View File

@ -18,6 +18,22 @@ opencv_fd:
rgb: false
sample: "object_detection"
# YOLOv8 object detection family from ultralytics (https://github.com/ultralytics/ultralytics)
# Might be used for all YOLOv8n YOLOv8s YOLOv8m YOLOv8l and YOLOv8x
yolov8x:
load_info:
url: "https://huggingface.co/cabelo/yolov8/resolve/main/yolov8x.onnx?download=true"
sha1: "462f15d668c046d38e27d3df01fe8142dd004cb4"
model: "yolov8x.onnx"
mean: 0.0
scale: 0.00392
width: 640
height: 640
rgb: true
classes: "object_detection_classes_yolo.txt"
background_label_id: 0
sample: "yolo_detector"
# YOLO4 object detection family from Darknet (https://github.com/AlexeyAB/darknet)
# YOLO object detection family from Darknet (https://pjreddie.com/darknet/yolo/)
# Might be used for all YOLOv2, TinyYolov2, YOLOv3, YOLOv4 and TinyYolov4