Skip to content

Commit b3d128b

Browse files
committed
Merge pull request opencv#8401 from avartenkov:multichannel_warp
2 parents 741e513 + 3fbe1f8 commit b3d128b

File tree

2 files changed

+60
-53
lines changed

2 files changed

+60
-53
lines changed

modules/imgproc/src/imgwarp.cpp

Lines changed: 44 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3533,14 +3533,13 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
35333533
int borderType, const Scalar& _borderValue )
35343534
{
35353535
Size ssize = _src.size(), dsize = _dst.size();
3536-
int cn = _src.channels();
3536+
const int cn = _src.channels();
35373537
const T* S0 = _src.ptr<T>();
3538+
T cval[CV_CN_MAX];
35383539
size_t sstep = _src.step/sizeof(S0[0]);
3539-
Scalar_<T> cval(saturate_cast<T>(_borderValue[0]),
3540-
saturate_cast<T>(_borderValue[1]),
3541-
saturate_cast<T>(_borderValue[2]),
3542-
saturate_cast<T>(_borderValue[3]));
3543-
int dx, dy;
3540+
3541+
for(int k = 0; k < cn; k++ )
3542+
cval[k] = saturate_cast<T>(_borderValue[k & 3]);
35443543

35453544
unsigned width1 = ssize.width, height1 = ssize.height;
35463545

@@ -3550,14 +3549,14 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
35503549
dsize.height = 1;
35513550
}
35523551

3553-
for( dy = 0; dy < dsize.height; dy++ )
3552+
for(int dy = 0; dy < dsize.height; dy++ )
35543553
{
35553554
T* D = _dst.ptr<T>(dy);
35563555
const short* XY = _xy.ptr<short>(dy);
35573556

35583557
if( cn == 1 )
35593558
{
3560-
for( dx = 0; dx < dsize.width; dx++ )
3559+
for(int dx = 0; dx < dsize.width; dx++ )
35613560
{
35623561
int sx = XY[dx*2], sy = XY[dx*2+1];
35633562
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
@@ -3583,9 +3582,9 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
35833582
}
35843583
else
35853584
{
3586-
for( dx = 0; dx < dsize.width; dx++, D += cn )
3585+
for(int dx = 0; dx < dsize.width; dx++, D += cn )
35873586
{
3588-
int sx = XY[dx*2], sy = XY[dx*2+1], k;
3587+
int sx = XY[dx*2], sy = XY[dx*2+1];
35893588
const T *S;
35903589
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
35913590
{
@@ -3602,7 +3601,7 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
36023601
else
36033602
{
36043603
S = S0 + sy*sstep + sx*cn;
3605-
for( k = 0; k < cn; k++ )
3604+
for(int k = 0; k < cn; k++ )
36063605
D[k] = S[k];
36073606
}
36083607
}
@@ -3622,7 +3621,7 @@ static void remapNearest( const Mat& _src, Mat& _dst, const Mat& _xy,
36223621
sy = borderInterpolate(sy, ssize.height, borderType);
36233622
S = S0 + sy*sstep + sx*cn;
36243623
}
3625-
for( k = 0; k < cn; k++ )
3624+
for(int k = 0; k < cn; k++ )
36263625
D[k] = S[k];
36273626
}
36283627
}
@@ -3852,16 +3851,15 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
38523851
typedef typename CastOp::rtype T;
38533852
typedef typename CastOp::type1 WT;
38543853
Size ssize = _src.size(), dsize = _dst.size();
3855-
int k, cn = _src.channels();
3854+
const int cn = _src.channels();
38563855
const AT* wtab = (const AT*)_wtab;
38573856
const T* S0 = _src.ptr<T>();
38583857
size_t sstep = _src.step/sizeof(S0[0]);
38593858
T cval[CV_CN_MAX];
3860-
int dx, dy;
38613859
CastOp castOp;
38623860
VecOp vecOp;
38633861

3864-
for( k = 0; k < cn; k++ )
3862+
for(int k = 0; k < cn; k++ )
38653863
cval[k] = saturate_cast<T>(_borderValue[k & 3]);
38663864

38673865
unsigned width1 = std::max(ssize.width-1, 0), height1 = std::max(ssize.height-1, 0);
@@ -3871,15 +3869,15 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
38713869
width1 = std::max(ssize.width-2, 0);
38723870
#endif
38733871

3874-
for( dy = 0; dy < dsize.height; dy++ )
3872+
for(int dy = 0; dy < dsize.height; dy++ )
38753873
{
38763874
T* D = _dst.ptr<T>(dy);
38773875
const short* XY = _xy.ptr<short>(dy);
38783876
const ushort* FXY = _fxy.ptr<ushort>(dy);
38793877
int X0 = 0;
38803878
bool prevInlier = false;
38813879

3882-
for( dx = 0; dx <= dsize.width; dx++ )
3880+
for(int dx = 0; dx <= dsize.width; dx++ )
38833881
{
38843882
bool curInlier = dx < dsize.width ?
38853883
(unsigned)XY[dx*2] < width1 &&
@@ -3948,7 +3946,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
39483946
int sx = XY[dx*2], sy = XY[dx*2+1];
39493947
const AT* w = wtab + FXY[dx]*4;
39503948
const T* S = S0 + sy*sstep + sx*cn;
3951-
for( k = 0; k < cn; k++ )
3949+
for(int k = 0; k < cn; k++ )
39523950
{
39533951
WT t0 = S[k]*w[0] + S[k+cn]*w[1] + S[sstep+k]*w[2] + S[sstep+k+cn]*w[3];
39543952
D[k] = castOp(t0);
@@ -4012,7 +4010,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
40124010
(sx >= ssize.width || sx+1 < 0 ||
40134011
sy >= ssize.height || sy+1 < 0) )
40144012
{
4015-
for( k = 0; k < cn; k++ )
4013+
for(int k = 0; k < cn; k++ )
40164014
D[k] = cval[k];
40174015
}
40184016
else
@@ -4046,7 +4044,7 @@ static void remapBilinear( const Mat& _src, Mat& _dst, const Mat& _xy,
40464044
v2 = sx0 >= 0 && sy1 >= 0 ? S0 + sy1*sstep + sx0*cn : &cval[0];
40474045
v3 = sx1 >= 0 && sy1 >= 0 ? S0 + sy1*sstep + sx1*cn : &cval[0];
40484046
}
4049-
for( k = 0; k < cn; k++ )
4047+
for(int k = 0; k < cn; k++ )
40504048
D[k] = castOp(WT(v0[k]*w[0] + v1[k]*w[1] + v2[k]*w[2] + v3[k]*w[3]));
40514049
}
40524050
}
@@ -4064,16 +4062,16 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
40644062
typedef typename CastOp::rtype T;
40654063
typedef typename CastOp::type1 WT;
40664064
Size ssize = _src.size(), dsize = _dst.size();
4067-
int cn = _src.channels();
4065+
const int cn = _src.channels();
40684066
const AT* wtab = (const AT*)_wtab;
40694067
const T* S0 = _src.ptr<T>();
40704068
size_t sstep = _src.step/sizeof(S0[0]);
4071-
Scalar_<T> cval(saturate_cast<T>(_borderValue[0]),
4072-
saturate_cast<T>(_borderValue[1]),
4073-
saturate_cast<T>(_borderValue[2]),
4074-
saturate_cast<T>(_borderValue[3]));
4075-
int dx, dy;
4069+
T cval[CV_CN_MAX];
40764070
CastOp castOp;
4071+
4072+
for(int k = 0; k < cn; k++ )
4073+
cval[k] = saturate_cast<T>(_borderValue[k & 3]);
4074+
40774075
int borderType1 = borderType != BORDER_TRANSPARENT ? borderType : BORDER_REFLECT_101;
40784076

40794077
unsigned width1 = std::max(ssize.width-3, 0), height1 = std::max(ssize.height-3, 0);
@@ -4084,21 +4082,20 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
40844082
dsize.height = 1;
40854083
}
40864084

4087-
for( dy = 0; dy < dsize.height; dy++ )
4085+
for(int dy = 0; dy < dsize.height; dy++ )
40884086
{
40894087
T* D = _dst.ptr<T>(dy);
40904088
const short* XY = _xy.ptr<short>(dy);
40914089
const ushort* FXY = _fxy.ptr<ushort>(dy);
40924090

4093-
for( dx = 0; dx < dsize.width; dx++, D += cn )
4091+
for(int dx = 0; dx < dsize.width; dx++, D += cn )
40944092
{
40954093
int sx = XY[dx*2]-1, sy = XY[dx*2+1]-1;
40964094
const AT* w = wtab + FXY[dx]*16;
4097-
int i, k;
40984095
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
40994096
{
41004097
const T* S = S0 + sy*sstep + sx*cn;
4101-
for( k = 0; k < cn; k++ )
4098+
for(int k = 0; k < cn; k++ )
41024099
{
41034100
WT sum = S[0]*w[0] + S[cn]*w[1] + S[cn*2]*w[2] + S[cn*3]*w[3];
41044101
S += sstep;
@@ -4123,21 +4120,21 @@ static void remapBicubic( const Mat& _src, Mat& _dst, const Mat& _xy,
41234120
(sx >= ssize.width || sx+4 <= 0 ||
41244121
sy >= ssize.height || sy+4 <= 0))
41254122
{
4126-
for( k = 0; k < cn; k++ )
4123+
for(int k = 0; k < cn; k++ )
41274124
D[k] = cval[k];
41284125
continue;
41294126
}
41304127

4131-
for( i = 0; i < 4; i++ )
4128+
for(int i = 0; i < 4; i++ )
41324129
{
41334130
x[i] = borderInterpolate(sx + i, ssize.width, borderType1)*cn;
41344131
y[i] = borderInterpolate(sy + i, ssize.height, borderType1);
41354132
}
41364133

4137-
for( k = 0; k < cn; k++, S0++, w -= 16 )
4134+
for(int k = 0; k < cn; k++, S0++, w -= 16 )
41384135
{
41394136
WT cv = cval[k], sum = cv*ONE;
4140-
for( i = 0; i < 4; i++, w += 4 )
4137+
for(int i = 0; i < 4; i++, w += 4 )
41414138
{
41424139
int yi = y[i];
41434140
const T* S = S0 + yi*sstep;
@@ -4169,16 +4166,16 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
41694166
typedef typename CastOp::rtype T;
41704167
typedef typename CastOp::type1 WT;
41714168
Size ssize = _src.size(), dsize = _dst.size();
4172-
int cn = _src.channels();
4169+
const int cn = _src.channels();
41734170
const AT* wtab = (const AT*)_wtab;
41744171
const T* S0 = _src.ptr<T>();
41754172
size_t sstep = _src.step/sizeof(S0[0]);
4176-
Scalar_<T> cval(saturate_cast<T>(_borderValue[0]),
4177-
saturate_cast<T>(_borderValue[1]),
4178-
saturate_cast<T>(_borderValue[2]),
4179-
saturate_cast<T>(_borderValue[3]));
4180-
int dx, dy;
4173+
T cval[CV_CN_MAX];
41814174
CastOp castOp;
4175+
4176+
for(int k = 0; k < cn; k++ )
4177+
cval[k] = saturate_cast<T>(_borderValue[k & 3]);
4178+
41824179
int borderType1 = borderType != BORDER_TRANSPARENT ? borderType : BORDER_REFLECT_101;
41834180

41844181
unsigned width1 = std::max(ssize.width-7, 0), height1 = std::max(ssize.height-7, 0);
@@ -4189,21 +4186,20 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
41894186
dsize.height = 1;
41904187
}
41914188

4192-
for( dy = 0; dy < dsize.height; dy++ )
4189+
for(int dy = 0; dy < dsize.height; dy++ )
41934190
{
41944191
T* D = _dst.ptr<T>(dy);
41954192
const short* XY = _xy.ptr<short>(dy);
41964193
const ushort* FXY = _fxy.ptr<ushort>(dy);
41974194

4198-
for( dx = 0; dx < dsize.width; dx++, D += cn )
4195+
for(int dx = 0; dx < dsize.width; dx++, D += cn )
41994196
{
42004197
int sx = XY[dx*2]-3, sy = XY[dx*2+1]-3;
42014198
const AT* w = wtab + FXY[dx]*64;
42024199
const T* S = S0 + sy*sstep + sx*cn;
4203-
int i, k;
42044200
if( (unsigned)sx < width1 && (unsigned)sy < height1 )
42054201
{
4206-
for( k = 0; k < cn; k++ )
4202+
for(int k = 0; k < cn; k++ )
42074203
{
42084204
WT sum = 0;
42094205
for( int r = 0; r < 8; r++, S += sstep, w += 8 )
@@ -4226,21 +4222,21 @@ static void remapLanczos4( const Mat& _src, Mat& _dst, const Mat& _xy,
42264222
(sx >= ssize.width || sx+8 <= 0 ||
42274223
sy >= ssize.height || sy+8 <= 0))
42284224
{
4229-
for( k = 0; k < cn; k++ )
4225+
for(int k = 0; k < cn; k++ )
42304226
D[k] = cval[k];
42314227
continue;
42324228
}
42334229

4234-
for( i = 0; i < 8; i++ )
4230+
for(int i = 0; i < 8; i++ )
42354231
{
42364232
x[i] = borderInterpolate(sx + i, ssize.width, borderType1)*cn;
42374233
y[i] = borderInterpolate(sy + i, ssize.height, borderType1);
42384234
}
42394235

4240-
for( k = 0; k < cn; k++, S0++, w -= 64 )
4236+
for(int k = 0; k < cn; k++, S0++, w -= 64 )
42414237
{
42424238
WT cv = cval[k], sum = cv*ONE;
4243-
for( i = 0; i < 8; i++, w += 8 )
4239+
for(int i = 0; i < 8; i++, w += 8 )
42444240
{
42454241
int yi = y[i];
42464242
const T* S1 = S0 + yi*sstep;

modules/imgproc/test/test_imgwarp.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1686,22 +1686,33 @@ TEST(Resize, Area_half)
16861686

16871687
TEST(Imgproc_Warp, multichannel)
16881688
{
1689+
static const int inter_types[] = {INTER_NEAREST, INTER_AREA, INTER_CUBIC,
1690+
INTER_LANCZOS4, INTER_LINEAR};
1691+
static const int inter_n = sizeof(inter_types) / sizeof(int);
1692+
1693+
static const int border_types[] = {BORDER_CONSTANT, BORDER_DEFAULT,
1694+
BORDER_REFLECT, BORDER_REPLICATE,
1695+
BORDER_WRAP, BORDER_WRAP};
1696+
static const int border_n = sizeof(border_types) / sizeof(int);
1697+
16891698
RNG& rng = theRNG();
1690-
for( int iter = 0; iter < 30; iter++ )
1699+
for( int iter = 0; iter < 100; iter++ )
16911700
{
1701+
int inter = inter_types[rng.uniform(0, inter_n)];
1702+
int border = border_types[rng.uniform(0, border_n)];
16921703
int width = rng.uniform(3, 333);
16931704
int height = rng.uniform(3, 333);
1694-
int cn = rng.uniform(1, 10);
1705+
int cn = rng.uniform(1, 15);
16951706
Mat src(height, width, CV_8UC(cn)), dst;
16961707
//randu(src, 0, 256);
16971708
src.setTo(0.);
16981709

1699-
Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1, 1);
1700-
warpAffine(src, dst, rot, src.size());
1710+
Mat rot = getRotationMatrix2D(Point2f(0.f, 0.f), 1.0, 1.0);
1711+
warpAffine(src, dst, rot, src.size(), inter, border);
17011712
ASSERT_EQ(0.0, norm(dst, NORM_INF));
17021713
Mat rot2 = Mat::eye(3, 3, rot.type());
17031714
rot.copyTo(rot2.rowRange(0, 2));
1704-
warpPerspective(src, dst, rot2, src.size());
1715+
warpPerspective(src, dst, rot2, src.size(), inter, border);
17051716
ASSERT_EQ(0.0, norm(dst, NORM_INF));
17061717
}
17071718
}

0 commit comments

Comments
 (0)