[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