17#ifndef __filter_connected_h__
18#define __filter_connected_h__
25#include "filter/base.h"
57 use_26_neighbours (false),
58 enabled_axes (3, true) { }
61 if (
axis > enabled_axes.size())
62 enabled_axes.resize (
axis+1,
false);
81 use_26_neighbours = i;
85 size_t size()
const {
return data.size(); }
88 bool use_26_neighbours;
119 template <
class VectorType>
121 const VectorType&,
const float)
const;
129 template <
class VectorType>
131 const VectorType&,
const float)
const;
134 template <
class VectorType>
136 const VectorType&,
const float)
const;
143 template <
class VectorType>
146 const VectorType& data,
147 const float threshold)
const
151 uint32_t current_label = 0;
152 for (uint32_t i = 0; i < labels.size(); i++) {
154 if (!labels[i] && data[i] > threshold) {
155 Cluster cluster (++current_label);
156 depth_first_search (i, cluster, labels, data, threshold);
157 clusters.push_back (cluster);
160 if (clusters.size() > std::numeric_limits<uint32_t>::max())
161 throw Exception (
"The number of clusters is larger than can be labelled with an unsigned 32bit integer.");
166 template <
class VectorType>
167 bool Connector::next_neighbour (uint32_t& node,
169 const VectorType& data,
170 const float threshold)
const
173 if (!labels[n] && data[n] > threshold) {
183 template <
class VectorType>
184 void Connector::depth_first_search (
const uint32_t root,
186 vector<uint32_t>& labels,
187 const VectorType& data,
188 const float threshold)
const
190 uint32_t node = root;
191 std::stack<uint32_t> stack;
193 labels[node] = cluster.label;
196 if (next_neighbour (node, labels, data, threshold)) {
200 if (stack.top() == root)
204 }
while (!next_neighbour (node, labels, data, threshold));
231 template <
class HeaderType>
238 if (this->ndim() > 4)
239 throw Exception (
"Cannot run connected components analysis with more than 4 dimensions");
246 template <
class HeaderType>
254 template <
class InputVoxelType,
class OutputVoxelType>
255 void operator() (InputVoxelType& in, OutputVoxelType& out)
264 std::unique_ptr<ProgressBar> progress;
272 connector.
run (clusters, labels);
273 if (progress) ++(*progress);
277 if (progress) ++(*progress);
282 for (uint32_t c = 0; c < clusters.size(); c++)
283 index_lookup[clusters[c].label] = c + 1;
285 for (
auto l =
Loop (out) (out); l; ++l)
288 for (uint32_t i = 0; i < v2v.size(); i++) {
289 assign_pos_of (v2v[i]).to (out);
291 if (index_lookup[labels[i]] == 1)
294 out.value() = index_lookup[labels[i]];
303 const size_t max_axis = *std::max_element (i.begin(), i.end());
304 if (max_axis >= ndim())
305 throw Exception (
"Requested axis for connected component filter (" +
str(max_axis) +
" is beyond the dimensionality of the image (" +
str(ndim()) +
"D)");
306 enabled_axes.assign (std::max (max_axis+1,
size_t(ndim())),
false);
307 for (
const auto&
axis : i) {
309 throw Exception (
"Cannot specify negative axis index for connected-component filter");
315 void set_largest_only (
bool value)
321 void set_26_connectivity (
bool value)
static constexpr uint8_t UInt32
vector< bool > enabled_axes
const vector< index_t > & operator[](const size_t index) const
void toggle_axis(const size_t axis, const bool value)
void set_axes(const vector< bool > &i)
void initialise(const Header &, const Voxel2Vector &)
Voxel2Vector::index_t index_t
void set_26_adjacency(const bool i)
bool operator<(const Cluster &j) const
Cluster(const uint32_t l)
class MR::Filter::Connector::Adjacency adjacency
void run(vector< Cluster > &, vector< uint32_t > &) const
static bool largest(const Cluster &i, const Cluster &j)
implements a progress meter to provide feedback to the user
FORCE_INLINE LoopAlongAxes Loop()
VectorType::Scalar value(const VectorType &coefs, typename VectorType::Scalar cos_elevation, typename VectorType::Scalar cos_azimuth, typename VectorType::Scalar sin_azimuth, int lmax)
std::string str(const T &value, int precision=0)