GooseEYE 0.9.1
Loading...
Searching...
No Matches
Ensemble_L.hpp
Go to the documentation of this file.
1
7#ifndef GOOSEEYE_ENSEMBLE_L_HPP
8#define GOOSEEYE_ENSEMBLE_L_HPP
9
10#include "GooseEYE.h"
11
12namespace GooseEYE {
13
14template <class T>
15inline void Ensemble::L(const T& f, path_mode mode)
16{
17 using value_type = typename T::value_type;
18
19 static_assert(std::is_integral<value_type>::value, "Integral image required.");
20
21 GOOSEEYE_ASSERT(f.dimension() == m_shape_orig.size(), std::out_of_range);
22 GOOSEEYE_ASSERT(m_stat == Type::L || m_stat == Type::Unset, std::out_of_range);
23
24 // lock statistics
25 m_stat = Type::L;
26
27 // not periodic (default): mask padded items
28 xt::pad_mode pad_mode = xt::pad_mode::constant;
29
30 // periodic: unmask padded items
31 if (m_periodic) {
32 pad_mode = xt::pad_mode::periodic;
33 }
34
35 // apply padding & convert to quasi-3d
36 array_type::tensor<value_type, 3> F = xt::pad(xt::atleast_3d(f), m_pad, pad_mode);
37
38 // ROI-shaped array used to extract a pixel stamp:
39 // a set of end-points over which to loop and check the statics
40 // - initialize to 1
41 array_type::tensor<int, 3> r = xt::ones<int>(m_shape);
42 // - determine interior pixels (account for quasi-3D images)
43 auto ix = m_shape[0] > 1 ? xt::range(1, m_shape[0] - 1) : xt::range(0, m_shape[0]);
44 auto iy = m_shape[1] > 1 ? xt::range(1, m_shape[1] - 1) : xt::range(0, m_shape[1]);
45 auto iz = m_shape[2] > 1 ? xt::range(1, m_shape[2] - 1) : xt::range(0, m_shape[2]);
46 // - set interior pixels to 0
47 xt::view(r, ix, iy, iz) = 0;
48
49 // get stamp, from the matrix "r"
50 array_type::tensor<int, 2> stamp = xt::from_indices(xt::argwhere(r));
51 for (size_t i = 0; i < MAX_DIM; ++i) {
52 xt::view(stamp, xt::all(), xt::keep(i)) -= m_pad[i][0];
53 }
54
55 // correlation
56 // N.B. getting the pixel paths is relatively expensive, so it is the output-most loop
57 for (size_t istamp = 0; istamp < stamp.shape(0); ++istamp) {
58
59 // pixel path between the center of the ROI and the current stamp point
61 GooseEYE::path({0, 0, 0}, {stamp(istamp, 0), stamp(istamp, 1), stamp(istamp, 2)}, mode);
62
63 // compute correlation along this path, for the entire image
64 for (size_t h = m_pad[0][0]; h < F.shape(0) - m_pad[0][1]; ++h) {
65 for (size_t i = m_pad[1][0]; i < F.shape(1) - m_pad[1][1]; ++i) {
66 for (size_t j = m_pad[2][0]; j < F.shape(2) - m_pad[2][1]; ++j) {
67 for (size_t p = 0; p < path.shape(0); ++p) {
68 // - get current relative position
69 int dh = path(p, 0);
70 int di = path(p, 1);
71 int dj = path(p, 2);
72 // - check to terminal walking along this path
73 if (!F(h + dh, i + di, j + dj)) {
74 break;
75 }
76 // - update the result
77 m_first(m_pad[0][0] + dh, m_pad[1][0] + di, m_pad[2][0] + dj) += 1.0;
78 }
79 }
80 }
81 }
82
83 // normalisation
84 for (size_t p = 0; p < path.shape(0); ++p) {
85 int dh = path(p, 0);
86 int di = path(p, 1);
87 int dj = path(p, 2);
88 m_norm(m_pad[0][0] + dh, m_pad[1][0] + di, m_pad[2][0] + dj) += f.size();
89 }
90 }
91}
92
93} // namespace GooseEYE
94
95#endif
#define GOOSEEYE_ASSERT(expr, assertion)
All assertions are implemented as:
Definition config.h:91
xt::xtensor< T, N > tensor
Fixed (static) rank array.
Definition config.h:155
Toolbox to compute statistics.
Definition config.h:128
path_mode
Different methods to compute a pixel-path.
Definition GooseEYE.h:93
array_type::tensor< int, 2 > path(const array_type::tensor< int, 1 > &x0, const array_type::tensor< int, 1 > &x1, path_mode mode=path_mode::Bresenham)
Compute a path between two pixels.
Definition GooseEYE.hpp:15