MorphologicalAttributeFilters
Public API documentation
Loading...
Searching...
No Matches
AttributeComputation.hpp
1#pragma once
2
3#include "../utils/Image.hpp"
4#include "../attributes/AttributeResultTypes.hpp"
5#include "../trees/MorphologicalTree.hpp"
6#include "../trees/WeightedMorphologicalTree.hpp"
7#include "../trees/WeightedTreeView.hpp"
8
9#include <concepts>
10#include <span>
11#include <string>
12#include <type_traits>
13#include <utility>
14#include <vector>
15
16namespace mmcfilters {
17
51public:
52
64 template <std::floating_point Real = float>
65 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const MorphologicalTree& tree, AttributeOrGroup attr, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
66
78 template <std::floating_point Real = float>
79 [[nodiscard]] static ComputedAttributeData<Real> computeTopologyAttributes(const MorphologicalTree& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
80
90 template<std::floating_point Real = float, AltitudeValue T>
91 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const WeightedMorphologicalTree<T>& tree, AttributeOrGroup attr, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
92
104 template<std::floating_point Real = float, AltitudeValue T>
105 [[nodiscard]] static ComputedAttributeData<Real> computeSingleTopologyAttribute(const WeightedTreeView<T>& tree, AttributeOrGroup attr, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
106
116 template<std::floating_point Real = float, AltitudeValue T>
117 [[nodiscard]] static ComputedAttributeData<Real> computeTopologyAttributes(const WeightedMorphologicalTree<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
118
130 template<std::floating_point Real = float, AltitudeValue T>
131 [[nodiscard]] static ComputedAttributeData<Real> computeTopologyAttributes(const WeightedTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
132
145 template<std::floating_point Real = float, AltitudeValue T>
146 [[nodiscard]] static ComputedAttributeData<Real> computeSingleAttribute(const WeightedMorphologicalTree<T>& tree, AttributeOrGroup attr, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
147
159 template<std::floating_point Real = float, AltitudeValue T>
160 [[nodiscard]] static ComputedAttributeData<Real> computeSingleAttribute(const WeightedTreeView<T>& tree, AttributeOrGroup attr, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
161
176 template<std::floating_point Real = float, AltitudeValue T>
177 [[nodiscard]] static ComputedAttributeDataWithDelta<Real> computeSingleAttributeWithDelta(const WeightedMorphologicalTree<T>& tree, Attribute attribute, AltitudeDiff<T> deltaStep, int radius, std::string padding="last-padding", NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
178
193 template<std::floating_point Real = float, AltitudeValue T>
194 [[nodiscard]] static ComputedAttributeDataWithDelta<Real> computeSingleAttributeWithDelta(const WeightedTreeView<T>& tree, Attribute attribute, AltitudeDiff<T> deltaStep, int radius, std::string padding="last-padding", NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
195
211 template<std::floating_point Real = float, AltitudeValue T>
212 [[nodiscard]] static ComputedAttributeData<Real> computeAttributes(const WeightedMorphologicalTree<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
213
225 template<std::floating_point Real = float, AltitudeValue T>
226 [[nodiscard]] static ComputedAttributeData<Real> computeAttributes(const WeightedTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
227
243 template<std::floating_point Real = float, AltitudeValue T>
244 [[nodiscard]] static ComputedAttributeData<Real> computeAttributesFromAltitudeSpan(const WeightedTreeView<T>& weighted, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace = NodeIdSpace::MORPHOLOGICAL_TREE);
245
264 template<std::floating_point Real = float, AltitudeValue T>
265 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const WeightedMorphologicalTree<T>& tree, const AttributeNames& attrNames, std::span<const Real> nodeValues);
266
276 template<std::floating_point Real = float, AltitudeValue T>
277 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const WeightedMorphologicalTree<T>& tree, const AttributeNames& attrNames, const std::vector<Real>& nodeValues);
278
288 template<std::floating_point Real = float, AltitudeValue T>
289 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const WeightedTreeView<T>& tree, const AttributeNames& attrNames, std::span<const Real> nodeValues);
290
300 template<std::floating_point Real = float, AltitudeValue T>
301 [[nodiscard]] static std::vector<Real> projectNodeValuesToExportedHigra(const WeightedTreeView<T>& tree, const AttributeNames& attrNames, const std::vector<Real>& nodeValues);
302
311 template<std::floating_point Real = float, AltitudeValue T>
312 [[nodiscard]] static ImagePtr<Real> computeAttributeMapping(const WeightedMorphologicalTree<T>& tree, Attribute attribute);
313
322 template<std::floating_point Real = float, AltitudeValue T>
323 [[nodiscard]] static ImagePtr<Real> computeAttributeMapping(const WeightedTreeView<T>& tree, Attribute attribute);
324
325};
326
327} // namespace mmcfilters
328
329
330
331#include "../attributes/detail/AttributeDeltaMaterialization.hpp"
332#include "../attributes/detail/AttributePipeline.hpp"
333#include "../attributes/detail/AttributeProjection.hpp"
334
335
336
337namespace mmcfilters {
338
339namespace detail {
340
341template<std::floating_point OutputReal, std::floating_point InternalReal>
342[[nodiscard]] inline ComputedAttributeData<OutputReal> castComputedAttributeData(ComputedAttributeData<InternalReal> computed) {
343 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
344 return computed;
345 } else {
346 std::vector<OutputReal> output;
347 output.reserve(computed.second.size());
348 for (const InternalReal value : computed.second) {
349 output.push_back(static_cast<OutputReal>(value));
350 }
351 return ComputedAttributeData<OutputReal>{
352 std::move(computed.first),
353 std::move(output),
354 computed.nodeIdSpace};
355 }
356}
357
358template<std::floating_point OutputReal, std::floating_point InternalReal>
359[[nodiscard]] inline ComputedAttributeDataWithDelta<OutputReal> castComputedAttributeDataWithDelta(ComputedAttributeDataWithDelta<InternalReal> computed) {
360 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
361 return computed;
362 } else {
363 std::vector<OutputReal> output;
364 output.reserve(computed.second.size());
365 for (const InternalReal value : computed.second) {
366 output.push_back(static_cast<OutputReal>(value));
367 }
368 return ComputedAttributeDataWithDelta<OutputReal>{
369 std::move(computed.first),
370 std::move(output),
371 computed.nodeIdSpace};
372 }
373}
374
375template<std::floating_point OutputReal, std::floating_point InternalReal>
376[[nodiscard]] inline std::vector<OutputReal> castAttributeValues(std::vector<InternalReal> values) {
377 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
378 return values;
379 } else {
380 std::vector<OutputReal> output;
381 output.reserve(values.size());
382 for (const InternalReal value : values) {
383 output.push_back(static_cast<OutputReal>(value));
384 }
385 return output;
386 }
387}
388
389template<std::floating_point OutputReal, std::floating_point InternalReal>
390[[nodiscard]] inline ImagePtr<OutputReal> mapNodeAttributeToImageCast(
391 const MorphologicalTree& tree,
392 const AttributeNames& attrNames,
393 std::span<const InternalReal> nodeValues,
394 Attribute attribute)
395{
396 ImagePtr<OutputReal> imgPtr = Image<OutputReal>::create(tree.getNumRowsOfImage(), tree.getNumColsOfImage());
397 OutputReal* img = imgPtr->rawData();
398 for (int p = 0; p < imgPtr->getSize(); ++p) {
399 const NodeId nodeId = tree.getProperPartOwner(p);
400 img[p] = static_cast<OutputReal>(nodeValues[attrNames.linearIndex(nodeId, attribute)]);
401 }
402 return imgPtr;
403}
404
405} // namespace detail
406
407template <std::floating_point Real>
409 return detail::castComputedAttributeData<Real>(
410 detail::materializeAttributesWithoutAltitude<double>(tree, {attrOrGroup}, outputSpace));
411}
412
413template <std::floating_point Real>
414inline ComputedAttributeData<Real> AttributeComputation::computeTopologyAttributes(const MorphologicalTree& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
415 return detail::castComputedAttributeData<Real>(
416 detail::materializeAttributesWithoutAltitude<double>(tree, attributes, outputSpace));
417}
418
419template<std::floating_point Real, AltitudeValue T>
423
424template<std::floating_point Real, AltitudeValue T>
426 tree.requireTopologyUnchanged("AttributeComputation::computeSingleTopologyAttribute");
427 return detail::castComputedAttributeData<Real>(
428 detail::materializeTopologyAttributeRequest<double>(
429 tree.topology(),
430 tree.altitude(),
431 {attrOrGroup},
432 detail::DependencyMapT<double>{},
433 outputSpace));
434}
435
436template<std::floating_point Real, AltitudeValue T>
437inline ComputedAttributeData<Real> AttributeComputation::computeTopologyAttributes(const WeightedMorphologicalTree<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
438 return computeTopologyAttributes<Real>(tree.asView(), attributes, outputSpace);
439}
440
441template<std::floating_point Real, AltitudeValue T>
442inline ComputedAttributeData<Real> AttributeComputation::computeTopologyAttributes(const WeightedTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
443 tree.requireTopologyUnchanged("AttributeComputation::computeTopologyAttributes");
444 return detail::castComputedAttributeData<Real>(
445 detail::materializeTopologyAttributeRequest<double>(
446 tree.topology(),
447 tree.altitude(),
448 attributes,
449 detail::DependencyMapT<double>{},
450 outputSpace));
451}
452
453template<std::floating_point Real, AltitudeValue T>
457
458template<std::floating_point Real, AltitudeValue T>
462
463template<std::floating_point Real, AltitudeValue T>
465 return computeSingleAttributeWithDelta<Real>(tree.asView(), attribute, deltaStep, radius, std::move(padding), outputSpace);
466}
467
468template<std::floating_point Real, AltitudeValue T>
470 tree.requireTopologyUnchanged("AttributeComputation::computeSingleAttributeWithDelta");
471 auto base = computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MORPHOLOGICAL_TREE);
472
473 return detail::castComputedAttributeDataWithDelta<Real>(
474 detail::materializeSingleAttributeWithTypedDelta<double>(
475 tree.topology(),
476 tree.altitude(),
477 std::move(base),
478 attribute,
479 deltaStep,
480 radius,
481 std::move(padding),
482 outputSpace));
483}
484
485template<std::floating_point Real, AltitudeValue T>
486inline ComputedAttributeData<Real> AttributeComputation::computeAttributes(const WeightedMorphologicalTree<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
487 return computeAttributes<Real>(tree.asView(), attributes, outputSpace);
488}
489
490template<std::floating_point Real, AltitudeValue T>
491inline ComputedAttributeData<Real> AttributeComputation::computeAttributes(const WeightedTreeView<T>& tree, const std::vector<AttributeOrGroup>& attributes, NodeIdSpace outputSpace) {
492 tree.requireTopologyUnchanged("AttributeComputation::computeAttributes");
494}
495
496template<std::floating_point Real, AltitudeValue T>
499 const std::vector<AttributeOrGroup>& attributes,
500 NodeIdSpace outputSpace) {
501 weighted.requireTopologyUnchanged("AttributeComputation::computeAttributesFromAltitudeSpan");
502 return detail::castComputedAttributeData<Real>(
503 detail::materializeAttributes<double>(weighted.topology(), weighted.altitude(), attributes, outputSpace));
504}
505
506template<std::floating_point Real, AltitudeValue T>
510 std::span<const Real> nodeValues) {
512}
513
514template<std::floating_point Real, AltitudeValue T>
518 const std::vector<Real>& nodeValues) {
519 return projectNodeValuesToExportedHigra<Real>(tree, attrNames, std::span<const Real>(nodeValues));
520}
521
522template<std::floating_point Real, AltitudeValue T>
524 const WeightedTreeView<T>& tree,
526 std::span<const Real> nodeValues) {
527 tree.topology().requireNotEditing("AttributeComputation::projectNodeValuesToExportedHigra");
528 tree.requireTopologyUnchanged("AttributeComputation::projectNodeValuesToExportedHigra");
529 if constexpr (std::is_same_v<Real, double>) {
530 return detail::projectNodeValuesToExportedHigraTyped<double>(
531 tree.topology(),
532 tree.altitude(),
533 attrNames,
534 nodeValues);
535 } else {
536 std::vector<double> internalValues;
537 internalValues.reserve(nodeValues.size());
538 for (const Real value : nodeValues) {
539 internalValues.push_back(static_cast<double>(value));
540 }
541 return detail::castAttributeValues<Real>(
542 detail::projectNodeValuesToExportedHigraTyped<double>(
543 tree.topology(),
544 tree.altitude(),
545 attrNames,
546 std::span<const double>(internalValues)));
547 }
548}
549
550template<std::floating_point Real, AltitudeValue T>
552 const WeightedTreeView<T>& tree,
554 const std::vector<Real>& nodeValues) {
555 return projectNodeValuesToExportedHigra<Real>(tree, attrNames, std::span<const Real>(nodeValues));
556}
557
558template<std::floating_point Real, AltitudeValue T>
560 auto [attrNames, buffer] = AttributeComputation::computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MORPHOLOGICAL_TREE);
561 return detail::mapNodeAttributeToImageCast<Real>(tree.topology(), attrNames, std::span<const double>(buffer), attribute);
562}
563
564template<std::floating_point Real, AltitudeValue T>
566 tree.requireTopologyUnchanged("AttributeComputation::computeAttributeMapping");
567 auto [attrNames, buffer] = AttributeComputation::computeSingleAttribute<double>(tree, attribute, NodeIdSpace::MORPHOLOGICAL_TREE);
568 return detail::mapNodeAttributeToImageCast<Real>(tree.topology(), attrNames, std::span<const double>(buffer), attribute);
569}
570
571} // namespace mmcfilters
typename detail::AltitudeDiffSelector< T >::type AltitudeDiff
Arithmetic result type for altitude differences.
Definition Altitude.hpp:74
int NodeId
Node identifier type used throughout the project.
Definition Common.hpp:17
std::shared_ptr< Image< PixelType > > ImagePtr
Shared pointer alias for an image with arbitrary pixel type.
Definition Image.hpp:253
Public facade for attribute computation.
static ComputedAttributeData< Real > computeSingleAttribute(const WeightedMorphologicalTree< T > &tree, AttributeOrGroup attr, NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes a single scalar attribute or a full attribute group.
static ComputedAttributeData< Real > computeSingleTopologyAttribute(const MorphologicalTree &tree, AttributeOrGroup attr, NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes one topology/support-only scalar attribute or group.
static ComputedAttributeData< Real > computeAttributes(const WeightedMorphologicalTree< T > &tree, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes a heterogeneous set of scalar attributes and attribute groups in one coordinated run.
static ComputedAttributeData< Real > computeTopologyAttributes(const MorphologicalTree &tree, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes several topology/support-only attributes or groups.
static ComputedAttributeDataWithDelta< Real > computeSingleAttributeWithDelta(const WeightedMorphologicalTree< T > &tree, Attribute attribute, AltitudeDiff< T > deltaStep, int radius, std::string padding="last-padding", NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes a delta-augmented version of one scalar attribute.
static ImagePtr< Real > computeAttributeMapping(const WeightedMorphologicalTree< T > &tree, Attribute attribute)
Projects a node attribute to a proper-part image in the original domain.
static std::vector< Real > projectNodeValuesToExportedHigra(const WeightedMorphologicalTree< T > &tree, const AttributeNames &attrNames, std::span< const Real > nodeValues)
Projects an already computed internal-node attribute buffer to the compact Higra layout produced by T...
static ComputedAttributeData< Real > computeAttributesFromAltitudeSpan(const WeightedTreeView< T > &weighted, const std::vector< AttributeOrGroup > &attributes, NodeIdSpace outputSpace=NodeIdSpace::MORPHOLOGICAL_TREE)
Computes attributes over an external altitude span.
Layout object that maps scalar attributes to flat-buffer offsets.
static Ptr create(int rows, int cols)
Creates an owned image with uninitialised pixel values.
Definition Image.hpp:79
Mutable morphological tree built directly on proper parts and dense node ids.
Wrapper pairing MorphologicalTree topology with an external altitude buffer.
Non-owning view pairing a topology with an external altitude span.
Owning result for one delta-augmented attribute layout and buffer.
Owning result for one computed scalar attribute layout and buffer.
NodeIdSpace nodeIdSpace
Node-id domain used by the rows of second.