MorphologicalAttributeFilters
Public API documentation
Loading...
Searching...
No Matches
AttributeFilters.hpp
1#pragma once
2
3#include "../utils/Image.hpp"
4#include "../utils/Common.hpp"
5#include "../trees/TreeAltitudeAlgorithms.hpp"
6#include "../trees/WeightedMorphologicalTree.hpp"
7#include "../trees/WeightedTreeView.hpp"
8#include "../trees/detail/TreeTraversalDetail.hpp"
9#include "DepthStableRegionComputer.hpp"
10#include "MSERComputer.hpp"
11#include "detail/VariationMeasure.hpp"
12#include "detail/ViterbiDecision.hpp"
13
14#include <cassert>
15#include <cmath>
16#include <concepts>
17#include <memory>
18#include <stack>
19#include <stdexcept>
20#include <string>
21#include <vector>
22
23namespace mmcfilters {
24
65template<AltitudeValue T>
67protected:
70
72 const WeightedMorphologicalTree<T>* weighted_ = nullptr;
73 const MorphologicalTree& tree;
74 std::size_t treeMutationVersion_ = 0;
75
76 AltitudeView view() const {
77 return weighted_ != nullptr ? weighted_->asView() : view_;
78 }
79
80 void requireStableTree(const char* context) const {
81 tree.requireMutationVersion(treeMutationVersion_, context);
82 }
83
84 template <std::floating_point Real>
85 static void requireAttributePointer(const Real* attribute, const char* context) {
86 if (attribute == nullptr) {
87 throw std::invalid_argument(std::string(context) + " requires a non-null attribute buffer.");
88 }
89 }
90
91 static void requireCriterionSize(const MorphologicalTree& tree, const std::vector<bool>& criterion, const char* context) {
92 if (criterion.size() != static_cast<std::size_t>(tree.getNumInternalNodeSlots())) {
93 throw std::invalid_argument(std::string(context) + " criterion size must match the internal node slot count.");
94 }
95 }
96
97 static void requireScoreSize(const MorphologicalTree& tree, const std::vector<float>& scores, const char* context) {
98 if (scores.size() != static_cast<std::size_t>(tree.getNumInternalNodeSlots())) {
99 throw std::invalid_argument(std::string(context) + " score size must match the internal node slot count.");
100 }
101 }
102
103 template <typename TImagePtr>
104 static void requireOutputImage(const MorphologicalTree& tree, const TImagePtr& image, const char* context) {
105 if (!image) {
106 throw std::invalid_argument(std::string(context) + " requires a non-null output image.");
107 }
108 if (image->getNumRows() != tree.getNumRowsOfImage() || image->getNumCols() != tree.getNumColsOfImage()) {
109 throw std::invalid_argument(std::string(context) + " output image shape must match the tree image domain.");
110 }
111 }
112
113 static T altitudeOf(const AltitudeView& view, NodeId nodeId) {
114 return view.getAltitude(nodeId);
115 }
116
118 return view.getNodeResidue(nodeId);
119 }
120
129 template <typename TValue>
131 for (int pixel : tree.getProperParts(nodeId)) {
132 output[pixel] = value;
133 }
134 }
135
143 template <typename TValue>
147 }
148 }
149
159 view.requireTopologyUnchanged("AttributeFilters::filteringBySubtractiveScoreRule");
160 const MorphologicalTree& tree = view.topology();
161 requireScoreSize(tree, prob, "AttributeFilters::filteringBySubtractiveScoreRule");
162 requireOutputImage(tree, imgOutputPtr, "AttributeFilters::filteringBySubtractiveScoreRule");
163 std::unique_ptr<float[]> mapLevel(new float[tree.getNumInternalNodeSlots()]);
164
165 const NodeId rootNodeId = tree.getRoot();
166 mapLevel[rootNodeId] = static_cast<float>(altitudeOf(view, rootNodeId));
167
168 // Parent filtered levels must be available before children are visited.
169 // `getAliveNodeIds()` is slot-order, not tree-order, so use an explicit
170 // top-down traversal that is valid for image-built and Higra-imported trees.
171 std::stack<NodeId> stack;
172 stack.push(rootNodeId);
173 while (!stack.empty()) {
174 const NodeId nodeId = stack.top();
175 stack.pop();
176 for (NodeId childNodeId : tree.getChildren(nodeId)) {
178 mapLevel[nodeId] + (static_cast<float>(residueOf(view, childNodeId)) * prob[childNodeId]);
179 stack.push(childNodeId);
180 }
181 }
182
183 auto imgOutput = imgOutputPtr->rawData();
184 for (NodeId nodeId : tree.getAliveNodeIds()) {
186 }
187 }
188
197 const char* context = "AttributeFilters::filteringBySubtractiveRule";
198 view.requireTopologyUnchanged(context);
199 const MorphologicalTree& tree = view.topology();
202 std::vector<AltitudeDiff<T>> mapLevel(static_cast<std::size_t>(tree.getNumInternalNodeSlots()));
203 const NodeId rootNodeId = tree.getRoot();
205
206 // The parent level in `mapLevel` is the already-filtered level, not the
207 // original altitude. This makes traversal order part of the algorithm.
208 std::stack<NodeId> stack;
209 stack.push(rootNodeId);
210 while (!stack.empty()) {
211 const NodeId nodeId = stack.top();
212 stack.pop();
213 for (NodeId childNodeId : tree.getChildren(nodeId)) {
216 : mapLevel[nodeId];
217 stack.push(childNodeId);
218 }
219 }
220
221 auto imgOutput = imgOutputPtr->rawData();
222 for (NodeId nodeId : tree.getAliveNodeIds()) {
223 writeProperParts(tree, nodeId, imgOutput, static_cast<T>(mapLevel[nodeId]));
224 }
225 }
226
235 const char* context = "AttributeFilters::filteringByDirectRule";
236 view.requireTopologyUnchanged(context);
237 const MorphologicalTree& tree = view.topology();
240 std::vector<T> mapLevel(static_cast<std::size_t>(tree.getNumInternalNodeSlots()));
241 const NodeId rootNodeId = tree.getRoot();
243
244 // Direct filtering is path-local. Traverse root-to-leaf so every child
245 // sees the filtered level chosen for its parent.
246 std::stack<NodeId> stack;
247 stack.push(rootNodeId);
248 while (!stack.empty()) {
249 const NodeId nodeId = stack.top();
250 stack.pop();
251 for (NodeId childNodeId : tree.getChildren(nodeId)) {
253 stack.push(childNodeId);
254 }
255 }
256
257 auto imgOutput = imgOutputPtr->rawData();
258 for (NodeId nodeId : tree.getAliveNodeIds()) {
260 }
261 }
262
272 const char* context = "AttributeFilters::filteringByPruningMin";
273 view.requireTopologyUnchanged(context);
274 const MorphologicalTree& tree = view.topology();
277 std::stack<NodeId> stack;
278 stack.push(tree.getRoot());
279 auto imgOutput = imgOutputPtr->rawData();
280
281 while (!stack.empty()) {
282 const NodeId nodeId = stack.top();
283 stack.pop();
285 for (NodeId childNodeId : tree.getChildren(nodeId)) {
286 if (criterion[childNodeId]) {
287 stack.push(childNodeId);
288 } else {
290 }
291 }
292 }
293 }
294
304 const char* context = "AttributeFilters::filteringByPruningMax";
305 view.requireTopologyUnchanged(context);
306 const MorphologicalTree& tree = view.topology();
309 // Internal `criterion` means "this whole subtree can be collapsed",
310 // which is the opposite of the caller's keep criterion at the leaves
311 // before descendant information is merged.
312 std::vector<uint8_t> criterion(tree.getNumInternalNodeSlots(), false);
313 detail::traversePostOrder(
314 tree,
315 tree.getRoot(),
316 [&criterion, &keepCriterion](NodeId nodeId) -> void {
317 criterion[nodeId] = !keepCriterion[nodeId];
318 },
320 criterion[parentNodeId] = (criterion[parentNodeId] & criterion[childNodeId]);
321 },
322 [](NodeId) -> void {});
323
324 auto imgOutput = imgOutputPtr->rawData();
325 std::stack<NodeId> stack;
326 stack.push(tree.getRoot());
327 while (!stack.empty()) {
328 const NodeId nodeId = stack.top();
329 stack.pop();
331 for (NodeId childNodeId : tree.getChildren(nodeId)) {
332 if (!criterion[childNodeId]) {
333 stack.push(childNodeId);
334 } else {
336 }
337 }
338 }
339 }
340
349 template <std::floating_point Real>
351 const char* context = "AttributeFilters::filteringByPruningMin";
352 view.requireTopologyUnchanged(context);
353 const MorphologicalTree& tree = view.topology();
356 auto imgOutput = imgOutputPtr->rawData();
357 std::stack<NodeId> stack;
358 stack.push(tree.getRoot());
359 while (!stack.empty()) {
360 const NodeId nodeId = stack.top();
361 stack.pop();
363 for (NodeId childNodeId : tree.getChildren(nodeId)) {
364 if (attribute[childNodeId] > threshold) {
365 stack.push(childNodeId);
366 } else {
368 }
369 }
370 }
371 }
372
380 template <std::floating_point Real>
382 const char* context = "AttributeFilters::filteringByPruningMax";
383 view.requireTopologyUnchanged(context);
384 const MorphologicalTree& tree = view.topology();
387 // Internal `criterion` records collapsible rejected subtrees, not a
388 // direct keep decision. The post-order merge implements the universal
389 // quantifier over descendants.
390 std::vector<uint8_t> criterion(tree.getNumInternalNodeSlots(), false);
391 detail::traversePostOrder(
392 tree,
393 tree.getRoot(),
394 [&criterion, attribute, threshold](NodeId nodeId) -> void {
395 if (attribute[nodeId] <= threshold) {
396 criterion[nodeId] = true;
397 }
398 },
401 },
402 [](NodeId) -> void {});
403
404 auto imgOutput = imgOutputPtr->rawData();
405 std::stack<NodeId> stack;
406 stack.push(tree.getRoot());
407 while (!stack.empty()) {
408 const NodeId nodeId = stack.top();
409 stack.pop();
411 for (NodeId childNodeId : tree.getChildren(nodeId)) {
412 if (!criterion[childNodeId]) {
413 stack.push(childNodeId);
414 } else {
416 }
417 }
418 }
419 }
420
421 template <std::floating_point Real, class StabilityComputer>
422 static std::vector<bool> adaptiveCriterionFromAttributeStability(
423 const MorphologicalTree& tree,
424 const Real* attribute,
427 const char* context) {
429 const std::vector<Real>& variation = stabilityComputer.getVariations();
430 std::vector<bool> isPruned(tree.getNumInternalNodeSlots(), false);
431 for (NodeId nodeId : tree.getAliveNodeIds()) {
432 if (attribute[nodeId] < threshold) {
433 // Lower finite variation values are more stable. If the center
434 // has no complete stability window, keep the
435 // historical fallback and prune the rejected node itself.
436 if (!detail::isFiniteVariation(variation[static_cast<std::size_t>(nodeId)])) {
437 isPruned[nodeId] = true;
438 } else {
439 isPruned[stabilityComputer.nodeWithMinimumVariationInWindow(nodeId)] = true;
440 }
441 }
442 }
443 return isPruned;
444 }
445
446 template <std::floating_point Real, class StabilityComputer>
447 static std::vector<bool> adaptiveCriterionFromMaskStability(
448 const MorphologicalTree& tree,
449 std::vector<bool>& criterion,
450 StabilityComputer& stabilityComputer,
451 const char* context) {
452 requireCriterionSize(tree, criterion, context);
453 const std::vector<Real>& variation = stabilityComputer.getVariations();
454 std::vector<bool> isPruned(tree.getNumInternalNodeSlots(), false);
455 for (NodeId nodeId : tree.getAliveNodeIds()) {
456 if (!criterion[nodeId]) {
457 // `criterion == false` marks an attribute rejection. The variation
458 // comparison moves the actual pruning decision to the locally
459 // smallest finite variation on the ancestor/descendant window.
460 if (!detail::isFiniteVariation(variation[static_cast<std::size_t>(nodeId)])) {
461 isPruned[nodeId] = true;
462 } else {
463 isPruned[stabilityComputer.nodeWithMinimumVariationInWindow(nodeId)] = true;
464 }
465 }
466 }
467 return isPruned;
468 }
469
470 template <std::floating_point Real>
471 static std::vector<bool> getAdaptiveCriterionImpl(const WeightedMorphologicalTree<T>& weighted, const Real* attribute, Real threshold, AltitudeDiff<T> delta) {
472 const MorphologicalTree& tree = weighted.topology();
473 MSERComputer<T, Real> mser(weighted);
474 (void)mser.computeMSER(delta);
475 return adaptiveCriterionFromAttributeStability<Real>(
476 tree,
477 attribute,
478 threshold,
479 mser,
480 "AttributeFilters::getAdaptiveCriterion");
481 }
482
483 static std::vector<bool> getAdaptiveCriterionImpl(const WeightedMorphologicalTree<T>& weighted, std::vector<bool>& criterion, AltitudeDiff<T> delta) {
484 const MorphologicalTree& tree = weighted.topology();
485 MSERComputer<T> mser(weighted);
486 (void)mser.computeMSER(delta);
487 return adaptiveCriterionFromMaskStability<float>(
488 tree,
489 criterion,
490 mser,
491 "AttributeFilters::getAdaptiveCriterion");
492 }
493
494 template <std::floating_point Real>
495 static std::vector<bool> getAdaptiveCriterionByDepthImpl(const MorphologicalTree& tree, const Real* attribute, Real threshold, int depthDelta) {
496 DepthStableRegionComputer<Real> stabilityComputer(tree);
497 (void)stabilityComputer.computeByDepth(depthDelta);
498 return adaptiveCriterionFromAttributeStability<Real>(
499 tree,
500 attribute,
501 threshold,
502 stabilityComputer,
503 "AttributeFilters::getAdaptiveCriterionByDepth");
504 }
505
506 static std::vector<bool> getAdaptiveCriterionByDepthImpl(const MorphologicalTree& tree, std::vector<bool>& criterion, int depthDelta) {
507 DepthStableRegionComputer<float> stabilityComputer(tree);
508 (void)stabilityComputer.computeByDepth(depthDelta);
509 return adaptiveCriterionFromMaskStability<float>(
510 tree,
511 criterion,
512 stabilityComputer,
513 "AttributeFilters::getAdaptiveCriterionByDepth");
514 }
516
517public:
525 : view_{view},
526 tree{view_.topology()},
527 treeMutationVersion_{tree.getMutationVersion()} {
528 view_.requireTopologyUnchanged("AttributeFilters");
529 }
530
539 : AttributeFilters(weighted.asView()) {
540 weighted_ = &weighted;
541 }
542
543 ~AttributeFilters() = default;
544
553 [[nodiscard]] std::vector<bool> getAdaptiveCriterion(std::vector<bool>& criterion, AltitudeDiff<T> delta) {
554 requireStableTree("AttributeFilters::getAdaptiveCriterion");
555 if (weighted_ == nullptr) {
556 throw std::logic_error("AttributeFilters::getAdaptiveCriterion requires a WeightedMorphologicalTree owner because MSER uses the tree-owned altitude.");
557 }
558 return AttributeFilters::getAdaptiveCriterionImpl(*weighted_, criterion, delta);
559 }
560
568 [[nodiscard]] std::vector<bool> getAdaptiveCriterionByDepth(std::vector<bool>& criterion, int depthDelta) {
569 requireStableTree("AttributeFilters::getAdaptiveCriterionByDepth");
570 return AttributeFilters::getAdaptiveCriterionByDepthImpl(this->tree, criterion, depthDelta);
571 }
572
580 template <std::floating_point Real>
581 [[nodiscard]] ImagePtr<T> filteringByPruningMin(const std::shared_ptr<Real[]>& attr, Real threshold) {
582 return filteringByPruningMin(attr.get(), threshold);
583 }
584
588 template <std::floating_point Real>
590 requireStableTree("AttributeFilters::filteringByPruningMin");
591 assert(attr != nullptr);
592 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
594 return imgOutput;
595 }
596
603 template <std::floating_point Real>
604 [[nodiscard]] ImagePtr<T> filteringByPruningMax(const std::shared_ptr<Real[]>& attr, Real threshold) {
605 return filteringByPruningMax(attr.get(), threshold);
606 }
607
611 template <std::floating_point Real>
613 requireStableTree("AttributeFilters::filteringByPruningMax");
614 assert(attr != nullptr);
615 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
617 return imgOutput;
618 }
619
630 template <std::floating_point Real>
632 requireStableTree("AttributeFilters::filteringByViterbiRule");
633 auto costs = detail::makeThresholdViterbiCosts(tree, attr, threshold);
634 std::vector<bool> criterion = detail::computeViterbiKeepCriterion(tree, costs);
635
636 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
638 return imgOutput;
639 }
640
645 requireStableTree("AttributeFilters::filteringByPruningMin");
646 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
648 return imgOutput;
649 }
650
655 requireStableTree("AttributeFilters::filteringByPruningMax");
656 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
658 return imgOutput;
659 }
660
668 requireStableTree("AttributeFilters::filteringByDirectRule");
669 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
671 return imgOutput;
672 }
673
681 requireStableTree("AttributeFilters::filteringBySubtractiveRule");
682 ImagePtr<T> imgOutput = Image<T>::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
684 return imgOutput;
685 }
686
694 requireStableTree("AttributeFilters::filteringBySubtractiveScoreRule");
695 ImageFloatPtr imgOutput = ImageFloat::create(this->tree.getNumRowsOfImage(), this->tree.getNumColsOfImage());
697 return imgOutput;
698 }
699
706
711 filteringBySubtractiveScoreRule(weighted.asView(), prob, imgOutputPtr);
712 }
713
720
725 filteringBySubtractiveRule(weighted.asView(), criterion, imgOutputPtr);
726 }
727
734
739 filteringByDirectRule(weighted.asView(), criterion, imgOutputPtr);
740 }
741
748
753 filteringByPruningMin(weighted.asView(), criterion, imgOutputPtr);
754 }
755
762
767 filteringByPruningMax(weighted.asView(), criterion, imgOutputPtr);
768 }
769
773 template <std::floating_point Real>
774 static void filteringByPruningMin(const WeightedTreeView<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, ImagePtr<T> imgOutputPtr) {
775 filteringByPruningMin(weighted, attribute.get(), threshold, imgOutputPtr);
776 }
777
781 template <std::floating_point Real>
782 static void filteringByPruningMin(const WeightedMorphologicalTree<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, ImagePtr<T> imgOutputPtr) {
783 filteringByPruningMin(weighted.asView(), attribute.get(), threshold, imgOutputPtr);
784 }
785
789 template <std::floating_point Real>
793
797 template <std::floating_point Real>
799 filteringByPruningMin(weighted.asView(), attribute, threshold, imgOutputPtr);
800 }
801
805 template <std::floating_point Real>
806 static void filteringByPruningMax(const WeightedTreeView<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, ImagePtr<T> imgOutputPtr) {
807 filteringByPruningMax(weighted, attribute.get(), threshold, imgOutputPtr);
808 }
809
813 template <std::floating_point Real>
814 static void filteringByPruningMax(const WeightedMorphologicalTree<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, ImagePtr<T> imgOutputPtr) {
815 filteringByPruningMax(weighted.asView(), attribute.get(), threshold, imgOutputPtr);
816 }
817
821 template <std::floating_point Real>
825
829 template <std::floating_point Real>
831 filteringByPruningMax(weighted.asView(), attribute, threshold, imgOutputPtr);
832 }
833
837 template <std::floating_point Real>
838 [[nodiscard]] static std::vector<bool> getAdaptiveCriterion(const WeightedMorphologicalTree<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, AltitudeDiff<T> delta) {
839 return getAdaptiveCriterionImpl(weighted, attribute.get(), threshold, delta);
840 }
841
845 template <std::floating_point Real>
846 [[nodiscard]] static std::vector<bool> getAdaptiveCriterion(const WeightedMorphologicalTree<T>& weighted, const Real* attribute, Real threshold, AltitudeDiff<T> delta) {
847 return getAdaptiveCriterionImpl(weighted, attribute, threshold, delta);
848 }
849
853 [[nodiscard]] static std::vector<bool> getAdaptiveCriterion(const WeightedMorphologicalTree<T>& weighted, std::vector<bool>& criterion, AltitudeDiff<T> delta) {
855 }
856
860 template <std::floating_point Real>
861 [[nodiscard]] static std::vector<bool> getAdaptiveCriterionByDepth(const WeightedMorphologicalTree<T>& weighted, const std::shared_ptr<Real[]>& attribute, Real threshold, int depthDelta) {
862 return getAdaptiveCriterionByDepthImpl(weighted.topology(), attribute.get(), threshold, depthDelta);
863 }
864
868 template <std::floating_point Real>
869 [[nodiscard]] static std::vector<bool> getAdaptiveCriterionByDepth(const WeightedMorphologicalTree<T>& weighted, const Real* attribute, Real threshold, int depthDelta) {
870 return getAdaptiveCriterionByDepthImpl(weighted.topology(), attribute, threshold, depthDelta);
871 }
872
876 [[nodiscard]] static std::vector<bool> getAdaptiveCriterionByDepth(const WeightedMorphologicalTree<T>& weighted, std::vector<bool>& criterion, int depthDelta) {
878 }
879};
880
881
882} // namespace mmcfilters
std::shared_ptr< ImageFloat > ImageFloatPtr
Shared pointer to a single-precision floating-point image.
Definition Image.hpp:247
Family of attribute-based image filtering operators on morphological trees.
static void filteringByPruningMin(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from a weighted owner into an output image.
static void filteringByDirectRule(const WeightedTreeView< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes direct-rule filtering into a caller-owned output image.
static void filteringByPruningMax(const WeightedTreeView< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from an owned attribute buffer into an output image.
static void filteringByPruningMax(const WeightedMorphologicalTree< T > &weighted, const Real *attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from a weighted owner and raw attribute buffer.
static void filteringByPruningMin(const WeightedTreeView< T > &weighted, const Real *attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from a raw attribute buffer into an output image.
static void filteringByPruningMax(const WeightedTreeView< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from a criterion into an output image.
AttributeFilters(const WeightedMorphologicalTree< T > &weighted)
Creates filtering operators over an owned weighted tree.
static void filteringByPruningMax(const WeightedMorphologicalTree< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from a weighted owner and owned attribute buffer.
static std::vector< bool > getAdaptiveCriterion(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, AltitudeDiff< T > delta)
Builds an MSER-assisted pruning criterion from an existing criterion mask.
static std::vector< bool > getAdaptiveCriterionByDepth(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, int depthDelta)
Builds a depth-stability pruning criterion from an existing criterion mask.
ImagePtr< T > filteringByPruningMax(std::vector< bool > &criterion)
Applies pruning-max filtering from a dense internal-node criterion.
static void filteringByDirectRule(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes direct-rule filtering from a weighted owner into an output image.
static void filteringByPruningMax(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from a weighted owner into an output image.
static std::vector< bool > getAdaptiveCriterion(const WeightedMorphologicalTree< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, AltitudeDiff< T > delta)
Builds an MSER-assisted pruning criterion from an attribute threshold.
std::vector< bool > getAdaptiveCriterion(std::vector< bool > &criterion, AltitudeDiff< T > delta)
Builds an MSER-assisted pruning criterion from an existing keep/reject mask.
ImagePtr< T > filteringByViterbiRule(const Real *attr, Real threshold)
Applies Salembier-style Viterbi filtering from a raw attribute buffer.
std::vector< bool > getAdaptiveCriterionByDepth(std::vector< bool > &criterion, int depthDelta)
Builds a depth-stability pruning criterion from an existing mask.
static void filteringBySubtractiveRule(const WeightedMorphologicalTree< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes subtractive-rule filtering from a weighted owner into an output image.
AttributeFilters(AltitudeView view)
Creates filtering operators over a non-owning weighted tree view.
ImagePtr< T > filteringByPruningMin(std::vector< bool > &criterion)
Applies pruning-min filtering from a dense internal-node criterion.
static void filteringByPruningMax(const WeightedTreeView< T > &weighted, const Real *attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-max filtering from a raw attribute buffer into an output image.
static void filteringByPruningMin(const WeightedMorphologicalTree< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from a weighted owner and owned attribute buffer.
static std::vector< bool > getAdaptiveCriterionByDepth(const WeightedMorphologicalTree< T > &weighted, const Real *attribute, Real threshold, int depthDelta)
Builds a depth-stability pruning criterion from a raw attribute buffer.
ImageFloatPtr filteringBySubtractiveScoreRule(std::vector< float > &prob)
Applies the subtractive score rule from dense per-node scores.
static std::vector< bool > getAdaptiveCriterionByDepth(const WeightedMorphologicalTree< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, int depthDelta)
Builds a depth-stability pruning criterion from an attribute threshold.
static void filteringByPruningMin(const WeightedTreeView< T > &weighted, const std::shared_ptr< Real[]> &attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from an owned attribute buffer into an output image.
ImagePtr< T > filteringByPruningMin(const std::shared_ptr< Real[]> &attr, Real threshold)
Applies pruning-min filtering from an attribute buffer.
ImagePtr< T > filteringByPruningMax(const Real *attr, Real threshold)
Applies pruning-max filtering from a raw internal-node attribute buffer.
static void filteringBySubtractiveRule(const WeightedTreeView< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes subtractive-rule filtering into a caller-owned output image.
static void filteringBySubtractiveScoreRule(const WeightedTreeView< T > &weighted, std::vector< float > &prob, ImageFloatPtr imgOutputPtr)
Writes subtractive-score filtering into a caller-owned output image.
static void filteringBySubtractiveScoreRule(const WeightedMorphologicalTree< T > &weighted, std::vector< float > &prob, ImageFloatPtr imgOutputPtr)
Writes subtractive-score filtering from a weighted owner into an output image.
static void filteringByPruningMin(const WeightedTreeView< T > &weighted, std::vector< bool > &criterion, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from a criterion into an output image.
ImagePtr< T > filteringByPruningMin(const Real *attr, Real threshold)
Applies pruning-min filtering from a raw internal-node attribute buffer.
ImagePtr< T > filteringByPruningMax(const std::shared_ptr< Real[]> &attr, Real threshold)
Applies pruning-max filtering from an attribute buffer.
static std::vector< bool > getAdaptiveCriterion(const WeightedMorphologicalTree< T > &weighted, const Real *attribute, Real threshold, AltitudeDiff< T > delta)
Builds an MSER-assisted pruning criterion from a raw attribute buffer.
static void filteringByPruningMin(const WeightedMorphologicalTree< T > &weighted, const Real *attribute, Real threshold, ImagePtr< T > imgOutputPtr)
Writes pruning-min filtering from a weighted owner and raw attribute buffer.
ImagePtr< T > filteringBySubtractiveRule(std::vector< bool > &criterion)
Applies the subtractive filtering rule from a dense internal-node criterion.
ImagePtr< T > filteringByDirectRule(std::vector< bool > &criterion)
Applies the direct filtering rule from a dense internal-node criterion.
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.
ChildrenRange getChildren(NodeId nodeId) const
Returns a fail-fast range over the direct children of nodeId.
void requireMutationVersion(std::size_t expectedVersion, const char *context) const
Rejects stale read-only views that captured an older mutation version.
int getNumInternalNodeSlots() const
Returns the size of the dense internal-node id domain.
SubtreeNodeRange getNodeSubtree(NodeId nodeId) const
Returns a pre-order traversal range over the subtree of nodeId.
NodeId getRoot() const
Returns the current hierarchy root.
ProperPartsRange getProperParts(NodeId nodeId) const
Returns a fail-fast range over the direct proper parts of nodeId.
int getNumColsOfImage() const
Returns the number of image columns in the attached 2D domain.
AliveNodeRange getAliveNodeIds() const
Returns a fail-fast range over all live node ids.
int getNumRowsOfImage() const
Returns the number of image rows in the attached 2D domain.
Owning result for one computed scalar attribute layout and buffer.