Skip to content

Commit 332bfdc

Browse files
committed
Added linear interpolation for transform (adds for rotate, scale, skew etc)
* TODO add tests * TODO check if scale can provide same functionality as resize
1 parent d4fe7e0 commit 332bfdc

File tree

17 files changed

+413
-114
lines changed

17 files changed

+413
-114
lines changed

include/af/image.h

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ AFAPI void saveImage(const char* filename, const array& in);
2121

2222
AFAPI array resize(const array in, const dim_type odim0, const dim_type odim1, const af_interp_type method=AF_INTERP_NEAREST);
2323

24-
AFAPI array transform(const array& in, const array& transform, const dim_type odim0, const dim_type odim1, const bool inverse=true);
24+
AFAPI array transform(const array& in, const array& transform, const dim_type odim0, const dim_type odim1, const af_interp_type method=AF_INTERP_NEAREST, const bool inverse=true);
2525

26-
AFAPI array rotate(const array& in, const float theta, const bool crop=true, const bool recenter=true);
26+
AFAPI array rotate(const array& in, const float theta, const af_interp_type method=AF_INTERP_NEAREST, const bool crop=true, const bool recenter=true);
2727

28-
AFAPI array translate(const array& in, const float trans0, const float trans1, const dim_type odim0, const dim_type odim1);
28+
AFAPI array translate(const array& in, const float trans0, const float trans1, const dim_type odim0, const dim_type odim1, const af_interp_type method=AF_INTERP_NEAREST);
2929

30-
AFAPI array scale(const array& in, const float scale0, const float scale1, const dim_type odim0, const dim_type odim1);
30+
AFAPI array scale(const array& in, const float scale0, const float scale1, const dim_type odim0, const dim_type odim1, const af_interp_type method=AF_INTERP_NEAREST);
3131

32-
AFAPI array skew(const array& in, const float skew0, const float skew1, const dim_type odim0, const dim_type odim1, const bool inverse=true);
32+
AFAPI array skew(const array& in, const float skew0, const float skew1, const dim_type odim0, const dim_type odim1, const bool inverse=true, const af_interp_type method=AF_INTERP_NEAREST);
3333

3434
AFAPI array bilateral(const array &in, const float spatial_sigma, const float chromatic_sigma, bool is_color=false);
3535

@@ -68,19 +68,23 @@ extern "C" {
6868
// Transform an image using a 3x2 transformation matrix.
6969
// If the transform matrix is a forward transformation matrix, then inverse is false.
7070
// If the transform martix is an inverse transformation matrix, then inverse is true;
71-
AFAPI af_err af_transform(af_array *out, const af_array in, const af_array transform, const dim_type odim0, const dim_type odim1, const bool inverse);
71+
AFAPI af_err af_transform(af_array *out, const af_array in, const af_array transform,
72+
const dim_type odim0, const dim_type odim1,
73+
const af_interp_type method, const bool inverse);
7274

7375
// Rotate
74-
AFAPI af_err af_rotate(af_array *out, const af_array in, const float theta, const bool crop, const bool recenter);
76+
AFAPI af_err af_rotate(af_array *out, const af_array in, const float theta,
77+
const af_interp_type method, const bool crop, const bool recenter);
7578
// Translate
7679
AFAPI af_err af_translate(af_array *out, const af_array in, const float trans0, const float trans1,
77-
const dim_type odim0, const dim_type odim1);
80+
const dim_type odim0, const dim_type odim1, const af_interp_type method);
7881
// Scale
7982
AFAPI af_err af_scale(af_array *out, const af_array in, const float scale0, const float scale1,
80-
const dim_type odim0, const dim_type odim1);
83+
const dim_type odim0, const dim_type odim1, const af_interp_type method);
8184
// Skew
8285
AFAPI af_err af_skew(af_array *out, const af_array in, const float skew0, const float skew1,
83-
const dim_type odim0, const dim_type odim1, const bool inverse);
86+
const dim_type odim0, const dim_type odim1, const af_interp_type method,
87+
const bool inverse);
8488

8589
// histogram: return af_array will have elements of type u32
8690
AFAPI af_err af_histogram(af_array *out, const af_array in, const unsigned nbins, const double minval, const double maxval);

src/api/c/transform.cpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,15 @@ using af::dim4;
1919
using namespace detail;
2020

2121
template<typename T>
22-
static inline af_array transform(const af_array in, const af_array tf, const af::dim4 &odims, const bool inverse)
22+
static inline af_array transform(const af_array in, const af_array tf, const af::dim4 &odims,
23+
const af_interp_type method, const bool inverse)
2324
{
24-
return getHandle(*transform<T>(getArray<T>(in), getArray<float>(tf), odims, inverse));
25+
return getHandle(*transform<T>(getArray<T>(in), getArray<float>(tf), odims, method, inverse));
2526
}
2627

2728
af_err af_transform(af_array *out, const af_array in, const af_array tf,
28-
const dim_type odim0, const dim_type odim1, const bool inverse)
29+
const dim_type odim0, const dim_type odim1,
30+
const af_interp_type method, const bool inverse)
2931
{
3032
try {
3133
ArrayInfo t_info = getInfo(tf);
@@ -36,6 +38,7 @@ af_err af_transform(af_array *out, const af_array in, const af_array tf,
3638
af_dtype itype = i_info.getType();
3739

3840
ARG_ASSERT(2, t_info.getType() == f32);
41+
ARG_ASSERT(5, method == AF_INTERP_NEAREST || method == AF_INTERP_BILINEAR);
3942
DIM_ASSERT(2, (tdims[0] == 3 && tdims[1] == 2));
4043
DIM_ASSERT(1, idims.elements() > 0);
4144
DIM_ASSERT(1, (idims.ndims() == 2 || idims.ndims() == 3));
@@ -50,11 +53,11 @@ af_err af_transform(af_array *out, const af_array in, const af_array tf,
5053

5154
af_array output = 0;
5255
switch(itype) {
53-
case f32: output = transform<float >(in, tf, odims, inverse); break;
54-
case f64: output = transform<double >(in, tf, odims, inverse); break;
55-
case s32: output = transform<int >(in, tf, odims, inverse); break;
56-
case u32: output = transform<uint >(in, tf, odims, inverse); break;
57-
case u8: output = transform<uchar >(in, tf, odims, inverse); break;
56+
case f32: output = transform<float >(in, tf, odims, method, inverse); break;
57+
case f64: output = transform<double >(in, tf, odims, method, inverse); break;
58+
case s32: output = transform<int >(in, tf, odims, method, inverse); break;
59+
case u32: output = transform<uint >(in, tf, odims, method, inverse); break;
60+
case u8: output = transform<uchar >(in, tf, odims, method, inverse); break;
5861
default: TYPE_ERROR(1, itype);
5962
}
6063
std::swap(*out,output);
@@ -64,7 +67,7 @@ af_err af_transform(af_array *out, const af_array in, const af_array tf,
6467
return AF_SUCCESS;
6568
}
6669

67-
af_err af_rotate(af_array *out, const af_array in, const float theta,
70+
af_err af_rotate(af_array *out, const af_array in, const float theta, const af_interp_type method,
6871
const bool crop, const bool recenter)
6972
{
7073
af_err ret = AF_SUCCESS;
@@ -114,7 +117,7 @@ af_err af_rotate(af_array *out, const af_array in, const float theta,
114117
ret = af_create_array(&t, trans_mat, tdims.ndims(), tdims.get(), f32);
115118

116119
if (ret == AF_SUCCESS) {
117-
return af_transform(out, in, t, odims0, odims1, true);
120+
return af_transform(out, in, t, odims0, odims1, method, true);
118121
}
119122
}
120123
CATCHALL;
@@ -123,7 +126,7 @@ af_err af_rotate(af_array *out, const af_array in, const float theta,
123126
}
124127

125128
af_err af_translate(af_array *out, const af_array in, const float trans0, const float trans1,
126-
const dim_type odim0, const dim_type odim1)
129+
const dim_type odim0, const dim_type odim1, const af_interp_type method)
127130
{
128131
af_err ret = AF_SUCCESS;
129132

@@ -139,7 +142,7 @@ af_err af_translate(af_array *out, const af_array in, const float trans0, const
139142
ret = af_create_array(&t, trans_mat, tdims.ndims(), tdims.get(), f32);
140143

141144
if (ret == AF_SUCCESS) {
142-
ret = af_transform(out, in, t, odim0, odim1, true);
145+
ret = af_transform(out, in, t, odim0, odim1, method, true);
143146
}
144147
}
145148
CATCHALL;
@@ -148,20 +151,26 @@ af_err af_translate(af_array *out, const af_array in, const float trans0, const
148151
}
149152

150153
af_err af_scale(af_array *out, const af_array in, const float scale0, const float scale1,
151-
const dim_type odim0, const dim_type odim1)
154+
const dim_type odim0, const dim_type odim1, const af_interp_type method)
152155
{
153156
af_err ret = AF_SUCCESS;
154157
try {
155158
ArrayInfo i_info = getInfo(in);
156159
af::dim4 idims = i_info.dims();
157160

158161
dim_type _odim0 = odim0, _odim1 = odim1;
159-
float sx = 1.f / scale0, sy = 1.f / scale1;
162+
float sx, sy;
160163
if(_odim0 == 0 && _odim1 == 0) {
164+
sx = 1.f / scale0, sy = 1.f / scale1;
161165
_odim0 = idims[0] / sx;
162166
_odim1 = idims[1] / sy;
163167
} else if ( _odim0 == 0 || _odim1 == 0) {
164-
return AF_ERR_ARG;
168+
return AF_ERR_SIZE;
169+
} else if (scale0 == 0 && scale1 == 0) {
170+
sx = idims[0] / (float)_odim0;
171+
sy = idims[1] / (float)_odim1;
172+
} else {
173+
sx = 1.f / scale0, sy = 1.f / scale1;
165174
}
166175

167176
static float trans_mat[6] = {1, 0, 0,
@@ -174,7 +183,7 @@ af_err af_scale(af_array *out, const af_array in, const float scale0, const floa
174183
ret = af_create_array(&t, trans_mat, tdims.ndims(), tdims.get(), f32);
175184

176185
if (ret == AF_SUCCESS) {
177-
return af_transform(out, in, t, odim0, odim1, true);
186+
return af_transform(out, in, t, _odim0, _odim1, method, true);
178187
}
179188
}
180189
CATCHALL;
@@ -183,7 +192,8 @@ af_err af_scale(af_array *out, const af_array in, const float scale0, const floa
183192
}
184193

185194
af_err af_skew(af_array *out, const af_array in, const float skew0, const float skew1,
186-
const dim_type odim0, const dim_type odim1, const bool inverse)
195+
const dim_type odim0, const dim_type odim1, const af_interp_type method,
196+
const bool inverse)
187197
{
188198
af_err ret = AF_SUCCESS;
189199
try {
@@ -214,7 +224,7 @@ af_err af_skew(af_array *out, const af_array in, const float skew0, const float
214224
ret = af_create_array(&t, trans_mat, tdims.ndims(), tdims.get(), f32);
215225

216226
if (ret == AF_SUCCESS) {
217-
return af_transform(out, in, t, odim0, odim1, true);
227+
return af_transform(out, in, t, odim0, odim1, method, true);
218228
}
219229
}
220230
CATCHALL;

src/api/cpp/rotate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
namespace af
1414
{
1515

16-
array rotate(const array& in, const float theta, const bool crop, const bool recenter)
16+
array rotate(const array& in, const float theta, const af_interp_type method, const bool crop, const bool recenter)
1717
{
1818
af_array out = 0;
19-
AF_THROW(af_rotate(&out, in.get(), theta, crop, recenter));
19+
AF_THROW(af_rotate(&out, in.get(), theta, method, crop, recenter));
2020
return array(out);
2121
}
2222

src/api/cpp/scale.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
namespace af
1414
{
1515

16-
array scale(const array& in, const float scale0, const float scale1, const dim_type odim0, const dim_type odim1)
16+
array scale(const array& in, const float scale0, const float scale1, const dim_type odim0, const dim_type odim1, const af_interp_type method)
1717
{
1818
af_array out = 0;
19-
AF_THROW(af_scale(&out, in.get(), scale0, scale1, odim0, odim1));
19+
AF_THROW(af_scale(&out, in.get(), scale0, scale1, odim0, odim1, method));
2020
return array(out);
2121
}
2222

src/api/cpp/skew.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
namespace af
1414
{
1515

16-
array skew(const array& in, const float skew0, const float skew1, const dim_type odim0, const dim_type odim1, const bool inverse)
16+
array skew(const array& in, const float skew0, const float skew1, const dim_type odim0, const dim_type odim1, const bool inverse, const af_interp_type method)
1717
{
1818
af_array out = 0;
19-
AF_THROW(af_skew(&out, in.get(), skew0, skew1, odim0, odim1, inverse));
19+
AF_THROW(af_skew(&out, in.get(), skew0, skew1, odim0, odim1, method, inverse));
2020
return array(out);
2121
}
2222

src/api/cpp/transform.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
namespace af
1414
{
1515

16-
array transform(const array& in, const array& transform, const dim_type odim0, const dim_type odim1, const bool inverse)
16+
array transform(const array& in, const array& transform, const dim_type odim0, const dim_type odim1, const af_interp_type method, const bool inverse)
1717
{
1818
af_array out = 0;
19-
AF_THROW(af_transform(&out, in.get(), transform.get(), odim0, odim1, inverse));
19+
AF_THROW(af_transform(&out, in.get(), transform.get(), odim0, odim1, method, inverse));
2020
return array(out);
2121
}
2222

src/api/cpp/translate.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@
1313
namespace af
1414
{
1515

16-
array translate(const array& in, const float trans0, const float trans1, const dim_type odim0, const dim_type odim1)
16+
array translate(const array& in, const float trans0, const float trans1, const dim_type odim0, const dim_type odim1, const af_interp_type method)
1717
{
1818
af_array out = 0;
19-
AF_THROW(af_translate(&out, in.get(), trans0, trans1, odim0, odim1));
19+
AF_THROW(af_translate(&out, in.get(), trans0, trans1, odim0, odim1, method));
2020
return array(out);
2121
}
2222

0 commit comments

Comments
 (0)