[arrayfire] 14/408: FEAT: Difference of Gaussians

Ghislain Vaillant ghisvail-guest at moszumanska.debian.org
Mon Sep 21 19:11:05 UTC 2015


This is an automated email from the git hooks/post-receive script.

ghisvail-guest pushed a commit to branch debian/sid
in repository arrayfire.

commit f00a3966a2f3f8c0c19dd9ab193d03de8e16b413
Author: pradeep <pradeep at arrayfire.com>
Date:   Thu Jun 18 15:31:22 2015 -0400

    FEAT: Difference of Gaussians
    
    * CPU, CUDA & OpenCL backends
    * Unit tests for non-batched, batched & invalid inputs
    * Documentation
---
 docs/details/image.dox                | 13 ++++++
 examples/image_processing/filters.cpp |  6 +--
 include/af/image.h                    | 26 ++++++++++++
 src/api/c/dog.cpp                     | 69 ++++++++++++++++++++++++++++++++
 src/api/cpp/dog.cpp                   | 24 +++++++++++
 test/dog.cpp                          | 75 +++++++++++++++++++++++++++++++++++
 6 files changed, 210 insertions(+), 3 deletions(-)

diff --git a/docs/details/image.dox b/docs/details/image.dox
index 7491d25..4707de7 100644
--- a/docs/details/image.dox
+++ b/docs/details/image.dox
@@ -570,5 +570,18 @@ Interpolation types of \ref AF_INTERP_NEAREST and \ref AF_INTERP_BILINEAR are al
 Affine transforms can be used for various purposes. \ref af::translate, \ref af::scale and \ref af::skew
 are specializations of the transform function.
 
+=======================================================================
+
+\defgroup image_func_dog DoG
+\ingroup imageflt_mat
+
+\brief Difference of Gaussians
+
+Given an image, this function computes two different versions of smoothed
+input image using the difference smoothing parameters and subtracts one
+from the other and returns the result.
+
+=======================================================================
+
 @}
 */
diff --git a/examples/image_processing/filters.cpp b/examples/image_processing/filters.cpp
index e669620..1032043 100644
--- a/examples/image_processing/filters.cpp
+++ b/examples/image_processing/filters.cpp
@@ -130,7 +130,7 @@ void normalizeImage(array &in)
     in = 255.0f*((in - min) / (max - min));
 }
 
-array dog(const array &in, int window_radius1, int window_radius2)
+array DifferenceOfGaussian(const array &in, int window_radius1, int window_radius2)
 {
     array ret_val;
     int w1 = 2 * window_radius1 + 1;
@@ -224,7 +224,7 @@ int main(int argc, char **argv)
         array sprd = spread(lena, 3, 3);
         array hrl = hurl(lena, 10, 1);
         array pckng = pick(lena, 40, 2);
-        array difog = dog(lena, 1, 2);
+        array difog = DifferenceOfGaussian(lena, 1, 2);
         array bil = bilateral(hrl, 3.0f, 40.0f);
         array mf = medianfilter(hrl, 5, 5);
         array gb = gaussianblur(hrl, 3, 3, 0.8);
@@ -261,4 +261,4 @@ int main(int argc, char **argv)
     }
 #endif
     return 0;
-}
\ No newline at end of file
+}
diff --git a/include/af/image.h b/include/af/image.h
index 67f5fc3..165def3 100644
--- a/include/af/image.h
+++ b/include/af/image.h
@@ -461,6 +461,18 @@ AFAPI array rgb2hsv(const array& in);
  */
 AFAPI array colorSpace(const array& image, const CSpace to, const CSpace from);
 
+/**
+   C++ Interface wrapper for Difference of Gaussians
+
+   \param[in] in is input image
+   \param[in] radius1 is the radius of first gaussian kernel
+   \param[in] radius2 is the radius of second gaussian kernel
+   \return    Difference of smoothed inputs
+
+   \ingroup image_func_dog
+ */
+AFAPI array dog(const array& in, const int radius1, const int radius2);
+
 }
 #endif
 
@@ -903,6 +915,20 @@ extern "C" {
     */
     AFAPI af_err af_color_space(af_array *out, const af_array image, const af_cspace_t to, const af_cspace_t from);
 
+    /**
+       C Interface wrapper for Difference of Gaussians
+
+       \param[out] out is difference of smoothed inputs
+       \param[in] in is input image
+       \param[in] radius1 is the radius of first gaussian kernel
+       \param[in] radius2 is the radius of second gaussian kernel
+       \return    \ref AF_SUCCESS if the computation is is successful,
+                  otherwise an appropriate error code is returned.
+
+       \ingroup image_func_dog
+     */
+    AFAPI af_err af_dog(af_array *out, const af_array in, const int radius1, const int radius2);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/api/c/dog.cpp b/src/api/c/dog.cpp
new file mode 100644
index 0000000..16b0c53
--- /dev/null
+++ b/src/api/c/dog.cpp
@@ -0,0 +1,69 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/dim4.hpp>
+#include <af/defines.h>
+#include <af/image.h>
+#include <err_common.hpp>
+#include <backend.hpp>
+#include <handle.hpp>
+#include <convolve.hpp>
+#include <arith.hpp>
+
+using af::dim4;
+using namespace detail;
+
+template<typename T, typename accT>
+static af_array dog(const af_array& in, const int radius1, const int radius2)
+{
+    af_array g1, g2;
+    g1 = g2 = 0;
+    AF_CHECK(af_gaussian_kernel(&g1, 2*radius1+1, 2*radius1+1, 0.0, 0.0));
+    AF_CHECK(af_gaussian_kernel(&g2, 2*radius2+1, 2*radius2+1, 0.0, 0.0));
+
+    Array<T> input  = getArray<T>(in);
+    dim4 iDims      = input.dims();
+
+    ConvolveBatchKind bkind = iDims[2] > 1 ? MANY2ONE : ONE2ONE;
+
+    Array<T> smth1 = convolve<T, accT, 2, false>(input, castArray<accT>(g1), bkind);
+    Array<T> smth2 = convolve<T, accT, 2, false>(input, castArray<accT>(g2), bkind);
+    Array<T> retVal= arithOp<T, af_sub_t>(smth1, smth2, iDims);
+
+    AF_CHECK(af_release_array(g1));
+    AF_CHECK(af_release_array(g2));
+
+    return getHandle<T>(retVal);
+}
+
+af_err af_dog(af_array *out, const af_array in, const int radius1, const int radius2)
+{
+    try {
+        ArrayInfo info = getInfo(in);
+        dim4 inDims = info.dims();
+        ARG_ASSERT(1, (inDims.ndims()>=2));
+        ARG_ASSERT(1, (inDims.ndims()<=3));
+
+        af_array output;
+        af_dtype type  = info.getType();
+        switch(type) {
+            case f32: output = dog<float , float>(in, radius1, radius2); break;
+            case f64: output = dog<double,double>(in, radius1, radius2); break;
+            case b8 : output = dog<char  , float>(in, radius1, radius2); break;
+            case s32: output = dog<int   , float>(in, radius1, radius2); break;
+            case u32: output = dog<uint  , float>(in, radius1, radius2); break;
+            case u8 : output = dog<uchar , float>(in, radius1, radius2); break;
+            default : TYPE_ERROR(1, type);
+        }
+        std::swap(*out, output);
+    }
+    CATCHALL;
+
+    return AF_SUCCESS;
+}
diff --git a/src/api/cpp/dog.cpp b/src/api/cpp/dog.cpp
new file mode 100644
index 0000000..6d8e138
--- /dev/null
+++ b/src/api/cpp/dog.cpp
@@ -0,0 +1,24 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <af/array.h>
+#include <af/image.h>
+#include "error.hpp"
+
+namespace af
+{
+
+array dog(const array& in, const int radius1, const int radius2)
+{
+    af_array temp = 0;
+    AF_THROW(af_dog(&temp, in.get(), radius1, radius2));
+    return array(temp);
+}
+
+}
diff --git a/test/dog.cpp b/test/dog.cpp
new file mode 100644
index 0000000..aa85814
--- /dev/null
+++ b/test/dog.cpp
@@ -0,0 +1,75 @@
+/*******************************************************
+ * Copyright (c) 2015, ArrayFire
+ * All rights reserved.
+ *
+ * This file is distributed under 3-clause BSD license.
+ * The complete license agreement can be obtained at:
+ * http://arrayfire.com/licenses/BSD-3-Clause
+ ********************************************************/
+
+#include <gtest/gtest.h>
+#include <arrayfire.h>
+#include <af/dim4.hpp>
+#include <af/traits.hpp>
+#include <string>
+#include <vector>
+#include <testHelpers.hpp>
+
+template<typename T>
+class DOG : public ::testing::Test
+{
+    public:
+        virtual void SetUp() {}
+};
+
+// create a list of types to be tested
+typedef ::testing::Types<float, double, int, uint, char, uchar> TestTypes;
+
+// register the type list
+TYPED_TEST_CASE(DOG, TestTypes);
+
+
+TYPED_TEST(DOG, Basic)
+{
+    if (noDoubleTests<TypeParam>()) return;
+
+    af::dim4 iDims(512, 512, 1, 1);
+    af::array in = af::constant<TypeParam>(1, iDims);
+    /* calculate DOG using ArrayFire functions */
+    af::array k1    = af::gaussianKernel(3, 3);
+    af::array k2    = af::gaussianKernel(2, 2);
+    af::array smth1 = af::convolve2(in, k1);
+    af::array smth2 = af::convolve2(in, k2);
+    af::array diff  = smth1 - smth2;
+    /* calcuate DOG using new function */
+    af::array out= af::dog(in, 3, 2);
+    /* compare both the values */
+    float accumErr = af::sum<float>(out-diff);
+    EXPECT_EQ(true, accumErr<1.0e-2);
+}
+
+TYPED_TEST(DOG, Batch)
+{
+    if (noDoubleTests<TypeParam>()) return;
+
+    af::dim4 iDims(512, 512, 3, 1);
+    af::array in = af::constant<TypeParam>(1, iDims);
+    /* calculate DOG using ArrayFire functions */
+    af::array k1    = af::gaussianKernel(3, 3);
+    af::array k2    = af::gaussianKernel(2, 2);
+    af::array smth1 = af::convolve2(in, k1);
+    af::array smth2 = af::convolve2(in, k2);
+    af::array diff  = smth1 - smth2;
+    /* calcuate DOG using new function */
+    af::array out= af::dog(in, 3, 2);
+    /* compare both the values */
+    float accumErr = af::sum<float>(out-diff);
+    EXPECT_EQ(true, accumErr<1.0e-2);
+}
+
+TYPED_TEST(DOG, InvalidArray)
+{
+    af::array in = af::randu(512);
+    EXPECT_THROW(af::dog(in, 3, 2),
+                 af::exception);
+}

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