40 #ifndef VIGRA_GRAPH_ALGORITHMS_HXX 41 #define VIGRA_GRAPH_ALGORITHMS_HXX 52 #include "graph_generalization.hxx" 53 #include "multi_gridgraph.hxx" 54 #include "priority_queue.hxx" 55 #include "union_find.hxx" 56 #include "adjacency_list_graph.hxx" 57 #include "graph_maps.hxx" 63 #include "functorexpression.hxx" 64 #include "array_vector.hxx" 72 namespace detail_graph_algorithms{
73 template <
class GRAPH_MAP,
class COMPERATOR>
74 struct GraphItemCompare
77 GraphItemCompare(
const GRAPH_MAP & map,
const COMPERATOR & comperator)
79 comperator_(comperator){
84 bool operator()(
const KEY & a,
const KEY & b)
const{
85 return comperator_(map_[a],map_[b]);
88 const GRAPH_MAP & map_;
89 const COMPERATOR & comperator_;
97 template<
class GRAPH,
class WEIGHTS,
class COMPERATOR>
100 const WEIGHTS & weights,
101 const COMPERATOR & comperator,
102 std::vector<typename GRAPH::Edge> & sortedEdges
104 sortedEdges.resize(g.edgeNum());
106 for(
typename GRAPH::EdgeIt e(g);e!=lemon::INVALID;++e){
110 detail_graph_algorithms::GraphItemCompare<WEIGHTS,COMPERATOR> edgeComperator(weights,comperator);
111 std::sort(sortedEdges.begin(),sortedEdges.end(),edgeComperator);
116 template<
class G,
class A,
class B>
118 typename G::NodeIt iter(g);
119 while(iter!=lemon::INVALID){
126 template<
class G,
class A,
class B>
128 typename G::EdgeIt iter(g);
129 while(iter!=lemon::INVALID){
135 template<
class G,
class A,
class T>
137 typename G::NodeIt iter(g);
138 while(iter!=lemon::INVALID){
144 template<
class G,
class A,
class T>
146 typename G::EdgeIt iter(g);
147 while(iter!=lemon::INVALID){
163 class GRAPH_IN_NODE_LABEL_MAP
167 GRAPH_IN_NODE_LABEL_MAP labels,
169 typename AdjacencyListGraph:: template EdgeMap< std::vector<typename GRAPH_IN::Edge> > & affiliatedEdges,
170 const Int64 ignoreLabel=-1
173 typedef typename GraphMapTypeTraits<GRAPH_IN_NODE_LABEL_MAP>::Value LabelType;
174 typedef GRAPH_IN GraphIn;
177 typedef typename GraphIn::Edge EdgeGraphIn;
178 typedef typename GraphIn::NodeIt NodeItGraphIn;
179 typedef typename GraphIn::EdgeIt EdgeItGraphIn;
180 typedef typename GraphOut::Edge EdgeGraphOut;
183 for(NodeItGraphIn iter(graphIn);iter!=lemon::INVALID;++iter){
184 const LabelType l=labels[*iter];
185 if(ignoreLabel==-1 || static_cast<Int64>(l)!=ignoreLabel)
189 for(EdgeItGraphIn e(graphIn);e!=lemon::INVALID;++e){
190 const EdgeGraphIn
edge(*e);
191 const LabelType lu = labels[graphIn.u(edge)];
192 const LabelType lv = labels[graphIn.v(edge)];
193 if( lu!=lv && ( ignoreLabel==-1 || (static_cast<Int64>(lu)!=ignoreLabel && static_cast<Int64>(lv)!=ignoreLabel) ) ){
200 affiliatedEdges.assign(rag);
201 for(EdgeItGraphIn e(graphIn);e!=lemon::INVALID;++e){
202 const EdgeGraphIn
edge(*e);
203 const LabelType lu = labels[graphIn.u(edge)];
204 const LabelType lv = labels[graphIn.v(edge)];
206 if( lu!=lv && ( ignoreLabel==-1 || (static_cast<Int64>(lu)!=ignoreLabel && static_cast<Int64>(lv)!=ignoreLabel) ) ){
210 affiliatedEdges[ragEdge].push_back(edge);
216 template<
unsigned int DIM,
class DTAG,
class AFF_EDGES>
217 size_t affiliatedEdgesSerializationSize(
220 const AFF_EDGES & affEdges
227 for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
230 size+=affEdges[e].size()*(DIM+1);
235 template<
class OUT_ITER,
unsigned int DIM,
class DTAG,
class AFF_EDGES>
236 void serializeAffiliatedEdges(
239 const AFF_EDGES & affEdges,
247 for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
249 const Edge
edge = *iter;
250 const size_t numAffEdge = affEdges[
edge].size();
251 *outIter = numAffEdge; ++outIter;
253 for(
size_t i=0; i<numAffEdge; ++i){
254 const GEdge gEdge = affEdges[
edge][i];
255 for(
size_t d=0; d<DIM+1; ++d){
256 *outIter = gEdge[d]; ++outIter;
262 template<
class IN_ITER,
unsigned int DIM,
class DTAG,
class AFF_EDGES>
263 void deserializeAffiliatedEdges(
266 AFF_EDGES & affEdges,
275 affEdges.assign(rag);
277 for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
279 const Edge
edge = *iter;
280 const size_t numAffEdge = *begin; ++begin;
282 for(
size_t i=0; i<numAffEdge; ++i){
284 for(
size_t d=0; d<DIM+1; ++d){
285 gEdge[d]=*begin; ++begin;
287 affEdges[
edge].push_back(gEdge);
296 template<
class GRAPH,
class WEIGHT_TYPE>
301 typedef typename Graph::Node Node;
302 typedef typename Graph::NodeIt NodeIt;
303 typedef typename Graph::Edge Edge;
304 typedef typename Graph::OutArcIt OutArcIt;
306 typedef WEIGHT_TYPE WeightType;
308 typedef typename Graph:: template NodeMap<Node> PredecessorsMap;
309 typedef typename Graph:: template NodeMap<WeightType> DistanceMap;
315 pq_(g.maxNodeId()+1),
333 template<
class WEIGHTS>
335 const Node &
target = lemon::INVALID,
336 WeightType maxDistance=NumericTraits<WeightType>::max())
338 this->initializeMaps(source);
339 runImpl(weights,
target, maxDistance);
355 template<
class WEIGHTS>
356 void run(Node
const & start, Node
const & stop,
357 const WEIGHTS & weights,
const Node & source,
358 const Node &
target = lemon::INVALID,
359 WeightType maxDistance=NumericTraits<WeightType>::max())
362 "ShortestPathDijkstra::run(): source is not within ROI");
363 vigra_precondition(
target == lemon::INVALID ||
365 "ShortestPathDijkstra::run(): target is not within ROI");
366 this->initializeMaps(source, start, stop);
367 runImpl(weights,
target, maxDistance);
376 template<
class WEIGHTS>
377 void reRun(
const WEIGHTS & weights,
const Node & source,
378 const Node &
target = lemon::INVALID,
379 WeightType maxDistance=NumericTraits<WeightType>::max())
381 this->reInitializeMaps(source);
382 runImpl(weights,
target, maxDistance);
389 template<
class WEIGHTS,
class ITER>
392 const Node &
target = lemon::INVALID,
393 WeightType maxDistance=NumericTraits<WeightType>::max())
395 this->initializeMapsMultiSource(source_begin, source_end);
396 runImpl(weights,
target, maxDistance);
404 template<
class EFGE_WEIGHTS,
class NODE_WEIGHTS,
class ITER>
407 const EFGE_WEIGHTS & edgeWeights,
408 const NODE_WEIGHTS & nodeWeights,
411 const Node &
target = lemon::INVALID,
412 WeightType maxDistance = NumericTraits<WeightType>::max())
414 this->initializeMapsMultiSource(source_begin, source_end);
415 runImplWithNodeWeights(edgeWeights, nodeWeights,
target, maxDistance);
433 return target_!=lemon::INVALID;
438 return discoveryOrder_;
459 template<
class WEIGHTS>
460 void runImpl(
const WEIGHTS & weights,
461 const Node &
target = lemon::INVALID,
462 WeightType maxDistance=NumericTraits<WeightType>::max())
464 ZeroNodeMap<Graph, WEIGHT_TYPE> zeroNodeMap;
465 this->runImplWithNodeWeights(weights,zeroNodeMap,
target, maxDistance);
469 template<
class EDGE_WEIGHTS,
class NODE_WEIGHTS>
470 void runImplWithNodeWeights(
471 const EDGE_WEIGHTS & edgeWeights,
472 const NODE_WEIGHTS & nodeWeights,
473 const Node &
target = lemon::INVALID,
474 WeightType maxDistance=NumericTraits<WeightType>::max())
476 target_ = lemon::INVALID;
477 while(!pq_.empty() ){
478 const Node topNode(graph_.nodeFromId(pq_.top()));
479 if(distMap_[topNode] > maxDistance)
482 discoveryOrder_.push_back(topNode);
486 for(OutArcIt outArcIt(graph_,topNode);outArcIt!=lemon::INVALID;++outArcIt){
487 const Node otherNode = graph_.target(*outArcIt);
488 const size_t otherNodeId = graph_.id(otherNode);
489 const WeightType otherNodeWeight = nodeWeights[otherNode];
490 if(pq_.contains(otherNodeId)){
491 const Edge
edge(*outArcIt);
492 const WeightType currentDist = distMap_[otherNode];
493 const WeightType alternativeDist = distMap_[topNode]+edgeWeights[
edge]+otherNodeWeight;
494 if(alternativeDist<currentDist){
495 pq_.push(otherNodeId,alternativeDist);
496 distMap_[otherNode]=alternativeDist;
497 predMap_[otherNode]=topNode;
500 else if(predMap_[otherNode]==lemon::INVALID){
501 const Edge
edge(*outArcIt);
502 const WeightType initialDist = distMap_[topNode]+edgeWeights[
edge]+otherNodeWeight;
503 if(initialDist<=maxDistance)
505 pq_.push(otherNodeId,initialDist);
506 distMap_[otherNode]=initialDist;
507 predMap_[otherNode]=topNode;
512 while(!pq_.empty() ){
513 const Node topNode(graph_.nodeFromId(pq_.top()));
514 predMap_[topNode]=lemon::INVALID;
517 if(
target == lemon::INVALID || discoveryOrder_.back() ==
target)
518 target_ = discoveryOrder_.back();
522 void initializeMaps(Node
const & source){
523 for(NodeIt n(graph_); n!=lemon::INVALID; ++n){
525 predMap_[node]=lemon::INVALID;
527 distMap_[
source]=
static_cast<WeightType
>(0.0);
529 discoveryOrder_.clear();
530 pq_.push(graph_.id(source),0.0);
534 void initializeMaps(Node
const & source,
535 Node
const & start, Node
const & stop)
537 Node left_border = min(start, Node(1)),
538 right_border = min(predMap_.shape()-stop, Node(1)),
539 DONT_TOUCH = Node(lemon::INVALID) - Node(1);
542 left_border, right_border, DONT_TOUCH);
543 predMap_.subarray(start, stop) = lemon::INVALID;
546 distMap_[
source]=
static_cast<WeightType
>(0.0);
547 discoveryOrder_.clear();
548 pq_.push(graph_.id(source),0.0);
552 template <
class ITER>
553 void initializeMapsMultiSource(ITER source, ITER source_end){
554 for(NodeIt n(graph_); n!=lemon::INVALID; ++n){
556 predMap_[node]=lemon::INVALID;
558 discoveryOrder_.clear();
559 for( ; source != source_end; ++
source)
561 distMap_[*
source]=
static_cast<WeightType
>(0.0);
563 pq_.push(graph_.id(*source),0.0);
565 source_=lemon::INVALID;
568 void reInitializeMaps(Node
const & source){
569 for(
unsigned int n=0; n<discoveryOrder_.size(); ++n){
570 predMap_[discoveryOrder_[n]]=lemon::INVALID;
572 distMap_[
source]=
static_cast<WeightType
>(0.0);
574 discoveryOrder_.clear();
575 pq_.push(graph_.id(source),0.0);
579 const Graph & graph_;
581 PredecessorsMap predMap_;
582 DistanceMap distMap_;
583 DiscoveryOrder discoveryOrder_;
590 template<
class NODE,
class PREDECESSORS>
594 const PREDECESSORS & predecessors
596 if(predecessors[target]==lemon::INVALID)
599 NODE currentNode =
target;
601 while(currentNode!=source){
602 currentNode=predecessors[currentNode];
610 template<
class GRAPH,
class WEIGHTS,
class PREDECESSORS,
class DISTANCE,
class HEURSTIC>
613 const typename GRAPH::Node & source,
614 const typename GRAPH::Node &
target,
615 const WEIGHTS & weights,
616 PREDECESSORS & predecessors,
618 const HEURSTIC & heuristic
622 typedef typename Graph::Edge Edge;
623 typedef typename Graph::Node Node;
624 typedef typename Graph::NodeIt NodeIt;
625 typedef typename Graph::OutArcIt OutArcIt;
626 typedef typename DISTANCE::value_type DistanceType;
628 typename GRAPH:: template NodeMap<bool> closedSet(graph);
631 for(NodeIt n(graph);n!=lemon::INVALID;++n){
633 closedSet[node]=
false;
634 distance[node]=std::numeric_limits<DistanceType>::infinity();
635 predecessors[node]=lemon::INVALID;
638 distance[
source]=
static_cast<DistanceType
>(0.0);
639 estimatedDistanceOpenSet.push(graph.id(source),heuristic(source,target));
642 while(!estimatedDistanceOpenSet.empty()){
645 const Node current = graph.nodeFromId(estimatedDistanceOpenSet.top());
653 estimatedDistanceOpenSet.pop();
654 closedSet[current]=
true;
657 for(OutArcIt outArcIt(graph,current);outArcIt!=lemon::INVALID;++outArcIt){
660 const Node neighbour = graph.target(*outArcIt);
661 const size_t neighbourId = graph.id(neighbour);
664 if(!closedSet[neighbour]){
667 const Edge
edge(*outArcIt);
670 const DistanceType tenativeScore = distance[current] + weights[
edge];
673 if(!estimatedDistanceOpenSet.contains(neighbourId) || tenativeScore < distance[neighbour] ){
675 predecessors[neighbour]=current;
676 distance[neighbour]=tenativeScore;
680 estimatedDistanceOpenSet.push(neighbourId,distance[neighbour]+heuristic(neighbour,target));
695 void shortestPathSegmentation(
697 const EDGE_WEIGHTS & edgeWeights,
698 const NODE_WEIGHTS & nodeWeights,
699 SEED_NODE_MAP & seeds
703 typedef typename Graph::Node Node;
704 typedef typename Graph::NodeIt NodeIt;
705 typedef WEIGHT_TYPE WeightType;
708 std::vector<Node> seededNodes;
709 for(NodeIt n(graph);n!=lemon::INVALID;++n){
713 seededNodes.push_back(node);
719 typedef typename Sp::PredecessorsMap PredecessorsMap;
721 sp.runMultiSource(edgeWeights, nodeWeights, seededNodes.begin(), seededNodes.end());
722 const PredecessorsMap & predMap = sp.predecessors();
724 for(NodeIt n(graph);n!=lemon::INVALID;++n){
728 Node pred=predMap[node];
729 while(seeds[pred]==0){
732 seeds[node]=seeds[pred];
737 namespace detail_watersheds_segmentation{
739 struct RawPriorityFunctor{
740 template<
class L,
class T>
741 T operator()(
const L label,
const T priority)
const{
748 template<
class PRIORITY_TYPE,
class LABEL_TYPE>
749 struct CarvingFunctor{
750 CarvingFunctor(
const LABEL_TYPE backgroundLabel,
751 const PRIORITY_TYPE & factor,
752 const PRIORITY_TYPE & noPriorBelow
754 : backgroundLabel_(backgroundLabel),
756 noPriorBelow_(noPriorBelow){
758 PRIORITY_TYPE operator()(
const LABEL_TYPE label,
const PRIORITY_TYPE priority)
const{
759 if(priority>=noPriorBelow_)
760 return (label==backgroundLabel_ ? priority*factor_ : priority);
765 LABEL_TYPE backgroundLabel_;
766 PRIORITY_TYPE factor_;
767 PRIORITY_TYPE noPriorBelow_;
775 class PRIORITY_MANIP_FUNCTOR,
778 void edgeWeightedWatershedsSegmentationImpl(
780 const EDGE_WEIGHTS & edgeWeights,
782 PRIORITY_MANIP_FUNCTOR & priorManipFunctor,
786 typedef typename Graph::Edge Edge;
787 typedef typename Graph::Node Node;
788 typedef typename Graph::NodeIt NodeIt;
789 typedef typename Graph::OutArcIt OutArcIt;
791 typedef typename EDGE_WEIGHTS::Value WeightType;
792 typedef typename LABELS::Value LabelType;
803 for(NodeIt n(g);n!=lemon::INVALID;++n){
805 if(labels[node]!=static_cast<LabelType>(0)){
806 for(OutArcIt a(g,node);a!=lemon::INVALID;++a){
808 const Node neigbour=g.target(*a);
810 if(labels[neigbour]==static_cast<LabelType>(0)){
811 const WeightType priority = priorManipFunctor(labels[node],edgeWeights[edge]);
812 pq.push(edge,priority);
822 const Edge
edge = pq.top();
825 const Node u = g.u(edge);
826 const Node v = g.v(edge);
827 const LabelType lU = labels[u];
828 const LabelType lV = labels[v];
832 throw std::runtime_error(
"both have no labels");
834 else if(lU!=0 && lV!=0){
839 const Node unlabeledNode = lU==0 ? u : v;
840 const LabelType label = lU==0 ? lV : lU;
843 labels[unlabeledNode] = label;
846 for(OutArcIt a(g,unlabeledNode);a!=lemon::INVALID;++a){
847 const Edge otherEdge(*a);
848 const Node targetNode=g.target(*a);
849 if(labels[targetNode] == 0){
851 const WeightType priority = priorManipFunctor(label,edgeWeights[otherEdge]);
852 pq.push(otherEdge,priority);
871 template<
class GRAPH,
class EDGE_WEIGHTS,
class SEEDS,
class LABELS>
874 const EDGE_WEIGHTS & edgeWeights,
878 detail_watersheds_segmentation::RawPriorityFunctor fPriority;
879 detail_watersheds_segmentation::edgeWeightedWatershedsSegmentationImpl(g,edgeWeights,seeds,fPriority,labels);
892 template<
class GRAPH,
class EDGE_WEIGHTS,
class SEEDS,
class LABELS>
895 const EDGE_WEIGHTS & edgeWeights,
897 const typename LABELS::Value backgroundLabel,
898 const typename EDGE_WEIGHTS::Value backgroundBias,
899 const typename EDGE_WEIGHTS::Value noPriorBelow,
902 typedef typename EDGE_WEIGHTS::Value WeightType;
903 typedef typename LABELS::Value LabelType;
904 detail_watersheds_segmentation::CarvingFunctor<WeightType,LabelType> fPriority(backgroundLabel,backgroundBias, noPriorBelow);
905 detail_watersheds_segmentation::edgeWeightedWatershedsSegmentationImpl(g,edgeWeights,seeds,fPriority,labels);
916 template<
class GRAPH ,
class EDGE_WEIGHTS,
class NODE_SIZE,
class NODE_LABEL_MAP>
919 const EDGE_WEIGHTS & edgeWeights,
920 const NODE_SIZE & nodeSizes,
922 NODE_LABEL_MAP & nodeLabeling,
923 const int nodeNumStopCond = -1
926 typedef typename Graph::Edge Edge;
927 typedef typename Graph::Node Node;
929 typedef typename EDGE_WEIGHTS::Value WeightType;
930 typedef typename EDGE_WEIGHTS::Value NodeSizeType;
931 typedef typename Graph:: template NodeMap<WeightType> NodeIntDiffMap;
932 typedef typename Graph:: template NodeMap<NodeSizeType> NodeSizeAccMap;
935 NodeIntDiffMap internalDiff(graph);
936 NodeSizeAccMap nodeSizeAcc(graph);
938 fillNodeMap(graph,internalDiff,static_cast<WeightType>(0.0));
945 std::vector<Edge> sortedEdges;
946 std::less<WeightType> comperator;
947 edgeSort(graph,edgeWeights,comperator,sortedEdges);
950 UnionFindArray<UInt64> ufdArray(graph.maxNodeId()+1);
953 size_t nodeNum = graph.nodeNum();
958 for(
size_t i=0;i<sortedEdges.size();++i){
959 const Edge e = sortedEdges[i];
960 const size_t rui = ufdArray.findIndex(graph.id(graph.u(e)));
961 const size_t rvi = ufdArray.findIndex(graph.id(graph.v(e)));
962 const Node ru = graph.nodeFromId(rui);
963 const Node rv = graph.nodeFromId(rvi);
967 const WeightType w = edgeWeights[e];
968 const NodeSizeType sizeRu = nodeSizeAcc[ru];
969 const NodeSizeType sizeRv = nodeSizeAcc[rv];
970 const WeightType tauRu =
static_cast<WeightType
>(k)/static_cast<WeightType>(sizeRu);
971 const WeightType tauRv =
static_cast<WeightType
>(k)/static_cast<WeightType>(sizeRv);
972 const WeightType minIntDiff = std::min(internalDiff[ru]+tauRu,internalDiff[rv]+tauRv);
975 ufdArray.makeUnion(rui,rvi);
978 const size_t newRepId = ufdArray.findIndex(rui);
979 const Node newRepNode = graph.nodeFromId(newRepId);
980 internalDiff[newRepNode]=w;
981 nodeSizeAcc[newRepNode] = sizeRu+sizeRv;
984 if(nodeNum==nodeNumStopCond){
988 if(nodeNumStopCond==-1){
992 if(nodeNum>nodeNumStopCond){
1000 ufdArray.makeContiguous();
1001 for(
typename GRAPH::NodeIt n(graph);n!=lemon::INVALID;++n){
1002 const Node node(*n);
1003 nodeLabeling[node]=ufdArray.findLabel(graph.id(node));
1010 namespace detail_graph_smoothing{
1014 class NODE_FEATURES_IN,
1016 class WEIGHTS_TO_SMOOTH_FACTOR,
1017 class NODE_FEATURES_OUT
1019 void graphSmoothingImpl(
1021 const NODE_FEATURES_IN & nodeFeaturesIn,
1022 const EDGE_WEIGHTS & edgeWeights,
1023 WEIGHTS_TO_SMOOTH_FACTOR & weightsToSmoothFactor,
1024 NODE_FEATURES_OUT & nodeFeaturesOut
1027 typedef GRAPH Graph;
1028 typedef typename Graph::Edge Edge;
1029 typedef typename Graph::Node Node;
1030 typedef typename Graph::NodeIt NodeIt;
1031 typedef typename Graph::OutArcIt OutArcIt;
1033 typedef typename NODE_FEATURES_IN::Value NodeFeatureInValue;
1034 typedef typename NODE_FEATURES_OUT::Reference NodeFeatureOutRef;
1035 typedef typename EDGE_WEIGHTS::ConstReference SmoothFactorType;
1040 for(NodeIt n(g);n!=lemon::INVALID;++n){
1042 const Node node(*n);
1044 NodeFeatureInValue featIn = nodeFeaturesIn[node];
1045 NodeFeatureOutRef featOut = nodeFeaturesOut[node];
1048 float weightSum = 0.0;
1050 for(OutArcIt a(g,node);a!=lemon::INVALID;++a){
1051 const Edge
edge(*a);
1052 const Node neigbour(g.target(*a));
1053 SmoothFactorType smoothFactor= weightsToSmoothFactor(edgeWeights[edge]);
1055 NodeFeatureInValue neighbourFeat = nodeFeaturesIn[neigbour];
1056 neighbourFeat*=smoothFactor;
1058 featOut = neighbourFeat;
1060 featOut += neighbourFeat;
1061 weightSum+=smoothFactor;
1065 featIn*=
static_cast<float>(
degree);
1066 weightSum+=
static_cast<float>(
degree);
1073 struct ExpSmoothFactor{
1074 ExpSmoothFactor(
const T lambda,
const T edgeThreshold,
const T scale)
1076 edgeThreshold_(edgeThreshold),