Skip to content

Commit 61ea091

Browse files
author
pradeep
committed
FEAT: Summed Area Tables (sat, af_sat) a.k.a integral images
1 parent 3d405b9 commit 61ea091

5 files changed

Lines changed: 160 additions & 0 deletions

File tree

docs/details/image.dox

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,19 @@ from the other and returns the result.
583583

584584
=======================================================================
585585

586+
\defgroup image_func_sat SAT
587+
\ingroup imageflt_mat
588+
589+
\brief Summed Area Tables
590+
591+
Given an image \f$ I: (x,y) \mapsto i \f$ where i is pixel intensity at position \f$(x, y)\f$.
592+
593+
\f$S(x, y) = i(x, y) + S(x-1, y) + S(x, y-1) - S(x-1, y-1)\f$
594+
595+
The output array of this function will have \f$ S(x, y) \f$ values at their corresponding locations, \f$(x,y)\f$
596+
597+
=======================================================================
598+
586599
\defgroup image_func_unwrap unwrap
587600
\ingroup image_mod
588601

include/af/image.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,17 @@ AFAPI array dog(const array& in, const int radius1, const int radius2);
490490
AFAPI array unwrap(const array& in, const dim_t wx, const dim_t wy,
491491
const dim_t sx, const dim_t sy, const dim_t px=0, const dim_t py=0);
492492

493+
494+
/**
495+
C++ Interface wrapper for summed area tables
496+
497+
\param[in] in is the input array
498+
\returns the summed area table of input image
499+
500+
\ingroup image_func_sat
501+
*/
502+
AFAPI array sat(const array& in);
503+
493504
}
494505
#endif
495506

@@ -965,6 +976,18 @@ extern "C" {
965976
AFAPI af_err af_unwrap(af_array *out, const af_array in, const dim_t wx, const dim_t wy,
966977
const dim_t sx, const dim_t sy, const dim_t px, const dim_t py);
967978

979+
/**
980+
C Interface wrapper for summed area tables
981+
982+
\param[out] out is the summed area table on input image(s)
983+
\param[in] in is the input array
984+
\return \ref AF_SUCCESS if the sat computation is successful,
985+
otherwise an appropriate error code is returned.
986+
987+
\ingroup image_func_sat
988+
*/
989+
AFAPI af_err af_sat(af_array *out, const af_array in);
990+
968991
#ifdef __cplusplus
969992
}
970993
#endif

src/api/c/sat.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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/defines.h>
11+
#include <af/image.h>
12+
#include <handle.hpp>
13+
#include <err_common.hpp>
14+
#include <scan.hpp>
15+
16+
using af::dim4;
17+
using namespace detail;
18+
19+
template<typename To, typename Ti>
20+
static af_array sat(const af_array& in)
21+
{
22+
const Array<To> input = castArray<To>(in);
23+
24+
Array<To> hprefix_scan = scan<af_add_t, To, To>(input, 0);
25+
Array<To> vprefix_scan = scan<af_add_t, To, To>(hprefix_scan, 1);
26+
27+
return getHandle<To>(vprefix_scan);
28+
}
29+
30+
af_err af_sat(af_array* out, const af_array in)
31+
{
32+
try{
33+
ArrayInfo info = getInfo(in);
34+
const dim4 dims = info.dims();
35+
36+
ARG_ASSERT(1, (dims.ndims() >= 2));
37+
38+
af_dtype inputType = info.getType();
39+
40+
af_array output = 0;
41+
switch(inputType) {
42+
case f64: output = sat<double, double>(in); break;
43+
case f32: output = sat<float , float >(in); break;
44+
case s32: output = sat<int , int >(in); break;
45+
case u32: output = sat<uint , uint >(in); break;
46+
case b8: output = sat<int , char >(in); break;
47+
case u8: output = sat<uint , uchar >(in); break;
48+
case s64: output = sat<intl , intl >(in); break;
49+
case u64: output = sat<uintl , uintl >(in); break;
50+
default: TYPE_ERROR(1, inputType);
51+
}
52+
std::swap(*out, output);
53+
}
54+
CATCHALL;
55+
56+
return AF_SUCCESS;
57+
}

src/api/cpp/sat.cpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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/image.h>
11+
#include <af/array.h>
12+
#include "error.hpp"
13+
14+
namespace af
15+
{
16+
17+
array sat(const array& in)
18+
{
19+
af_array out = 0;
20+
AF_THROW(af_sat(&out, in.get()));
21+
return array(out);
22+
}
23+
24+
}

test/sat.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
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 <gtest/gtest.h>
11+
#include <arrayfire.h>
12+
#include <af/dim4.hpp>
13+
#include <af/traits.hpp>
14+
#include <string>
15+
#include <vector>
16+
#include <testHelpers.hpp>
17+
18+
using std::string;
19+
using std::vector;
20+
21+
template<typename T>
22+
class SAT : public ::testing::Test
23+
{
24+
public:
25+
virtual void SetUp() {}
26+
};
27+
28+
// create a list of types to be tested
29+
typedef ::testing::Types<float, double, int, uint, char, uchar, uintl, intl> TestTypes;
30+
31+
// register the type list
32+
TYPED_TEST_CASE(SAT, TestTypes);
33+
34+
TYPED_TEST(SAT, IntegralImage)
35+
{
36+
af::array a = af::randu(530, 671, (af_dtype)af::dtype_traits<TypeParam>::af_type);
37+
af::array b = af::accum(a, 0);
38+
af::array c = af::accum(b, 1);
39+
40+
af::array s = af::sat(a);
41+
42+
EXPECT_EQ(true, af::allTrue<float>(c==s));
43+
}

0 commit comments

Comments
 (0)