[arrayfire] 113/284: Added perspective transform to CPU backend
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Sun Feb 7 18:59:24 UTC 2016
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch debian/experimental
in repository arrayfire.
commit 2a438713f9c6a42737a98722553147f1ed0b55bd
Author: Peter Andreas Entschev <peter at arrayfire.com>
Date: Tue Dec 29 11:27:22 2015 -0500
Added perspective transform to CPU backend
---
src/backend/cpu/rotate.cpp | 4 +-
src/backend/cpu/transform.cpp | 72 +++++++++++++++++++++++----------
src/backend/cpu/transform.hpp | 2 +-
src/backend/cpu/transform_interp.hpp | 78 ++++++++++++++++++++++++++----------
4 files changed, 110 insertions(+), 46 deletions(-)
diff --git a/src/backend/cpu/rotate.cpp b/src/backend/cpu/rotate.cpp
index a4af64b..9756323 100644
--- a/src/backend/cpu/rotate.cpp
+++ b/src/backend/cpu/rotate.cpp
@@ -25,7 +25,7 @@ namespace cpu
void (*t_fn)(T *, const T *, const float *, const af::dim4 &,
const af::dim4 &, const af::dim4 &,
- const dim_t, const dim_t, const dim_t, const dim_t);
+ const dim_t, const dim_t, const dim_t, const dim_t, const bool);
const float c = cos(-theta), s = sin(-theta);
float tx, ty;
@@ -67,7 +67,7 @@ namespace cpu
// Do transform for image
for(int yy = 0; yy < (int)odims[1]; yy++) {
for(int xx = 0; xx < (int)odims[0]; xx++) {
- t_fn(out, in, tmat, idims, ostrides, istrides, nimages, 0, xx, yy);
+ t_fn(out, in, tmat, idims, ostrides, istrides, nimages, 0, xx, yy, false);
}
}
}
diff --git a/src/backend/cpu/transform.cpp b/src/backend/cpu/transform.cpp
index 68e8d96..bf072c3 100644
--- a/src/backend/cpu/transform.cpp
+++ b/src/backend/cpu/transform.cpp
@@ -17,30 +17,52 @@
namespace cpu
{
template <typename T>
- void calc_affine_inverse(T *txo, const T *txi)
+ void calc_transform_inverse(T *txo, const T *txi, const bool perspective)
{
- T det = txi[0]*txi[4] - txi[1]*txi[3];
+ if (perspective) {
+ txo[0] = txi[4]*txi[8] - txi[5]*txi[7];
+ txo[1] = -(txi[1]*txi[8] - txi[2]*txi[7]);
+ txo[2] = txi[1]*txi[5] - txi[2]*txi[4];
- txo[0] = txi[4] / det;
- txo[1] = txi[3] / det;
- txo[3] = txi[1] / det;
- txo[4] = txi[0] / det;
+ txo[3] = -(txi[3]*txi[8] - txi[5]*txi[6]);
+ txo[4] = txi[0]*txi[8] - txi[2]*txi[6];
+ txo[5] = -(txi[0]*txi[5] - txi[2]*txi[3]);
- txo[2] = txi[2] * -txo[0] + txi[5] * -txo[1];
- txo[5] = txi[2] * -txo[3] + txi[5] * -txo[4];
+ txo[6] = txi[3]*txi[7] - txi[4]*txi[6];
+ txo[7] = -(txi[0]*txi[7] - txi[1]*txi[6]);
+ txo[8] = txi[0]*txi[4] - txi[1]*txi[3];
+
+ T det = txi[0]*txo[0] + txi[1]*txo[3] + txi[2]*txo[6];
+
+ txo[0] /= det; txo[1] /= det; txo[2] /= det;
+ txo[3] /= det; txo[4] /= det; txo[5] /= det;
+ txo[6] /= det; txo[7] /= det; txo[8] /= det;
+ }
+ else {
+ T det = txi[0]*txi[4] - txi[1]*txi[3];
+
+ txo[0] = txi[4] / det;
+ txo[1] = txi[3] / det;
+ txo[3] = txi[1] / det;
+ txo[4] = txi[0] / det;
+
+ txo[2] = txi[2] * -txo[0] + txi[5] * -txo[1];
+ txo[5] = txi[2] * -txo[3] + txi[5] * -txo[4];
+ }
}
template <typename T>
- void calc_affine_inverse(T *tmat, const T *tmat_ptr, const bool inverse)
+ void calc_transform_inverse(T *tmat, const T *tmat_ptr, const bool inverse,
+ const bool perspective, const unsigned transf_len)
{
// The way kernel is structured, it expects an inverse
// transform matrix by default.
// If it is an forward transform, then we need its inverse
if(inverse) {
- for(int i = 0; i < 6; i++)
+ for(int i = 0; i < (int)transf_len; i++)
tmat[i] = tmat_ptr[i];
} else {
- calc_affine_inverse(tmat, tmat_ptr);
+ calc_transform_inverse(tmat, tmat_ptr, perspective);
}
}
@@ -48,7 +70,8 @@ namespace cpu
void transform_(T *out, const T *in, const float *tf,
const af::dim4 &odims, const af::dim4 &idims,
const af::dim4 &ostrides, const af::dim4 &istrides,
- const af::dim4 &tstrides, const bool inverse)
+ const af::dim4 &tstrides, const bool inverse,
+ const bool perspective)
{
dim_t nimages = idims[2];
// Multiplied in src/backend/transform.cpp
@@ -56,7 +79,7 @@ namespace cpu
void (*t_fn)(T *, const T *, const float *, const af::dim4 &,
const af::dim4 &, const af::dim4 &,
- const dim_t, const dim_t, const dim_t, const dim_t);
+ const dim_t, const dim_t, const dim_t, const dim_t, const bool);
switch(method) {
case AF_INTERP_NEAREST:
@@ -73,13 +96,14 @@ namespace cpu
break;
}
+ const int transf_len = (perspective) ? 9 : 6;
// For each transform channel
for(int t_idx = 0; t_idx < (int)ntransforms; t_idx++) {
// Compute inverse if required
- const float *tmat_ptr = tf + t_idx * 6;
- float tmat[6];
- calc_affine_inverse(tmat, tmat_ptr, inverse);
+ const float *tmat_ptr = tf + t_idx * transf_len;
+ float* tmat = new float[transf_len];
+ calc_transform_inverse(tmat, tmat_ptr, inverse, perspective, transf_len);
// Offset for output pointer
dim_t o_offset = t_idx * nimages * ostrides[2];
@@ -87,15 +111,16 @@ namespace cpu
// Do transform for image
for(int yy = 0; yy < (int)odims[1]; yy++) {
for(int xx = 0; xx < (int)odims[0]; xx++) {
- t_fn(out, in, tmat, idims, ostrides, istrides, nimages, o_offset, xx, yy);
+ t_fn(out, in, tmat, idims, ostrides, istrides, nimages, o_offset, xx, yy, perspective);
}
}
+ delete[] tmat;
}
}
template<typename T>
Array<T> transform(const Array<T> &in, const Array<float> &transform, const af::dim4 &odims,
- const af_interp_type method, const bool inverse)
+ const af_interp_type method, const bool inverse, const bool perspective)
{
const af::dim4 idims = in.dims();
@@ -105,17 +130,20 @@ namespace cpu
case AF_INTERP_NEAREST:
transform_<T, AF_INTERP_NEAREST>
(out.get(), in.get(), transform.get(), odims, idims,
- out.strides(), in.strides(), transform.strides(), inverse);
+ out.strides(), in.strides(), transform.strides(), inverse,
+ perspective);
break;
case AF_INTERP_BILINEAR:
transform_<T, AF_INTERP_BILINEAR>
(out.get(), in.get(), transform.get(), odims, idims,
- out.strides(), in.strides(), transform.strides(), inverse);
+ out.strides(), in.strides(), transform.strides(), inverse,
+ perspective);
break;
case AF_INTERP_LOWER:
transform_<T, AF_INTERP_LOWER>
(out.get(), in.get(), transform.get(), odims, idims,
- out.strides(), in.strides(), transform.strides(), inverse);
+ out.strides(), in.strides(), transform.strides(), inverse,
+ perspective);
break;
default:
AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
@@ -129,7 +157,7 @@ namespace cpu
#define INSTANTIATE(T) \
template Array<T> transform(const Array<T> &in, const Array<float> &transform, \
const af::dim4 &odims, const af_interp_type method, \
- const bool inverse);
+ const bool inverse, const bool perspective);
INSTANTIATE(float)
diff --git a/src/backend/cpu/transform.hpp b/src/backend/cpu/transform.hpp
index f9e730b..ad4ebba 100644
--- a/src/backend/cpu/transform.hpp
+++ b/src/backend/cpu/transform.hpp
@@ -14,5 +14,5 @@ namespace cpu
{
template<typename T>
Array<T> transform(const Array<T> &in, const Array<float> &tf, const af::dim4 &odims,
- const af_interp_type method, const bool inverse);
+ const af_interp_type method, const bool inverse, const bool perspective);
}
diff --git a/src/backend/cpu/transform_interp.hpp b/src/backend/cpu/transform_interp.hpp
index 5ad4750..dacd2e9 100644
--- a/src/backend/cpu/transform_interp.hpp
+++ b/src/backend/cpu/transform_interp.hpp
@@ -27,15 +27,27 @@ namespace cpu
void transform_n(T *out, const T *in, const float *tmat, const af::dim4 &idims,
const af::dim4 &ostrides, const af::dim4 &istrides,
const dim_t nimages, const dim_t o_offset,
- const dim_t xx, const dim_t yy)
+ const dim_t xx, const dim_t yy, const bool perspective)
{
+ dim_t yi = 0, xi = 0;
// Compute output index
- const dim_t xi = round(xx * tmat[0]
- + yy * tmat[1]
- + tmat[2]);
- const dim_t yi = round(xx * tmat[3]
- + yy * tmat[4]
- + tmat[5]);
+ if (perspective) {
+ const float W = xx * tmat[6] + yy * tmat[7] + tmat[8];
+ xi = round((xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2]) / W);
+ yi = round((xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5]) / W);
+ }
+ else {
+ xi = round(xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2]);
+ yi = round(xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5]);
+ }
// Compute memory location of indices
dim_t loci = (yi * istrides[1] + xi);
@@ -62,16 +74,28 @@ namespace cpu
void transform_b(T *out, const T *in, const float *tmat, const af::dim4 &idims,
const af::dim4 &ostrides, const af::dim4 &istrides,
const dim_t nimages, const dim_t o_offset,
- const dim_t xx, const dim_t yy)
+ const dim_t xx, const dim_t yy, const bool perspective)
{
dim_t loco = (yy * ostrides[1] + xx);
// Compute input index
- const float xi = xx * tmat[0]
- + yy * tmat[1]
- + tmat[2];
- const float yi = xx * tmat[3]
- + yy * tmat[4]
- + tmat[5];
+ float xi = 0.0f, yi = 0.0f;
+ if (perspective) {
+ const float W = xx * tmat[6] + yy * tmat[7] + tmat[8];
+ xi = (xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2]) / W;
+ yi = (xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5]) / W;
+ }
+ else {
+ xi = xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2];
+ yi = xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5];
+ }
if (xi < -0.0001 || yi < -0.0001 || idims[0] < xi || idims[1] < yi) {
for(int i_idx = 0; i_idx < (int)nimages; i_idx++) {
@@ -126,15 +150,27 @@ namespace cpu
void transform_l(T *out, const T *in, const float *tmat, const af::dim4 &idims,
const af::dim4 &ostrides, const af::dim4 &istrides,
const dim_t nimages, const dim_t o_offset,
- const dim_t xx, const dim_t yy)
+ const dim_t xx, const dim_t yy, const bool perspective)
{
// Compute output index
- const dim_t xi = floor(xx * tmat[0]
- + yy * tmat[1]
- + tmat[2]);
- const dim_t yi = floor(xx * tmat[3]
- + yy * tmat[4]
- + tmat[5]);
+ dim_t xi = 0, yi = 0;
+ if (perspective) {
+ const float W = xx * tmat[6] + yy * tmat[7] + tmat[8];
+ xi = floor((xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2]) / W);
+ yi = floor((xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5]) / W);
+ }
+ else {
+ xi = floor(xx * tmat[0]
+ + yy * tmat[1]
+ + tmat[2]);
+ yi = floor(xx * tmat[3]
+ + yy * tmat[4]
+ + tmat[5]);
+ }
// Compute memory location of indices
dim_t loci = (yi * istrides[1] + xi);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/arrayfire.git
More information about the debian-science-commits
mailing list