21 inline float Lerp(
float a,
float b,
float w)
23 return w * b + (1.f - w) * a;
26 inline double EuclideanDistance(
float Xa,
float Ya,
const unsigned int Xb,
const unsigned int Yb)
28 return std::sqrt(pow(Xa - armnn::numeric_cast<float>(Xb), 2) + pow(Ya - armnn::numeric_cast<float>(Yb), 2));
31 inline float CalculateResizeScale(
const unsigned int& InputSize,
32 const unsigned int& OutputSize,
33 const bool& AlignCorners)
35 return (AlignCorners && OutputSize > 1)
36 ? armnn::numeric_cast<float>(InputSize - 1) / armnn::numeric_cast<float>(OutputSize - 1)
40 inline float PixelScaler(
const unsigned int& Pixel,
42 const bool& HalfPixelCenters,
48 return (
static_cast<float>(Pixel) + 0.5f) * Scale - 0.5f;
53 return (
static_cast<float>(Pixel) + 0.5f) * Scale;
57 return static_cast<float>(Pixel) * Scale;
72 bool halfPixelCenters)
76 "Resize: alignCorners and halfPixelCenters cannot both be true");
82 const unsigned int batchSize = inputInfo.
GetShape()[0];
92 const float scaleY = CalculateResizeScale(inputHeight, outputHeight, alignCorners);
93 const float scaleX = CalculateResizeScale(inputWidth, outputWidth, alignCorners);
98 for (
unsigned int n = 0; n < batchSize; ++n)
100 for (
unsigned int c = 0; c < channelCount; ++c)
102 for (
unsigned int y = 0; y < outputHeight; ++y)
105 float iy = PixelScaler(y, scaleY, halfPixelCenters, resizeMethod);
108 const float fiy = (resizeMethod == ResizeMethod::NearestNeighbor && alignCorners) ?
armnn::roundf(iy)
111 const unsigned int y0 =
static_cast<unsigned int>(std::max(fiy, 0.0f));
114 const float yw = iy - fiy;
116 for (
unsigned int x = 0; x < outputWidth; ++x)
119 float ix = PixelScaler(x, scaleX, halfPixelCenters, resizeMethod);
122 const float fix = resizeMethod == ResizeMethod::NearestNeighbor && alignCorners ?
armnn::roundf(ix)
125 const unsigned int x0 =
static_cast<unsigned int>(std::max(fix, 0.0f));
128 const float xw = ix - fix;
133 if (halfPixelCenters)
135 x1 = std::min(
static_cast<unsigned int>(std::ceil(ix)), inputWidth - 1u);
136 y1 = std::min(
static_cast<unsigned int>(std::ceil(iy)), inputHeight - 1u);
141 x1 = std::min(x0 + 1, inputWidth - 1u);
142 y1 = std::min(y0 + 1, inputHeight - 1u);
145 float interpolatedValue;
146 switch (resizeMethod)
148 case ResizeMethod::Bilinear:
150 in[dataLayout.
GetIndex(inputShape, n, c, y0, x0)];
151 float input1 = in.
Get();
152 in[dataLayout.
GetIndex(inputShape, n, c, y0, x1)];
153 float input2 = in.
Get();
154 in[dataLayout.
GetIndex(inputShape, n, c, y1, x0)];
155 float input3 = in.
Get();
156 in[dataLayout.
GetIndex(inputShape, n, c, y1, x1)];
157 float input4 = in.
Get();
159 const float ly0 = Lerp(input1, input2, xw);
160 const float ly1 = Lerp(input3, input4, xw);
161 interpolatedValue = Lerp(ly0, ly1, yw);
164 case ResizeMethod::NearestNeighbor:
167 auto distance00 = EuclideanDistance(fix, fiy, x0, y0);
168 auto distance01 = EuclideanDistance(fix, fiy, x0, y1);
169 auto distance10 = EuclideanDistance(fix, fiy, x1, y0);
170 auto distance11 = EuclideanDistance(fix, fiy, x1, y1);
172 auto minimum = std::min( { distance00, distance01, distance10, distance11 } );
174 unsigned int xNearest = 0;
175 unsigned int yNearest = 0;
182 else if (
minimum == distance01)
187 else if (
minimum == distance10)
192 else if (
minimum == distance11)
202 in[dataLayout.
GetIndex(inputShape, n, c, yNearest, xNearest)];
203 interpolatedValue = in.
Get();
208 std::to_string(
static_cast<int>(resizeMethod)));
210 out[dataLayout.
GetIndex(outputShape, n, c, y, x)];
211 out.
Set(interpolatedValue);
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
virtual IType Get() const =0
virtual void Set(IType right)=0
const TensorShape & GetShape() const
Provides access to the appropriate indexes for Channels, Height and Width based on DataLayout.
unsigned int GetIndex(const armnn::TensorShape &shape, unsigned int batchIndex, unsigned int channelIndex, unsigned int heightIndex, unsigned int widthIndex) const
unsigned int GetWidthIndex() const
unsigned int GetHeightIndex() const
unsigned int GetChannelsIndex() const
Copyright (c) 2021 ARM Limited and Contributors.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
float roundf(float value)
void Resize(Decoder< float > &in, const TensorInfo &inputInfo, Encoder< float > &out, const TensorInfo &outputInfo, DataLayoutIndexed dataLayout, ResizeMethod resizeMethod, bool alignCorners, bool halfPixelCenters)