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"
64 template <std::
floating_po
int Real =
float>
78 template <std::
floating_po
int Real =
float>
90 template<std::
floating_po
int Real =
float, AltitudeValue T>
104 template<std::
floating_po
int Real =
float, AltitudeValue T>
116 template<std::
floating_po
int Real =
float, AltitudeValue T>
130 template<std::
floating_po
int Real =
float, AltitudeValue T>
145 template<std::
floating_po
int Real =
float, AltitudeValue T>
159 template<std::
floating_po
int Real =
float, AltitudeValue T>
176 template<std::
floating_po
int Real =
float, AltitudeValue T>
193 template<std::
floating_po
int Real =
float, AltitudeValue T>
211 template<std::
floating_po
int Real =
float, AltitudeValue T>
225 template<std::
floating_po
int Real =
float, AltitudeValue T>
243 template<std::
floating_po
int Real =
float, AltitudeValue T>
264 template<std::
floating_po
int Real =
float, AltitudeValue T>
276 template<std::
floating_po
int Real =
float, AltitudeValue T>
288 template<std::
floating_po
int Real =
float, AltitudeValue T>
300 template<std::
floating_po
int Real =
float, AltitudeValue T>
311 template<std::
floating_po
int Real =
float, AltitudeValue T>
322 template<std::
floating_po
int Real =
float, AltitudeValue T>
331#include "../attributes/detail/AttributeDeltaMaterialization.hpp"
332#include "../attributes/detail/AttributePipeline.hpp"
333#include "../attributes/detail/AttributeProjection.hpp"
337namespace mmcfilters {
341template<std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
342[[nodiscard]]
inline ComputedAttributeData<OutputReal> castComputedAttributeData(ComputedAttributeData<InternalReal> computed) {
343 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
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));
351 return ComputedAttributeData<OutputReal>{
352 std::move(computed.first),
358template<std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
359[[nodiscard]]
inline ComputedAttributeDataWithDelta<OutputReal> castComputedAttributeDataWithDelta(ComputedAttributeDataWithDelta<InternalReal> computed) {
360 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
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));
368 return ComputedAttributeDataWithDelta<OutputReal>{
369 std::move(computed.first),
375template<std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
376[[nodiscard]]
inline std::vector<OutputReal> castAttributeValues(std::vector<InternalReal> values) {
377 if constexpr (std::is_same_v<OutputReal, InternalReal>) {
380 std::vector<OutputReal> output;
381 output.reserve(values.size());
382 for (
const InternalReal value : values) {
383 output.push_back(
static_cast<OutputReal
>(value));
389template<std::
floating_po
int OutputReal, std::
floating_po
int InternalReal>
390[[nodiscard]]
inline ImagePtr<OutputReal> mapNodeAttributeToImageCast(
391 const MorphologicalTree& tree,
392 const AttributeNames& attrNames,
393 std::span<const InternalReal> nodeValues,
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)]);
407template <std::
floating_po
int Real>
409 return detail::castComputedAttributeData<Real>(
413template <std::
floating_po
int Real>
415 return detail::castComputedAttributeData<Real>(
416 detail::materializeAttributesWithoutAltitude<double>(tree, attributes,
outputSpace));
419template<std::
floating_po
int Real, AltitudeValue T>
424template<std::
floating_po
int Real, AltitudeValue T>
426 tree.requireTopologyUnchanged(
"AttributeComputation::computeSingleTopologyAttribute");
427 return detail::castComputedAttributeData<Real>(
428 detail::materializeTopologyAttributeRequest<double>(
432 detail::DependencyMapT<double>{},
436template<std::
floating_po
int Real, AltitudeValue T>
441template<std::
floating_po
int Real, AltitudeValue T>
443 tree.requireTopologyUnchanged(
"AttributeComputation::computeTopologyAttributes");
444 return detail::castComputedAttributeData<Real>(
445 detail::materializeTopologyAttributeRequest<double>(
449 detail::DependencyMapT<double>{},
453template<std::
floating_po
int Real, AltitudeValue T>
458template<std::
floating_po
int Real, AltitudeValue T>
463template<std::
floating_po
int Real, AltitudeValue T>
468template<std::
floating_po
int Real, AltitudeValue T>
470 tree.requireTopologyUnchanged(
"AttributeComputation::computeSingleAttributeWithDelta");
473 return detail::castComputedAttributeDataWithDelta<Real>(
474 detail::materializeSingleAttributeWithTypedDelta<double>(
485template<std::
floating_po
int Real, AltitudeValue T>
490template<std::
floating_po
int Real, AltitudeValue T>
492 tree.requireTopologyUnchanged(
"AttributeComputation::computeAttributes");
496template<std::
floating_po
int Real, AltitudeValue T>
499 const std::vector<AttributeOrGroup>& attributes,
501 weighted.requireTopologyUnchanged(
"AttributeComputation::computeAttributesFromAltitudeSpan");
502 return detail::castComputedAttributeData<Real>(
506template<std::
floating_po
int Real, AltitudeValue T>
514template<std::
floating_po
int Real, AltitudeValue T>
522template<std::
floating_po
int Real, AltitudeValue T>
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>(
541 return detail::castAttributeValues<Real>(
542 detail::projectNodeValuesToExportedHigraTyped<double>(
550template<std::
floating_po
int Real, AltitudeValue T>
558template<std::
floating_po
int 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);
564template<std::
floating_po
int 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);
typename detail::AltitudeDiffSelector< T >::type AltitudeDiff
Arithmetic result type for altitude differences.
int NodeId
Node identifier type used throughout the project.
std::shared_ptr< Image< PixelType > > ImagePtr
Shared pointer alias for an image with arbitrary pixel type.
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.
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.