[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