aboutsummaryrefslogtreecommitdiff
path: root/src/core/NEON/kernels/NEWarpKernel.cpp
diff options
context:
space:
mode:
authorIsabella Gottardi <isabella.gottardi@arm.com>2017-07-04 11:21:28 +0100
committerAnthony Barbier <anthony.barbier@arm.com>2018-09-17 14:17:31 +0100
commit6203153b25fda2c4b8d94fe71337d1145a36c132 (patch)
treeaee1e7db73d09eabf01ed8fb7680f98f97e07c93 /src/core/NEON/kernels/NEWarpKernel.cpp
parentd6253602ec7ebcbe6adb0acc51a97a5d8c167495 (diff)
downloadComputeLibrary-6203153b25fda2c4b8d94fe71337d1145a36c132.tar.gz
COMPMID-424 Implemented reference implementation and validation tests (NEON and CL) for Warp Perspective
Changed the behaviour in NEWarpKernel for border mode replicate and constant to stick with the VX specs. When the new coords are out of the valid region, the output will be computed using the values from the border. In the validation tests the validate will be called with tolerance_value 1 and tolerance_number 0.2%, due to some float arithmetic related mismatches. Change-Id: Id4f9d0ef87178f8f8fd38ee17fee0e6f4beb85cd Reviewed-on: http://mpd-gerrit.cambridge.arm.com/80283 Tested-by: Kaizen <jeremy.johnson+kaizengerrit@arm.com> Reviewed-by: Moritz Pflanzer <moritz.pflanzer@arm.com> Reviewed-by: Steven Niu <steven.niu@arm.com>
Diffstat (limited to 'src/core/NEON/kernels/NEWarpKernel.cpp')
-rw-r--r--src/core/NEON/kernels/NEWarpKernel.cpp63
1 files changed, 56 insertions, 7 deletions
diff --git a/src/core/NEON/kernels/NEWarpKernel.cpp b/src/core/NEON/kernels/NEWarpKernel.cpp
index 8f8c852672..5ca1395b47 100644
--- a/src/core/NEON/kernels/NEWarpKernel.cpp
+++ b/src/core/NEON/kernels/NEWarpKernel.cpp
@@ -521,7 +521,6 @@ void NEWarpPerspectiveKernel<interpolation>::warp_constant(const Window &window)
const float yn = y0 / z0;
// Only use input values if xn and yn are within the valid region.
- // Otherwise write the constant border value.
if((min_y <= yn) && (yn < max_y) && (min_x <= xn) && (xn < max_x))
{
switch(interpolation)
@@ -538,7 +537,34 @@ void NEWarpPerspectiveKernel<interpolation>::warp_constant(const Window &window)
}
else
{
- *out.ptr() = _constant_border_value;
+ switch(interpolation)
+ {
+ case InterpolationPolicy::NEAREST_NEIGHBOR:
+ *out.ptr() = _constant_border_value;
+ break;
+ case InterpolationPolicy::BILINEAR:
+ {
+ const auto xi = clamp<int>(std::floor(xn), min_x - 1, max_x);
+ const auto yi = clamp<int>(std::floor(yn), min_y - 1, max_y);
+ const auto xi_1 = clamp<int>(std::floor(xn + 1), min_x - 1, max_x);
+ const auto yi_1 = clamp<int>(std::floor(yn + 1), min_y - 1, max_y);
+
+ const float dx = xn - std::floor(xn);
+ const float dy = yn - std::floor(yn);
+ const float dx1 = 1.0f - dx;
+ const float dy1 = 1.0f - dy;
+
+ const float a00 = *(in.ptr() + xi + yi * stride);
+ const float a01 = *(in.ptr() + xi_1 + yi * stride);
+ const float a10 = *(in.ptr() + xi + yi_1 * stride);
+ const float a11 = *(in.ptr() + xi_1 + yi_1 * stride);
+
+ *out.ptr() = a00 * (dx1 * dy1) + a01 * (dx * dy1) + a10 * (dx1 * dy) + a11 * (dx * dy);
+ }
+ break;
+ default:
+ ARM_COMPUTE_ERROR("Interpolation not supported");
+ }
}
x0 += M00;
@@ -619,7 +645,6 @@ void NEWarpPerspectiveKernel<interpolation>::warp_replicate(const Window &window
const float yn = y0 / z0;
// Only load from (x0, y0) if the point is within the valid region.
- // Otherwise load from the edge of the valid region.
if((min_y <= yn) && (yn < max_y) && (min_x <= xn) && (xn < max_x))
{
switch(interpolation)
@@ -637,10 +662,34 @@ void NEWarpPerspectiveKernel<interpolation>::warp_replicate(const Window &window
else
{
// Clamp coordinates
- const auto xi = clamp<int>(x0, min_x, max_x - 1);
- const auto yi = clamp<int>(y0, min_y, max_y - 1);
-
- *out.ptr() = *(in.ptr() + xi + yi * stride);
+ const auto xi = clamp<int>(std::floor(xn), min_x, max_x - 1);
+ const auto yi = clamp<int>(std::floor(yn), min_y, max_y - 1);
+ switch(interpolation)
+ {
+ case InterpolationPolicy::NEAREST_NEIGHBOR:
+ *out.ptr() = *(in.ptr() + xi + yi * stride);
+ break;
+ case InterpolationPolicy::BILINEAR:
+ {
+ const auto xi_1 = clamp<int>(std::floor(xn + 1), min_x, max_x - 1);
+ const auto yi_1 = clamp<int>(std::floor(yn + 1), min_y, max_y - 1);
+
+ const float dx = xn - std::floor(xn);
+ const float dy = yn - std::floor(yn);
+ const float dx1 = 1.0f - dx;
+ const float dy1 = 1.0f - dy;
+
+ const float a00 = *(in.ptr() + xi + yi * stride);
+ const float a01 = *(in.ptr() + xi_1 + yi * stride);
+ const float a10 = *(in.ptr() + xi + yi_1 * stride);
+ const float a11 = *(in.ptr() + xi_1 + yi_1 * stride);
+
+ *out.ptr() = a00 * (dx1 * dy1) + a01 * (dx * dy1) + a10 * (dx1 * dy) + a11 * (dx * dy);
+ }
+ break;
+ default:
+ ARM_COMPUTE_ERROR("Interpolation not supported");
+ }
}
x0 += M00;