[arrayfire] 115/284: Added perspective transform to OpenCL 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 15b9ad6ae46e76bb086a6bf136ffce0bf147a8b0
Author: Peter Andreas Entschev <peter at arrayfire.com>
Date:   Tue Dec 29 11:30:59 2015 -0500

    Added perspective transform to OpenCL backend
---
 src/backend/opencl/kernel/transform.cl        |  32 ++++++--
 src/backend/opencl/kernel/transform.hpp       |  14 ++--
 src/backend/opencl/kernel/transform_interp.cl |  69 +++++++++++-----
 src/backend/opencl/transform.cpp              | 110 ++++++++++++++++++--------
 src/backend/opencl/transform.hpp              |   2 +-
 5 files changed, 161 insertions(+), 66 deletions(-)

diff --git a/src/backend/opencl/kernel/transform.cl b/src/backend/opencl/kernel/transform.cl
index 824f50c..d746525 100644
--- a/src/backend/opencl/kernel/transform.cl
+++ b/src/backend/opencl/kernel/transform.cl
@@ -11,9 +11,28 @@
 #define BILINEAR transform_b
 #define LOWER transform_l
 
-void calc_affine_inverse(float* txo, __global const float* txi)
+void calc_transf_inverse(float* txo, __global const float* txi)
 {
-    float 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[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[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;
@@ -22,6 +41,7 @@ void calc_affine_inverse(float* txo, __global const float* txi)
 
     txo[2] = txi[2] * -txo[0] + txi[5] * -txo[1];
     txo[5] = txi[2] * -txo[3] + txi[5] * -txo[4];
+#endif
 }
 
 __kernel
@@ -59,17 +79,17 @@ void transform_kernel(__global T *d_out, const KParam out,
 
     // Transform is in global memory.
     // Needs offset to correct transform being processed.
-    __global const float *tmat_ptr = c_tmat + t_idx * 6;
-    float tmat[6];
+    __global const float *tmat_ptr = c_tmat + t_idx * TRANSF_LEN;
+    float tmat[TRANSF_LEN];
 
     // We expect a inverse transform matrix by default
     // If it is an forward transform, then we need its inverse
     if(INVERSE == 1) {
         #pragma unroll
-        for(int i = 0; i < 6; i++)
+        for(int i = 0; i < TRANSF_LEN; i++)
             tmat[i] = tmat_ptr[i];
     } else {
-        calc_affine_inverse(tmat, tmat_ptr);
+        calc_transf_inverse(tmat, tmat_ptr);
     }
 
     if (xido >= out.dims[0] && yido >= out.dims[1]) return;
diff --git a/src/backend/opencl/kernel/transform.hpp b/src/backend/opencl/kernel/transform.hpp
index 677acc3..f78c7b0 100644
--- a/src/backend/opencl/kernel/transform.hpp
+++ b/src/backend/opencl/kernel/transform.hpp
@@ -50,7 +50,7 @@ namespace opencl
                                             >::type;
 
 
-        template<typename T, bool isInverse, af_interp_type method>
+        template<typename T, bool isInverse, bool isPerspective, af_interp_type method>
         void transform(Param out, const Param in, const Param tf)
         {
             try {
@@ -64,11 +64,13 @@ namespace opencl
                 std::call_once( compileFlags[device], [device] () {
                     ToNum<T> toNum;
                     std::ostringstream options;
-                    options << " -D T="        << dtype_traits<T>::getName()
-                            << " -D INVERSE="  << (isInverse ? 1 : 0)
-                            << " -D ZERO="     << toNum(scalar<T>(0));
-                    options << " -D VT="       << dtype_traits<vtype_t<T>>::getName();
-                    options << " -D WT="       << dtype_traits<wtype_t<BT>>::getName();
+                    options << " -D T="           << dtype_traits<T>::getName()
+                            << " -D INVERSE="     << (isInverse ? 1 : 0)
+                            << " -D PERSPECTIVE=" << (isPerspective ? 1 : 0)
+                            << " -D TRANSF_LEN="  << (isPerspective ? 9 : 6)
+                            << " -D ZERO="        << toNum(scalar<T>(0));
+                    options << " -D VT="          << dtype_traits<vtype_t<T>>::getName();
+                    options << " -D WT="          << dtype_traits<wtype_t<BT>>::getName();
 
                     if((af_dtype) dtype_traits<T>::af_type == c32 ||
                        (af_dtype) dtype_traits<T>::af_type == c64) {
diff --git a/src/backend/opencl/kernel/transform_interp.cl b/src/backend/opencl/kernel/transform_interp.cl
index 1d82951..a083df0 100644
--- a/src/backend/opencl/kernel/transform_interp.cl
+++ b/src/backend/opencl/kernel/transform_interp.cl
@@ -25,12 +25,23 @@ void transform_n(__global T *d_out, const KParam out, __global const T *d_in, co
                  const float *tmat, const int xido, const int yido, const int nimages)
 {
     // Compute input index
-    const int xidi = round(xido * tmat[0]
-                         + yido * tmat[1]
-                                + tmat[2]);
-    const int yidi = round(xido * tmat[3]
-                         + yido * tmat[4]
-                                + tmat[5]);
+    int xidi = 0, yidi = 0;
+#if PERSPECTIVE
+    const float W = xido * tmat[6] + yido * tmat[7] + tmat[8];
+    xidi = round((xido * tmat[0]
+                + yido * tmat[1]
+                       + tmat[2]) / W);
+    yidi = round((xido * tmat[3]
+                + yido * tmat[4]
+                       + tmat[5]) / W);
+#else
+    xidi = round(xido * tmat[0]
+               + yido * tmat[1]
+                      + tmat[2]);
+    yidi = round(xido * tmat[3]
+               + yido * tmat[4]
+                      + tmat[5]);
+#endif
 
     // Compute memory location of indices
     const int loci = yidi * in.strides[1]  + xidi;
@@ -54,12 +65,23 @@ void transform_b(__global T *d_out, const KParam out, __global const T *d_in, co
     const int loco = (yido * out.strides[1] + xido);
 
     // Compute input index
-    const float xid = xido * tmat[0]
-                    + yido * tmat[1]
-                           + tmat[2];
-    const float yid = xido * tmat[3]
-                    + yido * tmat[4]
-                           + tmat[5];
+    float xid = 0.0f, yid = 0.0f;
+#if PERSPECTIVE
+    const float W = xido * tmat[6] + yido * tmat[7] + tmat[8];
+    xid = (xido * tmat[0]
+         + yido * tmat[1]
+                + tmat[2]) / W;
+    yid = (xido * tmat[3]
+         + yido * tmat[4]
+                + tmat[5]) / W;
+#else
+    xid = xido * tmat[0]
+        + yido * tmat[1]
+               + tmat[2];
+    yid = xido * tmat[3]
+        + yido * tmat[4]
+               + tmat[5];
+#endif
 
     T zero = ZERO;
     if (xid < -0.001 || yid < -0.001 || in.dims[0] < xid || in.dims[1] < yid) {
@@ -104,12 +126,23 @@ void transform_l(__global T *d_out, const KParam out, __global const T *d_in, co
                  const float *tmat, const int xido, const int yido, const int nimages)
 {
     // Compute input index
-    const int xidi = floor(xido * tmat[0]
-                         + yido * tmat[1]
-                                + tmat[2]);
-    const int yidi = floor(xido * tmat[3]
-                         + yido * tmat[4]
-                                + tmat[5]);
+    int xidi = 0, yidi = 0;
+#if PERSPECTIVE
+    const float W = xido * tmat[6] + yido * tmat[7] + tmat[8];
+    xidi = floor((xido * tmat[0]
+                + yido * tmat[1]
+                       + tmat[2]) / W);
+    yidi = floor((xido * tmat[3]
+                + yido * tmat[4]
+                       + tmat[5]) / W);
+#else
+    xidi = floor(xido * tmat[0]
+               + yido * tmat[1]
+                      + tmat[2]);
+    yidi = floor(xido * tmat[3]
+               + yido * tmat[4]
+                      + tmat[5]);
+#endif
 
     // Compute memory location of indices
     const int loci = yidi * in.strides[1]  + xidi;
diff --git a/src/backend/opencl/transform.cpp b/src/backend/opencl/transform.cpp
index c8e2b69..379fd2a 100644
--- a/src/backend/opencl/transform.cpp
+++ b/src/backend/opencl/transform.cpp
@@ -18,46 +18,86 @@ namespace opencl
 {
     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::dim4 &odims, const af_interp_type method,
+                       const bool inverse, const bool perspective)
     {
         Array<T> out = createEmptyArray<T>(odims);
 
         if(inverse) {
-            switch(method) {
-                case AF_INTERP_NEAREST:
-                    kernel::transform<T, true, AF_INTERP_NEAREST>
-                                     (out, in, transform);
-                    break;
-                case AF_INTERP_BILINEAR:
-                    kernel::transform<T, true, AF_INTERP_BILINEAR>
-                                     (out, in, transform);
-                    break;
-                case AF_INTERP_LOWER:
-                    kernel::transform<T, true, AF_INTERP_LOWER>
-                                     (out, in, transform);
-                    break;
-                default:
-                    AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
-                    break;
+            if (perspective) {
+                switch(method) {
+                    case AF_INTERP_NEAREST:
+                        kernel::transform<T, true, true, AF_INTERP_NEAREST>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_BILINEAR:
+                        kernel::transform<T, true, true, AF_INTERP_BILINEAR>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_LOWER:
+                        kernel::transform<T, true, true, AF_INTERP_LOWER>
+                                         (out, in, transform);
+                        break;
+                    default:
+                        AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
+                        break;
+                }
+            } else {
+                switch(method) {
+                    case AF_INTERP_NEAREST:
+                        kernel::transform<T, true, false, AF_INTERP_NEAREST>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_BILINEAR:
+                        kernel::transform<T, true, false, AF_INTERP_BILINEAR>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_LOWER:
+                        kernel::transform<T, true, false, AF_INTERP_LOWER>
+                                         (out, in, transform);
+                        break;
+                    default:
+                        AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
+                        break;
+                }
             }
         } else {
-            switch(method) {
-                case AF_INTERP_NEAREST:
-                    kernel::transform<T, false, AF_INTERP_NEAREST>
-                                     (out, in, transform);
-                    break;
-                case AF_INTERP_BILINEAR:
-                    kernel::transform<T, false, AF_INTERP_BILINEAR>
-                                     (out, in, transform);
-                    break;
-                case AF_INTERP_LOWER:
-                    kernel::transform<T, false, AF_INTERP_LOWER>
-                                     (out, in, transform);
-                    break;
-                default:
-                    AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
-                    break;
+            if (perspective) {
+                switch(method) {
+                    case AF_INTERP_NEAREST:
+                        kernel::transform<T, false, true, AF_INTERP_NEAREST>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_BILINEAR:
+                        kernel::transform<T, false, true, AF_INTERP_BILINEAR>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_LOWER:
+                        kernel::transform<T, false, true, AF_INTERP_LOWER>
+                                         (out, in, transform);
+                        break;
+                    default:
+                        AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
+                        break;
+                }
+            } else {
+                switch(method) {
+                    case AF_INTERP_NEAREST:
+                        kernel::transform<T, false, false, AF_INTERP_NEAREST>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_BILINEAR:
+                        kernel::transform<T, false, false, AF_INTERP_BILINEAR>
+                                         (out, in, transform);
+                        break;
+                    case AF_INTERP_LOWER:
+                        kernel::transform<T, false, false, AF_INTERP_LOWER>
+                                         (out, in, transform);
+                        break;
+                    default:
+                        AF_ERROR("Unsupported interpolation type", AF_ERR_ARG);
+                        break;
+                }
             }
         }
 
@@ -68,7 +108,7 @@ namespace opencl
 #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)
     INSTANTIATE(double)
diff --git a/src/backend/opencl/transform.hpp b/src/backend/opencl/transform.hpp
index f0b4d4c..064817a 100644
--- a/src/backend/opencl/transform.hpp
+++ b/src/backend/opencl/transform.hpp
@@ -14,5 +14,5 @@ namespace opencl
 {
     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);
 }

-- 
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