Skip to content

Commit d21b107

Browse files
committed
FEAT: Adding gaussian kernel to all backends
1 parent 78d41ec commit d21b107

4 files changed

Lines changed: 130 additions & 0 deletions

File tree

include/af/compatible.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#pragma once
1111
#include <af/array.h>
12+
#include <af/image.h>
1213

1314
#ifdef __cplusplus
1415
namespace af
@@ -24,5 +25,8 @@ AFAPI array loadimage(const char* filename, const bool is_color=false);
2425

2526
AFAPI void saveimage(const char* filename, const array& in);
2627

28+
AFAPI array gaussiankernel(const int rows, const int cols, const double sig_r = 0, const double sig_c = 0);
29+
30+
2731
}
2832
#endif

include/af/image.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ AFAPI array gray2rgb(const array& in, const float rFactor=1.0, const float gFact
7474

7575
AFAPI array histequal(const array& in, const array& hist);
7676

77+
AFAPI array gaussianKernel(const int rows, const int cols, const double sig_r = 0, const double sig_c = 0);
78+
7779
}
7880
#endif
7981

@@ -155,6 +157,10 @@ extern "C" {
155157

156158
AFAPI af_err af_histequal(af_array *out, const af_array in, const af_array hist);
157159

160+
AFAPI af_err af_gaussian_kernel(af_array *out,
161+
const int rows, const int cols,
162+
const double sigma_r, const double sigma_c);
163+
158164
#ifdef __cplusplus
159165
}
160166
#endif

src/api/c/gaussian_kernel.cpp

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*******************************************************
2+
* Copyright (c) 2014, ArrayFire
3+
* All rights reserved.
4+
*
5+
* This file is distributed under 3-clause BSD license.
6+
* The complete license agreement can be obtained at:
7+
* http://arrayfire.com/licenses/BSD-3-Clause
8+
********************************************************/
9+
10+
#include <af/dim4.hpp>
11+
#include <af/defines.h>
12+
#include <af/image.h>
13+
#include <err_common.hpp>
14+
#include <backend.hpp>
15+
#include <handle.hpp>
16+
#include <reduce.hpp>
17+
#include <arith.hpp>
18+
#include <math.hpp>
19+
#include <unary.hpp>
20+
#include <iota.hpp>
21+
#include <reduce.hpp>
22+
#include <transpose.hpp>
23+
24+
using namespace detail;
25+
26+
template<typename T>
27+
Array<T> gaussianKernel(const int rows, const int cols, const double sigma_r, const double sigma_c)
28+
{
29+
const dim4 odims = dim4(rows, cols);
30+
double sigma = 0;
31+
32+
Array<T> tmp = createValueArray<T>(odims, scalar<T>(0));
33+
Array<T> half = createValueArray<T>(odims, 0.5);
34+
Array<T> zero = createValueArray<T>(odims, scalar<T>(0));
35+
36+
if (cols > 1) {
37+
Array<T> wt = iota<T>(dim4(cols, rows), 0);
38+
Array<T> w = transpose<T>(wt, false);
39+
40+
Array<T> c = createValueArray<T>(odims, scalar<T>((double)(cols - 1) / 2.0));
41+
w = arithOp<T, af_sub_t>(w, c, odims);
42+
43+
sigma = sigma_c > 0 ? sigma_c : 0.25 * cols;
44+
Array<T> sig = createValueArray<T>(odims, sigma);
45+
w = arithOp<T, af_div_t>(w, sig, odims);
46+
47+
w = arithOp<T, af_mul_t>(w, w, odims);
48+
tmp = arithOp<T, af_add_t>(w, tmp, odims);
49+
}
50+
51+
if (rows > 1) {
52+
Array<T> w = iota<T>(dim4(rows, cols), 0);
53+
54+
Array<T> r = createValueArray<T>(odims, scalar<T>((double)(rows - 1) / 2.0));
55+
w = arithOp<T, af_sub_t>(w, r, odims);
56+
57+
sigma = sigma_r > 0 ? sigma_r : 0.25 * rows;
58+
Array<T> sig = createValueArray<T>(odims, sigma);
59+
60+
w = arithOp<T, af_div_t>(w, sig, odims);
61+
w = arithOp<T, af_mul_t>(w, w, odims);
62+
tmp = arithOp<T, af_add_t>(w, tmp, odims);
63+
}
64+
65+
tmp = arithOp<T, af_mul_t>(half, tmp, odims);
66+
tmp = arithOp<T, af_sub_t>(zero, tmp, odims);
67+
tmp = unaryOp<T, af_exp_t>(tmp);
68+
69+
// Use this instead of (2 * pi * sig^2);
70+
// This ensures the window adds up to 1
71+
T norm_factor = reduce_all<af_add_t, T, T>(tmp);
72+
73+
Array<T> norm = createValueArray(odims, norm_factor);
74+
Array<T> res = arithOp<T, af_div_t>(tmp, norm, odims);
75+
76+
return res;
77+
}
78+
79+
af_err af_gaussian_kernel(af_array *out,
80+
const int rows, const int cols,
81+
const double sigma_r, const double sigma_c)
82+
{
83+
af_array res;
84+
try {
85+
res = getHandle<float>(gaussianKernel<float>(rows, cols, sigma_r, sigma_c));
86+
std::swap(*out, res);
87+
}CATCHALL;
88+
return AF_SUCCESS;
89+
}

src/api/cpp/gaussian_kernel.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*******************************************************
2+
* Copyright (c) 2014, ArrayFire
3+
* All rights reserved.
4+
*
5+
* This file is distributed under 3-clause BSD license.
6+
* The complete license agreement can be obtained at:
7+
* http://arrayfire.com/licenses/BSD-3-Clause
8+
********************************************************/
9+
#include <af/dim4.hpp>
10+
#include <af/image.h>
11+
#include <af/algorithm.h>
12+
#include <af/compatible.h>
13+
#include "error.hpp"
14+
15+
namespace af{
16+
array gaussianKernel(const int rows, const int cols,
17+
const double sig_r, const double sig_c)
18+
{
19+
af_array res;
20+
AF_THROW(af_gaussian_kernel(&res, rows, cols, sig_r, sig_c));
21+
return array(res);
22+
}
23+
24+
// Compatible function
25+
array gaussiankernel(const int rows, const int cols,
26+
const double sig_r, const double sig_c)
27+
{
28+
return gaussianKernel(rows, cols, sig_r, sig_c);
29+
}
30+
31+
}

0 commit comments

Comments
 (0)