[ VIGRA Homepage | Function Index | Class Index | Namespaces | File List | Main Page ]

graph_algorithms.hxx VIGRA

1 /************************************************************************/
2 /* */
3 /* Copyright 2014 by Thorsten Beier and Ullrich Koethe */
4 /* */
5 /* This file is part of the VIGRA computer vision library. */
6 /* The VIGRA Website is */
7 /* http://hci.iwr.uni-heidelberg.de/vigra/ */
8 /* Please direct questions, bug reports, and contributions to */
9 /* ullrich.koethe@iwr.uni-heidelberg.de or */
10 /* vigra@informatik.uni-hamburg.de */
11 /* */
12 /* Permission is hereby granted, free of charge, to any person */
13 /* obtaining a copy of this software and associated documentation */
14 /* files (the "Software"), to deal in the Software without */
15 /* restriction, including without limitation the rights to use, */
16 /* copy, modify, merge, publish, distribute, sublicense, and/or */
17 /* sell copies of the Software, and to permit persons to whom the */
18 /* Software is furnished to do so, subject to the following */
19 /* conditions: */
20 /* */
21 /* The above copyright notice and this permission notice shall be */
22 /* included in all copies or substantial portions of the */
23 /* Software. */
24 /* */
25 /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */
26 /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */
27 /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
28 /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */
29 /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */
30 /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */
31 /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */
32 /* OTHER DEALINGS IN THE SOFTWARE. */
33 /* */
34 /************************************************************************/
35 
36 /**
37  * This header provides definitions of graph-related algorithms
38  */
39 
40 #ifndef VIGRA_GRAPH_ALGORITHMS_HXX
41 #define VIGRA_GRAPH_ALGORITHMS_HXX
42 
43 /*std*/
44 #include <algorithm>
45 #include <vector>
46 #include <functional>
47 #include <set>
48 #include <iomanip>
49 
50 /*vigra*/
51 #include "graphs.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"
58 
59 #include "timing.hxx"
60 //#include "openmp_helper.hxx"
61 
62 
63 #include "functorexpression.hxx"
64 #include "array_vector.hxx"
65 
66 namespace vigra{
67 
68 /** \addtogroup GraphDataStructures
69 */
70 //@{
71 
72  namespace detail_graph_algorithms{
73  template <class GRAPH_MAP,class COMPERATOR>
74  struct GraphItemCompare
75  {
76 
77  GraphItemCompare(const GRAPH_MAP & map,const COMPERATOR & comperator)
78  : map_(map),
79  comperator_(comperator){
80 
81  }
82 
83  template<class KEY>
84  bool operator()(const KEY & a, const KEY & b) const{
85  return comperator_(map_[a],map_[b]);
86  }
87 
88  const GRAPH_MAP & map_;
89  const COMPERATOR & comperator_;
90  };
91  } // namespace detail_graph_algorithms
92 
93  /// \brief get a vector of Edge descriptors
94  ///
95  /// Sort the Edge descriptors given weights
96  /// and a comperator
97  template<class GRAPH,class WEIGHTS,class COMPERATOR>
98  void edgeSort(
99  const GRAPH & g,
100  const WEIGHTS & weights,
101  const COMPERATOR & comperator,
102  std::vector<typename GRAPH::Edge> & sortedEdges
103  ){
104  sortedEdges.resize(g.edgeNum());
105  size_t c=0;
106  for(typename GRAPH::EdgeIt e(g);e!=lemon::INVALID;++e){
107  sortedEdges[c]=*e;
108  ++c;
109  }
110  detail_graph_algorithms::GraphItemCompare<WEIGHTS,COMPERATOR> edgeComperator(weights,comperator);
111  std::sort(sortedEdges.begin(),sortedEdges.end(),edgeComperator);
112  }
113 
114 
115  /// \brief copy a lemon node map
116  template<class G,class A,class B>
117  void copyNodeMap(const G & g,const A & a ,B & b){
118  typename G::NodeIt iter(g);
119  while(iter!=lemon::INVALID){
120  b[*iter]=a[*iter];
121  ++iter;
122  }
123 
124  }
125  /// \brief copy a lemon edge map
126  template<class G,class A,class B>
127  void copyEdgeMap(const G & g,const A & a ,B & b){
128  typename G::EdgeIt iter(g);
129  while(iter!=lemon::INVALID){
130  b[*iter]=a[*iter];
131  ++iter;
132  }
133  }
134  /// \brief fill a lemon node map
135  template<class G,class A,class T>
136  void fillNodeMap(const G & g, A & a, const T & value){
137  typename G::NodeIt iter(g);
138  while(iter!=lemon::INVALID){
139  a[*iter]=value;
140  ++iter;
141  }
142  }
143  /// \brief fill a lemon edge map
144  template<class G,class A,class T>
145  void fillEdgeMap(const G & g,A & a ,const T & value){
146  typename G::EdgeIt iter(g);
147  while(iter!=lemon::INVALID){
148  a[*iter]=value;
149  ++iter;
150  }
151  }
152 
153  /// \brief make a region adjacency graph from a graph and labels w.r.t. that graph
154  ///
155  /// \param graphIn : input graph
156  /// \param labels : labels w.r.t. graphIn
157  /// \param[out] rag : region adjacency graph
158  /// \param[out] affiliatedEdges : a vector of edges of graphIn for each edge in rag
159  /// \param ignoreLabel : optional label to ignore (default: -1 means no label will be ignored)
160  ///
161  template<
162  class GRAPH_IN,
163  class GRAPH_IN_NODE_LABEL_MAP
164  >
166  GRAPH_IN graphIn,
167  GRAPH_IN_NODE_LABEL_MAP labels,
168  AdjacencyListGraph & rag,
169  typename AdjacencyListGraph:: template EdgeMap< std::vector<typename GRAPH_IN::Edge> > & affiliatedEdges,
170  const Int64 ignoreLabel=-1
171  ){
172  rag=AdjacencyListGraph();
173  typedef typename GraphMapTypeTraits<GRAPH_IN_NODE_LABEL_MAP>::Value LabelType;
174  typedef GRAPH_IN GraphIn;
175  typedef AdjacencyListGraph GraphOut;
176 
177  typedef typename GraphIn::Edge EdgeGraphIn;
178  typedef typename GraphIn::NodeIt NodeItGraphIn;
179  typedef typename GraphIn::EdgeIt EdgeItGraphIn;
180  typedef typename GraphOut::Edge EdgeGraphOut;
181 
182 
183  for(NodeItGraphIn iter(graphIn);iter!=lemon::INVALID;++iter){
184  const LabelType l=labels[*iter];
185  if(ignoreLabel==-1 || static_cast<Int64>(l)!=ignoreLabel)
186  rag.addNode(l);
187  }
188 
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) ) ){
194  // if there is an edge between lu and lv no new edge will be added
195  rag.addEdge( rag.nodeFromId(lu),rag.nodeFromId(lv));
196  }
197  }
198 
199  //SET UP HYPEREDGES
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)];
205  //std::cout<<"edge between ?? "<<lu<<" "<<lv<<"\n";
206  if( lu!=lv && ( ignoreLabel==-1 || (static_cast<Int64>(lu)!=ignoreLabel && static_cast<Int64>(lv)!=ignoreLabel) ) ){
207  //std::cout<<"find edge between "<<lu<<" "<<lv<<"\n";
208  EdgeGraphOut ragEdge= rag.findEdge(rag.nodeFromId(lu),rag.nodeFromId(lv));
209  //std::cout<<"invalid?"<<bool(ragEdge==lemon::INVALID)<<" id "<<rag.id(ragEdge)<<"\n";
210  affiliatedEdges[ragEdge].push_back(edge);
211  //std::cout<<"write done\n";
212  }
213  }
214  }
215 
216  template<unsigned int DIM, class DTAG, class AFF_EDGES>
217  size_t affiliatedEdgesSerializationSize(
218  const GridGraph<DIM,DTAG> &,
219  const AdjacencyListGraph & rag,
220  const AFF_EDGES & affEdges
221  ){
222  size_t size = 0;
223 
224  typedef typename AdjacencyListGraph::EdgeIt EdgeIt;
225  typedef typename AdjacencyListGraph::Edge Edge;
226 
227  for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
228  const Edge e(*iter);
229  size+=1;
230  size+=affEdges[e].size()*(DIM+1);
231  }
232  return size;
233  }
234 
235  template<class OUT_ITER, unsigned int DIM, class DTAG, class AFF_EDGES>
236  void serializeAffiliatedEdges(
237  const GridGraph<DIM,DTAG> &,
238  const AdjacencyListGraph & rag,
239  const AFF_EDGES & affEdges,
240  OUT_ITER outIter
241  ){
242 
243  typedef typename AdjacencyListGraph::EdgeIt EdgeIt;
244  typedef typename AdjacencyListGraph::Edge Edge;
245  typedef typename GridGraph<DIM,DTAG>::Edge GEdge;
246 
247  for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
248 
249  const Edge edge = *iter;
250  const size_t numAffEdge = affEdges[edge].size();
251  *outIter = numAffEdge; ++outIter;
252 
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;
257  }
258  }
259  }
260  }
261 
262  template<class IN_ITER, unsigned int DIM, class DTAG, class AFF_EDGES>
263  void deserializeAffiliatedEdges(
264  const GridGraph<DIM,DTAG> &,
265  const AdjacencyListGraph & rag,
266  AFF_EDGES & affEdges,
267  IN_ITER begin,
268  IN_ITER
269  ){
270 
271  typedef typename AdjacencyListGraph::EdgeIt EdgeIt;
272  typedef typename AdjacencyListGraph::Edge Edge;
273  typedef typename GridGraph<DIM,DTAG>::Edge GEdge;
274 
275  affEdges.assign(rag);
276 
277  for(EdgeIt iter(rag); iter!=lemon::INVALID; ++iter){
278 
279  const Edge edge = *iter;
280  const size_t numAffEdge = *begin; ++begin;
281 
282  for(size_t i=0; i<numAffEdge; ++i){
283  GEdge gEdge;
284  for(size_t d=0; d<DIM+1; ++d){
285  gEdge[d]=*begin; ++begin;
286  }
287  affEdges[edge].push_back(gEdge);
288  }
289  }
290  }
291 
292 
293 
294 
295  /// \brief shortest path computer
296  template<class GRAPH,class WEIGHT_TYPE>
298  public:
299  typedef GRAPH Graph;
300 
301  typedef typename Graph::Node Node;
302  typedef typename Graph::NodeIt NodeIt;
303  typedef typename Graph::Edge Edge;
304  typedef typename Graph::OutArcIt OutArcIt;
305 
306  typedef WEIGHT_TYPE WeightType;
308  typedef typename Graph:: template NodeMap<Node> PredecessorsMap;
309  typedef typename Graph:: template NodeMap<WeightType> DistanceMap;
311 
312  /// \ brief constructor from graph
313  ShortestPathDijkstra(const Graph & g)
314  : graph_(g),
315  pq_(g.maxNodeId()+1),
316  predMap_(g),
317  distMap_(g)
318  {
319  }
320 
321  /// \brief run shortest path given edge weights
322  ///
323  /// \param weights : edge weights encoding the distance between adjacent nodes (must be non-negative)
324  /// \param source : source node where shortest path should start
325  /// \param target : target node where shortest path should stop. If target is not given
326  /// or <tt>INVALID</tt>, the shortest path from source to all reachable nodes is computed
327  /// \param maxDistance : path search is terminated when the path length exceeds <tt>maxDistance</tt>
328  ///
329  /// When a valid \a target is unreachable from \a source (either because the graph is disconnected
330  /// or \a maxDistance is exceeded), it is set to <tt>lemon::INVALID</tt>. In contrast, if \a target
331  /// was <tt>lemon::INVALID</tt> at the beginning, it will always be set to the last node
332  /// visited in the search.
333  template<class WEIGHTS>
334  void run(const WEIGHTS & weights, const Node & source,
335  const Node & target = lemon::INVALID,
336  WeightType maxDistance=NumericTraits<WeightType>::max())
337  {
338  this->initializeMaps(source);
339  runImpl(weights, target, maxDistance);
340  }
341 
342  /// \brief run shortest path in a region of interest of a \ref GridGraph.
343  ///
344  /// \param start : first point in the desired ROI.
345  /// \param stop : beyond the last point in the desired ROI (i.e. exclusive)
346  /// \param weights : edge weights encoding the distance between adjacent nodes (must be non-negative)
347  /// \param source : source node where shortest path should start
348  /// \param target : target node where shortest path should stop. If target is not given
349  /// or <tt>INVALID</tt>, the shortest path from source to all reachable nodes is computed
350  /// \param maxDistance : path search is terminated when the path length exceeds <tt>maxDistance</tt>
351  ///
352  /// This version of <tt>run()</tt> restricts the path search to the ROI <tt>[start, stop)</tt> and only
353  /// works for instances of \ref GridGraph. Otherwise, it is identical to the standard <tt>run()</tt>
354  /// function.
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())
360  {
361  vigra_precondition(allLessEqual(start, source) && allLess(source, stop),
362  "ShortestPathDijkstra::run(): source is not within ROI");
363  vigra_precondition(target == lemon::INVALID ||
364  (allLessEqual(start, target) && allLess(target, stop)),
365  "ShortestPathDijkstra::run(): target is not within ROI");
366  this->initializeMaps(source, start, stop);
367  runImpl(weights, target, maxDistance);
368  }
369 
370  /// \brief run shortest path again with given edge weights
371  ///
372  /// This only differs from standard <tt>run()</tt> by initialization: Instead of resetting
373  /// the entire graph, this only resets the nodes that have been visited in the
374  /// previous run, i.e. the contents of the array <tt>discoveryOrder()</tt>.
375  /// This will be much faster if only a small fraction of the nodes has to be reset.
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())
380  {
381  this->reInitializeMaps(source);
382  runImpl(weights, target, maxDistance);
383  }
384 
385  /// \brief run shortest path with given edge weights from multiple sources.
386  ///
387  /// This is otherwise identical to standard <tt>run()</tt>, except that
388  /// <tt>source()</tt> returns <tt>lemon::INVALID</tt> after path search finishes.
389  template<class WEIGHTS, class ITER>
390  void
391  runMultiSource(const WEIGHTS & weights, ITER source_begin, ITER source_end,
392  const Node & target = lemon::INVALID,
393  WeightType maxDistance=NumericTraits<WeightType>::max())
394  {
395  this->initializeMapsMultiSource(source_begin, source_end);
396  runImpl(weights, target, maxDistance);
397  }
398 
399 
400  /// \brief run shortest path with given edge weights from multiple sources.
401  ///
402  /// This is otherwise identical to standard <tt>run()</tt>, except that
403  /// <tt>source()</tt> returns <tt>lemon::INVALID</tt> after path search finishes.
404  template<class EFGE_WEIGHTS,class NODE_WEIGHTS, class ITER>
405  void
407  const EFGE_WEIGHTS & edgeWeights,
408  const NODE_WEIGHTS & nodeWeights,
409  ITER source_begin,
410  ITER source_end,
411  const Node & target = lemon::INVALID,
412  WeightType maxDistance = NumericTraits<WeightType>::max())
413  {
414  this->initializeMapsMultiSource(source_begin, source_end);
415  runImplWithNodeWeights(edgeWeights, nodeWeights, target, maxDistance);
416  }
417 
418  /// \brief get the graph
419  const Graph & graph()const{
420  return graph_;
421  }
422  /// \brief get the source node
423  const Node & source()const{
424  return source_;
425  }
426  /// \brief get the target node
427  const Node & target()const{
428  return target_;
429  }
430 
431  /// \brief check if explicit target is given
432  bool hasTarget()const{
433  return target_!=lemon::INVALID;
434  }
435 
436  /// \brief get an array with all visited nodes, sorted by distance from source
438  return discoveryOrder_;
439  }
440 
441  /// \brief get the predecessors node map (after a call of run)
442  const PredecessorsMap & predecessors()const{
443  return predMap_;
444  }
445 
446  /// \brief get the distances node map (after a call of run)
447  const DistanceMap & distances()const{
448  return distMap_;
449  }
450 
451  /// \brief get the distance to a rarget node (after a call of run)
452  WeightType distance(const Node & target)const{
453  return distMap_[target];
454  }
455 
456 
457  private:
458 
459  template<class WEIGHTS>
460  void runImpl(const WEIGHTS & weights,
461  const Node & target = lemon::INVALID,
462  WeightType maxDistance=NumericTraits<WeightType>::max())
463  {
464  ZeroNodeMap<Graph, WEIGHT_TYPE> zeroNodeMap;
465  this->runImplWithNodeWeights(weights,zeroNodeMap, target, maxDistance);
466  }
467 
468 
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())
475  {
476  target_ = lemon::INVALID;
477  while(!pq_.empty() ){ //&& !finished){
478  const Node topNode(graph_.nodeFromId(pq_.top()));
479  if(distMap_[topNode] > maxDistance)
480  break; // distance threshold exceeded
481  pq_.pop();
482  discoveryOrder_.push_back(topNode);
483  if(topNode == target)
484  break;
485  // loop over all neigbours
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;
498  }
499  }
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)
504  {
505  pq_.push(otherNodeId,initialDist);
506  distMap_[otherNode]=initialDist;
507  predMap_[otherNode]=topNode;
508  }
509  }
510  }
511  }
512  while(!pq_.empty() ){
513  const Node topNode(graph_.nodeFromId(pq_.top()));
514  predMap_[topNode]=lemon::INVALID;
515  pq_.pop();
516  }
517  if(target == lemon::INVALID || discoveryOrder_.back() == target)
518  target_ = discoveryOrder_.back(); // Means that target was reached. If, to the contrary, target
519  // was unreachable within maxDistance, target_ remains INVALID.
520  }
521 
522  void initializeMaps(Node const & source){
523  for(NodeIt n(graph_); n!=lemon::INVALID; ++n){
524  const Node node(*n);
525  predMap_[node]=lemon::INVALID;
526  }
527  distMap_[source]=static_cast<WeightType>(0.0);
528  predMap_[source]=source;
529  discoveryOrder_.clear();
530  pq_.push(graph_.id(source),0.0);
531  source_=source;
532  }
533 
534  void initializeMaps(Node const & source,
535  Node const & start, Node const & stop)
536  {
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);
540 
541  initMultiArrayBorder(predMap_.subarray(start-left_border, stop+right_border),
542  left_border, right_border, DONT_TOUCH);
543  predMap_.subarray(start, stop) = lemon::INVALID;
544  predMap_[source]=source;
545 
546  distMap_[source]=static_cast<WeightType>(0.0);
547  discoveryOrder_.clear();
548  pq_.push(graph_.id(source),0.0);
549  source_=source;
550  }
551 
552  template <class ITER>
553  void initializeMapsMultiSource(ITER source, ITER source_end){
554  for(NodeIt n(graph_); n!=lemon::INVALID; ++n){
555  const Node node(*n);
556  predMap_[node]=lemon::INVALID;
557  }
558  discoveryOrder_.clear();
559  for( ; source != source_end; ++source)
560  {
561  distMap_[*source]=static_cast<WeightType>(0.0);
562  predMap_[*source]=*source;
563  pq_.push(graph_.id(*source),0.0);
564  }
565  source_=lemon::INVALID;
566  }
567 
568  void reInitializeMaps(Node const & source){
569  for(unsigned int n=0; n<discoveryOrder_.size(); ++n){
570  predMap_[discoveryOrder_[n]]=lemon::INVALID;
571  }
572  distMap_[source]=static_cast<WeightType>(0.0);
573  predMap_[source]=source;
574  discoveryOrder_.clear();
575  pq_.push(graph_.id(source),0.0);
576  source_=source;
577  }
578 
579  const Graph & graph_;
580  PqType pq_;
581  PredecessorsMap predMap_;
582  DistanceMap distMap_;
583  DiscoveryOrder discoveryOrder_;
584 
585  Node source_;
586  Node target_;
587  };
588 
589  /// \brief get the length in node units of a path
590  template<class NODE,class PREDECESSORS>
591  size_t pathLength(
592  const NODE source,
593  const NODE target,
594  const PREDECESSORS & predecessors
595  ){
596  if(predecessors[target]==lemon::INVALID)
597  return 0;
598  else{
599  NODE currentNode = target;
600  size_t length=1;
601  while(currentNode!=source){
602  currentNode=predecessors[currentNode];
603  length+=1;
604  }
605  return length;
606  }
607  }
608 
609  /// \brief Astar Shortest path search
610  template<class GRAPH,class WEIGHTS,class PREDECESSORS,class DISTANCE,class HEURSTIC>
612  const GRAPH & graph,
613  const typename GRAPH::Node & source,
614  const typename GRAPH::Node & target,
615  const WEIGHTS & weights,
616  PREDECESSORS & predecessors,
617  DISTANCE & distance,
618  const HEURSTIC & heuristic
619  ){
620 
621  typedef GRAPH Graph;
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;
627 
628  typename GRAPH:: template NodeMap<bool> closedSet(graph);
629  vigra::ChangeablePriorityQueue<typename WEIGHTS::value_type> estimatedDistanceOpenSet(graph.maxNodeId()+1);
630  // initialize
631  for(NodeIt n(graph);n!=lemon::INVALID;++n){
632  const Node node(*n);
633  closedSet[node]=false;
634  distance[node]=std::numeric_limits<DistanceType>::infinity();
635  predecessors[node]=lemon::INVALID;
636  }
637  // distance and estimated distance for start node
638  distance[source]=static_cast<DistanceType>(0.0);
639  estimatedDistanceOpenSet.push(graph.id(source),heuristic(source,target));
640 
641  // while any nodes left in openSet
642  while(!estimatedDistanceOpenSet.empty()){
643 
644  // get the node with the lpwest estimated distance in the open set
645  const Node current = graph.nodeFromId(estimatedDistanceOpenSet.top());
646 
647  // reached target?
648  if(current==target)
649  break;
650 
651  // remove current from openSet
652  // add current to closedSet
653  estimatedDistanceOpenSet.pop();
654  closedSet[current]=true;
655 
656  // iterate over neigbours of current
657  for(OutArcIt outArcIt(graph,current);outArcIt!=lemon::INVALID;++outArcIt){
658 
659  // get neigbour node and id
660  const Node neighbour = graph.target(*outArcIt);
661  const size_t neighbourId = graph.id(neighbour);
662 
663  // if neighbour is not yet in closedSet
664  if(!closedSet[neighbour]){
665 
666  // get edge between current and neigbour
667  const Edge edge(*outArcIt);
668 
669  // get tentative score
670  const DistanceType tenativeScore = distance[current] + weights[edge];
671 
672  // neighbour NOT in openSet OR tentative score better than the current distance
673  if(!estimatedDistanceOpenSet.contains(neighbourId) || tenativeScore < distance[neighbour] ){
674  // set predecessors and distance
675  predecessors[neighbour]=current;
676  distance[neighbour]=tenativeScore;
677 
678  // update the estimated cost from neighbour to target
679  // ( and neigbour will be (re)-added to openSet)
680  estimatedDistanceOpenSet.push(neighbourId,distance[neighbour]+heuristic(neighbour,target));
681  }
682  }
683  }
684  }
685  }
686 
687 
688  template<
689  class GRAPH,
690  class EDGE_WEIGHTS,
691  class NODE_WEIGHTS,
692  class SEED_NODE_MAP,
693  class WEIGHT_TYPE
694  >
695  void shortestPathSegmentation(
696  const GRAPH & graph,
697  const EDGE_WEIGHTS & edgeWeights,
698  const NODE_WEIGHTS & nodeWeights,
699  SEED_NODE_MAP & seeds
700  ){
701 
702  typedef GRAPH Graph;
703  typedef typename Graph::Node Node;
704  typedef typename Graph::NodeIt NodeIt;
705  typedef WEIGHT_TYPE WeightType;
706 
707  // find seeds
708  std::vector<Node> seededNodes;
709  for(NodeIt n(graph);n!=lemon::INVALID;++n){
710  const Node node(*n);
711  // not a seed
712  if(seeds[node]!=0){
713  seededNodes.push_back(node);
714  }
715  }
716 
717  // do shortest path
718  typedef ShortestPathDijkstra<Graph, WeightType> Sp;
719  typedef typename Sp::PredecessorsMap PredecessorsMap;
720  Sp sp(graph);
721  sp.runMultiSource(edgeWeights, nodeWeights, seededNodes.begin(), seededNodes.end());
722  const PredecessorsMap & predMap = sp.predecessors();
723  // do the labeling
724  for(NodeIt n(graph);n!=lemon::INVALID;++n){
725  Node node(*n);
726  if(seeds[node]==0){
727  Node pred=predMap[node];
728  while(seeds[pred]==0){
729  pred=predMap[pred];
730  }
731  seeds[node]=seeds[pred];
732  }
733  }
734  }
735 
736  namespace detail_watersheds_segmentation{
737 
738  struct RawPriorityFunctor{
739  template<class LabelType, class T>
740  T operator()(const LabelType /*label*/,const T priority)const{
741  return priority;
742  }
743  };
744 
745 
746 
747  template<class PRIORITY_TYPE,class LABEL_TYPE>
748  struct CarvingFunctor{
749  CarvingFunctor(const LABEL_TYPE backgroundLabel,
750  const PRIORITY_TYPE & factor,
751  const PRIORITY_TYPE & noPriorBelow
752  )
753  : backgroundLabel_(backgroundLabel),
754  factor_(factor),
755  noPriorBelow_(noPriorBelow){
756  }
757  PRIORITY_TYPE operator()(const LABEL_TYPE label,const PRIORITY_TYPE priority)const{
758  if(priority>=noPriorBelow_)
759  return (label==backgroundLabel_ ? priority*factor_ : priority);
760  else{
761  return priority;
762  }
763  }
764  LABEL_TYPE backgroundLabel_;
765  PRIORITY_TYPE factor_;
766  PRIORITY_TYPE noPriorBelow_;
767  };
768 
769 
770  template<
771  class GRAPH,
772  class EDGE_WEIGHTS,
773  class SEEDS,
774  class PRIORITY_MANIP_FUNCTOR,
775  class LABELS
776  >
777  void edgeWeightedWatershedsSegmentationImpl(
778  const GRAPH & g,
779  const EDGE_WEIGHTS & edgeWeights,
780  const SEEDS & seeds,
781  PRIORITY_MANIP_FUNCTOR & priorManipFunctor,
782  LABELS & labels
783  ){
784  typedef GRAPH Graph;
785  typedef typename Graph::Edge Edge;
786  typedef typename Graph::Node Node;
787  typedef typename Graph::NodeIt NodeIt;
788  typedef typename Graph::OutArcIt OutArcIt;
789 
790  typedef typename EDGE_WEIGHTS::Value WeightType;
791  typedef typename LABELS::Value LabelType;
792  //typedef typename Graph:: template EdgeMap<bool> EdgeBoolMap;
793  typedef PriorityQueue<Edge,WeightType,true> PQ;
794 
795  PQ pq;
796  //EdgeBoolMap inPQ(g);
797  copyNodeMap(g,seeds,labels);
798  //fillEdgeMap(g,inPQ,false);
799 
800 
801  // put edges from nodes with seed on pq
802  for(NodeIt n(g);n!=lemon::INVALID;++n){
803  const Node node(*n);
804  if(labels[node]!=static_cast<LabelType>(0)){
805  for(OutArcIt a(g,node);a!=lemon::INVALID;++a){
806  const Edge edge(*a);
807  const Node neigbour=g.target(*a);
808  //std::cout<<"n- node "<<g.id(neigbour)<<"\n";
809  if(labels[neigbour]==static_cast<LabelType>(0)){
810  const WeightType priority = priorManipFunctor(labels[node],edgeWeights[edge]);
811  pq.push(edge,priority);
812  //inPQ[edge]=true;
813  }
814  }
815  }
816  }
817 
818 
819  while(!pq.empty()){
820 
821  const Edge edge = pq.top();
822  pq.pop();
823 
824  const Node u = g.u(edge);
825  const Node v = g.v(edge);
826  const LabelType lU = labels[u];
827  const LabelType lV = labels[v];
828 
829 
830  if(lU==0 && lV==0){
831  throw std::runtime_error("both have no labels");
832  }
833  else if(lU!=0 && lV!=0){
834  // nothing to do
835  }
836  else{
837 
838  const Node unlabeledNode = lU==0 ? u : v;
839  const LabelType label = lU==0 ? lV : lU;
840 
841  // assign label to unlabeled node
842  labels[unlabeledNode] = label;
843 
844  // iterate over the nodes edges
845  for(OutArcIt a(g,unlabeledNode);a!=lemon::INVALID;++a){
846  const Edge otherEdge(*a);
847  const Node targetNode=g.target(*a);
848  if(labels[targetNode] == 0){
849  //if(inPQ[otherEdge] == false && labels[targetNode] == 0){
850  const WeightType priority = priorManipFunctor(label,edgeWeights[otherEdge]);
851  pq.push(otherEdge,priority);
852  // inPQ[otherEdge]=true;
853  }
854  }
855  }
856 
857  }
858 
859  }
860 
861  } // end namespace detail_watersheds_segmentation
862 
863 
864  /// \brief edge weighted watersheds Segmentataion
865  ///
866  /// \param g: input graph
867  /// \param edgeWeights : edge weights / edge indicator
868  /// \param seeds : seed must be non empty!
869  /// \param[out] labels : resulting nodeLabeling (not necessarily dense)
870  template<class GRAPH,class EDGE_WEIGHTS,class SEEDS,class LABELS>
872  const GRAPH & g,
873  const EDGE_WEIGHTS & edgeWeights,
874  const SEEDS & seeds,
875  LABELS & labels
876  ){
877  detail_watersheds_segmentation::RawPriorityFunctor fPriority;
878  detail_watersheds_segmentation::edgeWeightedWatershedsSegmentationImpl(g,edgeWeights,seeds,fPriority,labels);
879  }
880 
881 
882  /// \brief edge weighted watersheds Segmentataion
883  ///
884  /// \param g: input graph
885  /// \param edgeWeights : edge weights / edge indicator
886  /// \param seeds : seed must be non empty!
887  /// \param backgroundLabel : which label is background
888  /// \param backgroundBias : bias for background
889  /// \param noPriorBelow : don't bias the background if edge indicator is below this value
890  /// \param[out] labels : resulting nodeLabeling (not necessarily dense)
891  template<class GRAPH,class EDGE_WEIGHTS,class SEEDS,class LABELS>
893  const GRAPH & g,
894  const EDGE_WEIGHTS & edgeWeights,
895  const SEEDS & seeds,
896  const typename LABELS::Value backgroundLabel,
897  const typename EDGE_WEIGHTS::Value backgroundBias,
898  const typename EDGE_WEIGHTS::Value noPriorBelow,
899  LABELS & labels
900  ){
901  typedef typename EDGE_WEIGHTS::Value WeightType;
902  typedef typename LABELS::Value LabelType;
903  detail_watersheds_segmentation::CarvingFunctor<WeightType,LabelType> fPriority(backgroundLabel,backgroundBias, noPriorBelow);
904  detail_watersheds_segmentation::edgeWeightedWatershedsSegmentationImpl(g,edgeWeights,seeds,fPriority,labels);
905  }
906 
907  /// \brief edge weighted watersheds Segmentataion
908  ///
909  /// \param graph: input graph
910  /// \param edgeWeights : edge weights / edge indicator
911  /// \param nodeSizes : size of each node
912  /// \param k : free parameter of felzenszwalb algorithm
913  /// \param[out] nodeLabeling : nodeLabeling (not necessarily dense)
914  /// \param nodeNumStopCond : optional stopping condition
915  template< class GRAPH , class EDGE_WEIGHTS, class NODE_SIZE,class NODE_LABEL_MAP>
917  const GRAPH & graph,
918  const EDGE_WEIGHTS & edgeWeights,
919  const NODE_SIZE & nodeSizes,
920  float k,
921  NODE_LABEL_MAP & nodeLabeling,
922  const int nodeNumStopCond = -1
923  ){
924  typedef GRAPH Graph;
925  typedef typename Graph::Edge Edge;
926  typedef typename Graph::Node Node;
927 
928  typedef typename EDGE_WEIGHTS::Value WeightType;
929  typedef typename EDGE_WEIGHTS::Value NodeSizeType;
930  typedef typename Graph:: template NodeMap<WeightType> NodeIntDiffMap;
931  typedef typename Graph:: template NodeMap<NodeSizeType> NodeSizeAccMap;
932 
933  // initalize node size map and internal diff map
934  NodeIntDiffMap internalDiff(graph);
935  NodeSizeAccMap nodeSizeAcc(graph);
936  copyNodeMap(graph,nodeSizes,nodeSizeAcc);
937  fillNodeMap(graph,internalDiff,static_cast<WeightType>(0.0));
938 
939 
940 
941  // initlaize internal node diff map
942 
943  // sort the edges by their weights
944  std::vector<Edge> sortedEdges;
945  std::less<WeightType> comperator;
946  edgeSort(graph,edgeWeights,comperator,sortedEdges);
947 
948  // make the ufd
949  UnionFindArray<UInt64> ufdArray(graph.maxNodeId()+1);
950 
951 
952  size_t nodeNum = graph.nodeNum();
953 
954 
955  while(true){
956  // iterate over edges is the sorted order
957  for(size_t i=0;i<sortedEdges.size();++i){
958  const Edge e = sortedEdges[i];
959  const size_t rui = ufdArray.findIndex(graph.id(graph.u(e)));
960  const size_t rvi = ufdArray.findIndex(graph.id(graph.v(e)));
961  const Node ru = graph.nodeFromId(rui);
962  const Node rv = graph.nodeFromId(rvi);
963  if(rui!=rvi){
964 
965  //check if to merge or not ?
966  const WeightType w = edgeWeights[e];
967  const NodeSizeType sizeRu = nodeSizeAcc[ru];
968  const NodeSizeType sizeRv = nodeSizeAcc[rv];
969  const WeightType tauRu = static_cast<WeightType>(k)/static_cast<WeightType>(sizeRu);
970  const WeightType tauRv = static_cast<WeightType>(k)/static_cast<WeightType>(sizeRv);
971  const WeightType minIntDiff = std::min(internalDiff[ru]+tauRu,internalDiff[rv]+tauRv);
972  if(w<=minIntDiff){
973  // do merge
974  ufdArray.makeUnion(rui,rvi);
975  --nodeNum;
976  // update size and internal difference
977  const size_t newRepId = ufdArray.findIndex(rui);
978  const Node newRepNode = graph.nodeFromId(newRepId);
979  internalDiff[newRepNode]=w;
980  nodeSizeAcc[newRepNode] = sizeRu+sizeRv;
981  }
982  }
983  if(nodeNumStopCond >= 0 && nodeNum==static_cast<size_t>(nodeNumStopCond)){
984  break;
985  }
986  }
987  if(nodeNumStopCond==-1){
988  break;
989  }
990  else{
991  if(nodeNumStopCond >= 0 && nodeNum>static_cast<size_t>(nodeNumStopCond)){
992  k *= 1.2f;
993  }
994  else{
995  break;
996  }
997  }
998  }
999  ufdArray.makeContiguous();
1000  for(typename GRAPH::NodeIt n(graph);n!=lemon::INVALID;++n){
1001  const Node node(*n);
1002  nodeLabeling[node]=ufdArray.findLabel(graph.id(node));
1003  }
1004  }
1005 
1006 
1007 
1008 
1009  namespace detail_graph_smoothing{
1010 
1011  template<
1012  class GRAPH,
1013  class NODE_FEATURES_IN,
1014  class EDGE_WEIGHTS,
1015  class WEIGHTS_TO_SMOOTH_FACTOR,
1016  class NODE_FEATURES_OUT
1017  >
1018  void graphSmoothingImpl(
1019  const GRAPH & g,
1020  const NODE_FEATURES_IN & nodeFeaturesIn,
1021  const EDGE_WEIGHTS & edgeWeights,
1022  WEIGHTS_TO_SMOOTH_FACTOR & weightsToSmoothFactor,
1023  NODE_FEATURES_OUT & nodeFeaturesOut
1024 
1025  ){
1026  typedef GRAPH Graph;
1027  typedef typename Graph::Edge Edge;
1028  typedef typename Graph::Node Node;
1029  typedef typename Graph::NodeIt NodeIt;
1030  typedef typename Graph::OutArcIt OutArcIt;
1031 
1032  typedef typename NODE_FEATURES_IN::Value NodeFeatureInValue;
1033  typedef typename NODE_FEATURES_OUT::Reference NodeFeatureOutRef;
1034  typedef typename EDGE_WEIGHTS::ConstReference SmoothFactorType;
1035 
1036 
1037  //fillNodeMap(g, nodeFeaturesOut, typename NODE_FEATURES_OUT::value_type(0.0));
1038 
1039  for(NodeIt n(g);n!=lemon::INVALID;++n){
1040 
1041  const Node node(*n);
1042 
1043  NodeFeatureInValue featIn = nodeFeaturesIn[node];
1044  NodeFeatureOutRef featOut = nodeFeaturesOut[node];
1045 
1046  featOut=0;
1047  float weightSum = 0.0;
1048  size_t degree = 0;
1049  for(OutArcIt a(g,node);a!=lemon::INVALID;++a){
1050  const Edge edge(*a);
1051  const Node neigbour(g.target(*a));
1052  SmoothFactorType smoothFactor= weightsToSmoothFactor(edgeWeights[edge]);
1053 
1054  NodeFeatureInValue neighbourFeat = nodeFeaturesIn[neigbour];
1055  neighbourFeat*=smoothFactor;
1056  if(degree==0)
1057  featOut = neighbourFeat;
1058  else
1059  featOut += neighbourFeat;
1060  weightSum+=smoothFactor;
1061  ++degree;
1062  }
1063  // fixme..set me to right type
1064  featIn*=static_cast<float>(degree);
1065  weightSum+=static_cast<float>(degree);
1066  featOut+=featIn;
1067  featOut/=weightSum;
1068  }
1069  }
1070 
1071  template<class T>
1072  struct ExpSmoothFactor{
1073  ExpSmoothFactor(const T lambda,const T edgeThreshold,const T scale)
1074  : lambda_(lambda),
1075  edgeThreshold_(edgeThreshold),
1076  scale_(scale){
1077  }
1078  T operator()(const T weight){
1079  return weight> edgeThreshold_ ? 0 : std::exp(-1.0*lambda_*weight)*scale_;
1080  }
1081  T lambda_;
1082  T edgeThreshold_;
1083  T scale_;
1084  };
1085 
1086  } // namespace detail_graph_smoothing
1087 
1088 
1089  /// \brief smooth node features of a graph
1090  ///
1091  /// \param g : input graph
1092  /// \param nodeFeaturesIn : input node features which should be smoothed
1093  /// \param edgeIndicator : edge indicator to indicate over which edges one should smooth
1094  /// \param lambda : scale edge indicator by lambda before taking negative exponent
1095  /// \param edgeThreshold : edge threshold
1096  /// \param scale : how much smoothing should be applied
1097  /// \param[out] nodeFeaturesOut : smoothed node features
1098  template<class GRAPH, class NODE_FEATURES_IN,class EDGE_INDICATOR,class NODE_FEATURES_OUT>
1100  const GRAPH & g,
1101  const NODE_FEATURES_IN & nodeFeaturesIn,
1102  const EDGE_INDICATOR & edgeIndicator,
1103  const float lambda,
1104  const float edgeThreshold,
1105  const float scale,
1106  NODE_FEATURES_OUT & nodeFeaturesOut
1107  ){
1108  detail_graph_smoothing::ExpSmoothFactor<float> functor(lambda,edgeThreshold,scale);
1109  detail_graph_smoothing::graphSmoothingImpl(g,nodeFeaturesIn,edgeIndicator,functor,nodeFeaturesOut);
1110  }
1111 
1112  /// \brief smooth node features of a graph
1113  ///
1114  /// \param g : input graph
1115  /// \param nodeFeaturesIn : input node features which should be smoothed
1116  /// \param edgeIndicator : edge indicator to indicate over which edges one should smooth
1117  /// \param lambda : scale edge indicator by lambda before taking negative exponent
1118  /// \param edgeThreshold : edge threshold
1119  /// \param scale : how much smoothing should be applied
1120  /// \param iterations : how often should this algorithm be called recursively
1121  /// \param[out] nodeFeaturesBuffer : preallocated(!) buffer to store node features temp.
1122  /// \param[out] nodeFeaturesOut : smoothed node features
1123  template<class GRAPH, class NODE_FEATURES_IN,class EDGE_INDICATOR,class NODE_FEATURES_OUT>
1125  const GRAPH & g,
1126  const NODE_FEATURES_IN & nodeFeaturesIn,
1127  const EDGE_INDICATOR & edgeIndicator,
1128  const float lambda,
1129  const float edgeThreshold,
1130  const float scale,
1131  size_t iterations,
1132  NODE_FEATURES_OUT & nodeFeaturesBuffer,
1133  NODE_FEATURES_OUT & nodeFeaturesOut
1134  ){
1135 
1136  iterations = std::max(size_t(1),iterations);
1137  // initial run
1138  graphSmoothing(g,nodeFeaturesIn,edgeIndicator,lambda,edgeThreshold,scale,nodeFeaturesOut);
1139  iterations -=1;
1140 
1141  bool outAsIn=true;
1142  for(size_t i=0;i<iterations;++i){
1143  if(outAsIn){
1144  graphSmoothing(g,nodeFeaturesOut,edgeIndicator,lambda,edgeThreshold,scale,nodeFeaturesBuffer);
1145  outAsIn=false;
1146  }
1147  else{
1148  graphSmoothing(g,nodeFeaturesBuffer,edgeIndicator,lambda,edgeThreshold,scale,nodeFeaturesOut);
1149  outAsIn=true;
1150  }
1151  }
1152  if(!outAsIn){
1153  copyNodeMap(g,nodeFeaturesBuffer,nodeFeaturesOut);
1154  }
1155  }
1156 
1157 
1158  template<class GRAPH, class NODE_MAP, class EDGE_MAP>
1159  void nodeGtToEdgeGt(
1160  const GRAPH & g,
1161  const NODE_MAP & nodeGt,
1162  const Int64 ignoreLabel,
1163  EDGE_MAP & edgeGt
1164  ){
1165  typedef typename GRAPH::Node Node;
1166  typedef typename GRAPH::EdgeIt EdgeIt;
1167  typedef typename GRAPH::Edge Edge;
1168 
1169  for(EdgeIt edgeIt(g); edgeIt!=lemon::INVALID; ++edgeIt){
1170  const Edge edge(*edgeIt);
1171  const Node u = g.u(edge);
1172  const Node v = g.v(edge);
1173 
1174  const Int64 lU = static_cast<Int64>(nodeGt[u]);
1175  const Int64 lV = static_cast<Int64>(nodeGt[v]);
1176 
1177  if(ignoreLabel==-1 || (lU!=ignoreLabel || lV!=ignoreLabel)){
1178  edgeGt[edge] = lU == lV ? 0 : 1;
1179  }
1180  else{
1181  edgeGt[edge] = 2;
1182  }
1183  }
1184  }
1185 
1186 
1187 
1188 
1189 
1190 
1191  /// project ground truth from a base graph, to a region adjacency graph.
1192  ///
1193  ///
1194  ///
1195  ///
1196  template<class RAG, class BASE_GRAPH, class BASE_GRAPH_RAG_LABELS,
1197  class BASE_GRAPH_GT, class RAG_GT, class RAG_GT_QT>
1199  const RAG & rag,
1200  const BASE_GRAPH & baseGraph,
1201  const BASE_GRAPH_RAG_LABELS & baseGraphRagLabels,
1202  const BASE_GRAPH_GT & baseGraphGt,
1203  RAG_GT & ragGt,
1204  RAG_GT_QT &
1205  ){
1206  typedef typename BASE_GRAPH::Node BaseGraphNode;
1207  typedef typename BASE_GRAPH::NodeIt BaseGraphNodeIt;
1208  typedef typename RAG::NodeIt RagNodeIt;
1209  typedef typename RAG::Node RagNode;
1210  typedef typename BASE_GRAPH_RAG_LABELS::Value BaseRagLabelType;
1211  typedef typename BASE_GRAPH_GT::Value GtLabelType;
1212  typedef typename RAG_GT::Value RagGtLabelType;
1213 
1214  // overlap map
1215  typedef std::map<GtLabelType,UInt32> MapType;
1216  typedef typename MapType::const_iterator MapIter;
1217  typedef typename RAG:: template NodeMap<MapType> Overlap;
1218  Overlap overlap(rag);
1219 
1220  size_t i=0;
1221  //::cout<<"\n";
1222  for(BaseGraphNodeIt baseNodeIter(baseGraph); baseNodeIter!=lemon::INVALID; ++baseNodeIter , ++i ){
1223 
1224  //if (i%2000 == 0){
1225  // std::cout<<"\r"<<std::setw(10)<< float(i)/float(baseGraph.nodeNum())<<std::flush;
1226  //}
1227 
1228  const BaseGraphNode baseNode = *baseNodeIter;
1229 
1230  // get gt label
1231  const GtLabelType gtLabel = baseGraphGt[baseNode];
1232 
1233  // get the label which generated rag
1234  // (node mapping from bg-node to rag-node-id)
1235  const BaseRagLabelType bgRagLabel = baseGraphRagLabels[baseNode];
1236  const RagNode ragNode = rag.nodeFromId(bgRagLabel);
1237 
1238  // fill overlap
1239  overlap[ragNode][gtLabel]+=1;
1240  }
1241  //std::cout<<"\n";
1242  // select label with max overlap
1243  for(RagNodeIt ragNodeIter(rag); ragNodeIter!=lemon::INVALID; ++ragNodeIter ){
1244  const RagNode ragNode = *ragNodeIter;
1245  const MapType olMap = overlap[ragNode];
1246  UInt32 olSize=0;
1247  RagGtLabelType bestLabel = 0;
1248  for(MapIter olIter = olMap.begin(); olIter!=olMap.end(); ++olIter ){
1249  if(olIter->second > olSize){
1250  olSize = olIter->second;
1251  bestLabel = olIter->first;
1252  }
1253  }
1254  ragGt[ragNode]=bestLabel;
1255  }
1256  }
1257 
1258 
1259 
1260  /// \brief Find indices of points on the edges
1261  ///
1262  /// \param rag : Region adjacency graph of the labels array
1263  /// \param graph : Graph of labels array
1264  /// \param affiliatedEdges : The affiliated edges of the region adjacency graph
1265  /// \param labelsArray : The label image
1266  /// \param node : The node (of the region adjacency graph), whose edges shall be found
1267  template<class RAGGRAPH, class GRAPH, class RAGEDGES, unsigned int N, class T>
1269  const RAGGRAPH & rag,
1270  const GRAPH & graph,
1271  const RAGEDGES & affiliatedEdges,
1272  MultiArrayView<N, T> labelsArray,
1273  const typename RAGGRAPH::Node & node
1274  ){
1275  typedef typename GRAPH::Node Node;
1276  typedef typename GRAPH::Edge Edge;
1277  typedef typename RAGGRAPH::OutArcIt RagOutArcIt;
1278  typedef typename RAGGRAPH::Edge RagEdge;
1279  typedef typename GraphDescriptorToMultiArrayIndex<GRAPH>::IntrinsicNodeMapShape NodeCoordinate;
1280 
1281  T nodeLabel = rag.id(node);
1282 
1283  // Find edges and write them into a set.
1284  std::set< NodeCoordinate > edgeCoordinates;
1285  for (RagOutArcIt iter(rag, node); iter != lemon::INVALID; ++iter)
1286  {
1287  const RagEdge ragEdge(*iter);
1288  const std::vector<Edge> & affEdges = affiliatedEdges[ragEdge];
1289  for (int i=0; i<affEdges.size(); ++i)
1290  {
1291  Node u = graph.u(affEdges[i]);
1292  Node v = graph.v(affEdges[i]);
1293  T uLabel = labelsArray[u];
1294  T vLabel = labelsArray[v];
1295 
1296  NodeCoordinate coords;
1297  if (uLabel == nodeLabel)
1298  {
1299  coords = GraphDescriptorToMultiArrayIndex<GRAPH>::intrinsicNodeCoordinate(graph, u);
1300  }
1301  else if (vLabel == nodeLabel)
1302  {
1303  coords = GraphDescriptorToMultiArrayIndex<GRAPH>::intrinsicNodeCoordinate(graph, v);
1304  }
1305  else
1306  {
1307  vigra_precondition(false, "You should not come to this part of the code.");
1308  }
1309  edgeCoordinates.insert(coords);
1310  }
1311  }
1312 
1313  // Fill the return array.
1314  MultiArray<2, MultiArrayIndex> edgePoints(Shape2(edgeCoordinates.size(), N));
1315  edgePoints.init(0);
1316  int next = 0;
1317  typedef typename std::set< NodeCoordinate >::iterator setIter;
1318  for (setIter iter = edgeCoordinates.begin(); iter!=edgeCoordinates.end(); ++iter)
1319  {
1320  NodeCoordinate coords = *iter;
1321  for (int k=0; k<coords.size(); ++k)
1322  {
1323  edgePoints(next, k) = coords[k];
1324  }
1325  next++;
1326  }
1327  return edgePoints;
1328  }
1329  /// \brief create edge weights from node weights
1330  ///
1331  /// \param g : input graph
1332  /// \param nodeWeights : node property map holding node weights
1333  /// \param[out] edgeWeights : resulting edge weights
1334  /// \param euclidean : if 'true', multiply the computed weights with the Euclidean
1335  /// distance between the edge's end nodes (default: 'false')
1336  /// \param func : binary function that computes the edge weight from the
1337  /// weights of the edge's end nodes (default: take the average)
1338  template<unsigned int N, class DirectedTag,
1339  class NODEMAP, class EDGEMAP, class FUNCTOR>
1340  void
1342  const GridGraph<N, DirectedTag> & g,
1343  const NODEMAP & nodeWeights,
1344  EDGEMAP & edgeWeights,
1345  bool euclidean,
1346  FUNCTOR const & func)
1347  {
1348  typedef GridGraph<N, DirectedTag> Graph;
1349  typedef typename Graph::Edge Edge;
1350  typedef typename Graph::EdgeIt EdgeIt;
1351  typedef typename MultiArrayShape<N>::type CoordType;
1352 
1353  vigra_precondition(nodeWeights.shape() == g.shape(),
1354  "edgeWeightsFromNodeWeights(): shape mismatch between graph and nodeWeights.");
1355 
1356  for (EdgeIt iter(g); iter!=lemon::INVALID; ++iter)
1357  {
1358  const Edge edge(*iter);
1359  const CoordType uCoord(g.u(edge));
1360  const CoordType vCoord(g.v(edge));
1361  if (euclidean)
1362  {
1363  edgeWeights[edge] = norm(uCoord-vCoord) * func(nodeWeights[uCoord], nodeWeights[vCoord]);
1364  }
1365  else
1366  {
1367  edgeWeights[edge] = func(nodeWeights[uCoord], nodeWeights[vCoord]);
1368  }
1369  }
1370  }
1371 
1372  template<unsigned int N, class DirectedTag,
1373  class NODEMAP, class EDGEMAP>
1374  inline void
1376  const GridGraph<N, DirectedTag> & g,
1377  const NODEMAP & nodeWeights,
1378  EDGEMAP & edgeWeights,
1379  bool euclidean=false)
1380  {
1381  using namespace vigra::functor;
1382  edgeWeightsFromNodeWeights(g, nodeWeights, edgeWeights, euclidean, Param(0.5)*(Arg1()+Arg2()));
1383  }
1384 
1385 
1386  /// \brief create edge weights from an interpolated image
1387  ///
1388  /// \param g : input graph
1389  /// \param interpolatedImage : interpolated image
1390  /// \param[out] edgeWeights : edge weights
1391  /// \param euclidean : if 'true', multiply the weights with the Euclidean
1392  /// distance between the edge's end nodes (default: 'false')
1393  ///
1394  /// For each edge, the function reads the weight from <tt>interpolatedImage[u+v]</tt>,
1395  /// where <tt>u</tt> and <tt>v</tt> are the coordinates of the edge's end points.
1396  template<unsigned int N, class DirectedTag,
1397  class T, class EDGEMAP>
1398  void
1400  const GridGraph<N, DirectedTag> & g,
1401  const MultiArrayView<N, T> & interpolatedImage,
1402  EDGEMAP & edgeWeights,
1403  bool euclidean = false)
1404  {
1405  typedef GridGraph<N, DirectedTag> Graph;
1406  typedef typename Graph::Edge Edge;
1407  typedef typename Graph::EdgeIt EdgeIt;
1408  typedef typename MultiArrayShape<N>::type CoordType;
1409 
1410  vigra_precondition(interpolatedImage.shape() == 2*g.shape()-CoordType(1),
1411  "edgeWeightsFromInterpolatedImage(): interpolated shape must be shape*2-1");
1412 
1413  for (EdgeIt iter(g); iter!=lemon::INVALID; ++iter)
1414  {
1415  const Edge edge(*iter);
1416  const CoordType uCoord(g.u(edge));
1417  const CoordType vCoord(g.v(edge));
1418  if (euclidean)
1419  {
1420  edgeWeights[edge] = norm(uCoord-vCoord) * interpolatedImage[uCoord+vCoord];
1421  }
1422  else
1423  {
1424  edgeWeights[edge] = interpolatedImage[uCoord+vCoord];
1425  }
1426  }
1427  }
1428 
1429  template<class GRAPH>
1430  struct ThreeCycle{
1431 
1432  typedef typename GRAPH::Node Node;
1433 
1434  ThreeCycle(const Node & a, const Node & b, const Node c){
1435  nodes_[0] = a;
1436  nodes_[1] = b;
1437  nodes_[2] = c;
1438  std::sort(nodes_, nodes_+3);
1439  }
1440  bool operator < (const ThreeCycle & other)const{
1441  if(nodes_[0] < other.nodes_[0]){
1442  return true;
1443  }
1444  else if(nodes_[0] == other.nodes_[0]){
1445  if(nodes_[1] < other.nodes_[1]){
1446  return true;
1447  }
1448  else if(nodes_[1] == other.nodes_[1]){
1449  if(nodes_[2] < other.nodes_[2]){
1450  return true;
1451  }
1452  else{
1453  return false;
1454  }
1455  }
1456  else{
1457  return false;
1458  }
1459  }
1460  else{
1461  return false;
1462  }
1463  }
1464 
1465  Node nodes_[3];
1466 
1467 
1468  };
1469 
1470 
1471  template<class GRAPH>
1472  void find3Cycles(
1473  const GRAPH & g,
1474  MultiArray<1, TinyVector<Int32, 3> > & cyclesArray
1475  ){
1476  typedef typename GRAPH::Node Node;
1477  typedef typename GRAPH::Edge Edge;
1478  typedef typename GRAPH::EdgeIt EdgeIt;
1479  typedef typename GRAPH::OutArcIt OutArcIt;
1480 
1481  typedef ThreeCycle<GRAPH> Cycle;
1482 
1483  std::set< Cycle > cycles;
1484  typedef typename std::set<Cycle>::const_iterator SetIter;
1485  for (EdgeIt iter(g); iter!=lemon::INVALID; ++iter){
1486  const Edge edge(*iter);
1487  const Node u = g.u(edge);
1488  const Node v = g.v(edge);
1489 
1490  // find a node n which is connected to u and v
1491  for(OutArcIt outArcIt(g,u); outArcIt!=lemon::INVALID;++outArcIt){
1492  const Node w = g.target(*outArcIt);
1493  if(w != v){
1494  const Edge e = g.findEdge(w,v);
1495  if(e != lemon::INVALID){
1496  // found cycle
1497  cycles.insert(Cycle(u, v, w));
1498  }
1499  }
1500  }
1501  }
1502  cyclesArray.reshape(TinyVector<UInt32,1>(cycles.size()));
1503  UInt32 i=0;
1504  for(SetIter iter=cycles.begin(); iter!=cycles.end(); ++iter){
1505 
1506  const Cycle & c = *iter;
1507  for(size_t j=0;j<3; ++j){
1508  cyclesArray(i)[j] = g.id(c.nodes_[j]);
1509  }
1510  ++i;
1511  }
1512  }
1513 
1514  template<class GRAPH>
1515  void find3CyclesEdges(
1516  const GRAPH & g,
1517  MultiArray<1, TinyVector<Int32, 3> > & cyclesArray
1518  ){
1519  typedef typename GRAPH::Node Node;
1520  typedef typename GRAPH::Edge Edge;
1521  typedef typename GRAPH::EdgeIt EdgeIt;
1522  typedef typename GRAPH::OutArcIt OutArcIt;
1523 
1524  typedef ThreeCycle<GRAPH> Cycle;
1525 
1526  std::set< Cycle > cycles;
1527  typedef typename std::set<Cycle>::const_iterator SetIter;
1528  for (EdgeIt iter(g); iter!=lemon::INVALID; ++iter){
1529  const Edge edge(*iter);
1530  const Node u = g.u(edge);
1531  const Node v = g.v(edge);
1532 
1533  // find a node n which is connected to u and v
1534  for(OutArcIt outArcIt(g,u); outArcIt!=lemon::INVALID;++outArcIt){
1535  const Node w = g.target(*outArcIt);
1536  if(w != v){
1537  const Edge e = g.findEdge(w,v);
1538  if(e != lemon::INVALID){
1539  // found cycle
1540  cycles.insert(Cycle(u, v, w));
1541  }
1542  }
1543  }
1544  }
1545  cyclesArray.reshape(TinyVector<UInt32,1>(cycles.size()));
1546  UInt32 i=0;
1547  for(SetIter iter=cycles.begin(); iter!=cycles.end(); ++iter){
1548 
1549  const Cycle & c = *iter;
1550  const Node u = c.nodes_[0];
1551  const Node v = c.nodes_[1];
1552  const Node w = c.nodes_[2];
1553 
1554  cyclesArray(i)[0] = g.id(g.findEdge(u, v));
1555  cyclesArray(i)[1] = g.id(g.findEdge(u, w));
1556  cyclesArray(i)[2] = g.id(g.findEdge(v, w));
1557  ++i;
1558  }
1559  }
1560 
1561 //@}
1562 
1563 } // namespace vigra
1564 
1565 #endif // VIGRA_GRAPH_ALGORITHMS_HXX
vigra::GridGraph< N, DirectedTag >::degree_size_type degree(typename vigra::GridGraph< N, DirectedTag >::vertex_descriptor const &v, vigra::GridGraph< N, DirectedTag > const &g)
Return total number of edges (incoming and outgoing) of vertex v (API: boost).
Definition: multi_gridgraph.hxx:2828
Define a grid graph in arbitrary dimensions.
Definition: multi_fwd.hxx:217
const Node & target() const
get the target node
Definition: graph_algorithms.hxx:427
bool empty() const
check if the PQ is empty
Definition: priority_queue.hxx:444
reference back()
Definition: array_vector.hxx:321
void initMultiArrayBorder(...)
Write values to the specified border values in the array.
vigra::GridGraph< N, DirectedTag >::vertex_descriptor target(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the end vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2954
void run(Node const &start, Node const &stop, const WEIGHTS &weights, const Node &source, const Node &target=lemon::INVALID, WeightType maxDistance=NumericTraits< WeightType >::max())
run shortest path in a region of interest of a GridGraph.
Definition: graph_algorithms.hxx:356
void fillNodeMap(const G &g, A &a, const T &value)
fill a lemon node map
Definition: graph_algorithms.hxx:136
const difference_type & shape() const
Definition: multi_array.hxx:1648
void projectGroundTruth(const RAG &rag, const BASE_GRAPH &baseGraph, const BASE_GRAPH_RAG_LABELS &baseGraphRagLabels, const BASE_GRAPH_GT &baseGraphGt, RAG_GT &ragGt, RAG_GT_QT &)
Definition: graph_algorithms.hxx:1198
Node nodeFromId(const index_type id) const
Get node descriptor for given node ID i (API: LEMON). Return Node(lemon::INVALID) when the ID does no...
linalg::TemporaryMatrix< T > exp(MultiArrayView< 2, T, C > const &v)
MultiArray< 2, MultiArrayIndex > ragFindEdges(const RAGGRAPH &rag, const GRAPH &graph, const RAGEDGES &affiliatedEdges, MultiArrayView< N, T > labelsArray, const typename RAGGRAPH::Node &node)
Find indices of points on the edges.
Definition: graph_algorithms.hxx:1268
void pop()
Remove the current top element.
Definition: priority_queue.hxx:502
void shortestPathAStar(const GRAPH &graph, const typename GRAPH::Node &source, const typename GRAPH::Node &target, const WEIGHTS &weights, PREDECESSORS &predecessors, DISTANCE &distance, const HEURSTIC &heuristic)
Astar Shortest path search.
Definition: graph_algorithms.hxx:611
detail::GenericEdge< index_type > Edge
edge descriptor
Definition: adjacency_list_graph.hxx:249
const Node & source() const
get the source node
Definition: graph_algorithms.hxx:423
Main MultiArray class containing the memory management.
Definition: multi_array.hxx:2474
bool contains(const int i) const
check if i is an index on the PQ
Definition: priority_queue.hxx:459
void felzenszwalbSegmentation(const GRAPH &graph, const EDGE_WEIGHTS &edgeWeights, const NODE_SIZE &nodeSizes, float k, NODE_LABEL_MAP &nodeLabeling, const int nodeNumStopCond=-1)
edge weighted watersheds Segmentataion
Definition: graph_algorithms.hxx:916
void edgeWeightsFromNodeWeights(const GridGraph< N, DirectedTag > &g, const NODEMAP &nodeWeights, EDGEMAP &edgeWeights, bool euclidean, FUNCTOR const &func)
create edge weights from node weights
Definition: graph_algorithms.hxx:1341
bool allLess(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise less-than
Definition: tinyvector.hxx:1375
undirected adjacency list graph in the LEMON API
Definition: adjacency_list_graph.hxx:227
Node v(Edge const &e) const
Get the end node of the given edge e (API: LEMON, the boost::graph API provides the free function bo...
Definition: multi_gridgraph.hxx:2390
const DistanceMap & distances() const
get the distances node map (after a call of run)
Definition: graph_algorithms.hxx:447
detail::SelectIntegerType< 64, detail::SignedIntTypes >::type Int64
64-bit signed int
Definition: sized_int.hxx:177
void recursiveGraphSmoothing(const GRAPH &g, const NODE_FEATURES_IN &nodeFeaturesIn, const EDGE_INDICATOR &edgeIndicator, const float lambda, const float edgeThreshold, const float scale, size_t iterations, NODE_FEATURES_OUT &nodeFeaturesBuffer, NODE_FEATURES_OUT &nodeFeaturesOut)
smooth node features of a graph
Definition: graph_algorithms.hxx:1124
FFTWComplex< R >::NormType norm(const FFTWComplex< R > &a)
norm (= magnitude)
Definition: fftw3.hxx:1037
shortest path computer
Definition: graph_algorithms.hxx:297
void push(const value_type i, const priority_type p)
Insert a index with a given priority.
Definition: priority_queue.hxx:475
void copyNodeMap(const G &g, const A &a, B &b)
copy a lemon node map
Definition: graph_algorithms.hxx:117
MultiArray & init(const U &init)
Definition: multi_array.hxx:2851
void edgeWeightsFromInterpolatedImage(const GridGraph< N, DirectedTag > &g, const MultiArrayView< N, T > &interpolatedImage, EDGEMAP &edgeWeights, bool euclidean=false)
create edge weights from an interpolated image
Definition: graph_algorithms.hxx:1399
vigra::GridGraph< N, DirectedTag >::vertex_descriptor source(typename vigra::GridGraph< N, DirectedTag >::edge_descriptor const &e, vigra::GridGraph< N, DirectedTag > const &g)
Get a vertex descriptor for the start vertex of edge e in graph g (API: boost).
Definition: multi_gridgraph.hxx:2943
Node u(Edge const &e) const
Get the start node of the given edge e (API: LEMON, the boost::graph API provides the free function ...
Definition: multi_gridgraph.hxx:2382
void runMultiSource(const WEIGHTS &weights, ITER source_begin, ITER source_end, const Node &target=lemon::INVALID, WeightType maxDistance=NumericTraits< WeightType >::max())
run shortest path with given edge weights from multiple sources.
Definition: graph_algorithms.hxx:391
void copyEdgeMap(const G &g, const A &a, B &b)
copy a lemon edge map
Definition: graph_algorithms.hxx:127
size_t pathLength(const NODE source, const NODE target, const PREDECESSORS &predecessors)
get the length in node units of a path
Definition: graph_algorithms.hxx:591
bool hasTarget() const
check if explicit target is given
Definition: graph_algorithms.hxx:432
Class for fixed size vectors.This class contains an array of size SIZE of the specified VALUETYPE...
Definition: accessor.hxx:940
void fillEdgeMap(const G &g, A &a, const T &value)
fill a lemon edge map
Definition: graph_algorithms.hxx:145
void makeRegionAdjacencyGraph(GRAPH_IN graphIn, GRAPH_IN_NODE_LABEL_MAP labels, AdjacencyListGraph &rag, typename AdjacencyListGraph::template EdgeMap< std::vector< typename GRAPH_IN::Edge > > &affiliatedEdges, const Int64 ignoreLabel=-1)
make a region adjacency graph from a graph and labels w.r.t. that graph
Definition: graph_algorithms.hxx:165
void edgeSort(const GRAPH &g, const WEIGHTS &weights, const COMPERATOR &comperator, std::vector< typename GRAPH::Edge > &sortedEdges)
get a vector of Edge descriptors
Definition: graph_algorithms.hxx:98
std::pair< typename vigra::GridGraph< N, DirectedTag >::edge_descriptor, bool > edge(typename vigra::GridGraph< N, DirectedTag >::vertex_descriptor const &u, typename vigra::GridGraph< N, DirectedTag >::vertex_descriptor const &v, vigra::GridGraph< N, DirectedTag > const &g)
Return the pair (edge_descriptor, true) when an edge between vertices u and v exists, or (lemon::INVALID, false) otherwise (API: boost).
Definition: multi_gridgraph.hxx:2990
void carvingSegmentation(const GRAPH &g, const EDGE_WEIGHTS &edgeWeights, const SEEDS &seeds, const typename LABELS::Value backgroundLabel, const typename EDGE_WEIGHTS::Value backgroundBias, const typename EDGE_WEIGHTS::Value noPriorBelow, LABELS &labels)
edge weighted watersheds Segmentataion
Definition: graph_algorithms.hxx:892
bool operator<(FixedPoint< IntBits1, FracBits1 > l, FixedPoint< IntBits2, FracBits2 > r)
less than
Definition: fixedpoint.hxx:512
void edgeWeightedWatershedsSegmentation(const GRAPH &g, const EDGE_WEIGHTS &edgeWeights, const SEEDS &seeds, LABELS &labels)
edge weighted watersheds Segmentataion
Definition: graph_algorithms.hxx:871
void runMultiSource(const EFGE_WEIGHTS &edgeWeights, const NODE_WEIGHTS &nodeWeights, ITER source_begin, ITER source_end, const Node &target=lemon::INVALID, WeightType maxDistance=NumericTraits< WeightType >::max())
run shortest path with given edge weights from multiple sources.
Definition: graph_algorithms.hxx:406
detail::SelectIntegerType< 32, detail::UnsignedIntTypes >::type UInt32
32-bit unsigned int
Definition: sized_int.hxx:183
Edge findEdge(const Node &a, const Node &b) const
Get a descriptor for the edge connecting vertices u and v, or lemon::INVALID if no such edge exists (...
const_reference top() const
get index with top priority
Definition: priority_queue.hxx:490
const PredecessorsMap & predecessors() const
get the predecessors node map (after a call of run)
Definition: graph_algorithms.hxx:442
Base class for, and view to, vigra::MultiArray.
Definition: multi_array.hxx:704
void graphSmoothing(const GRAPH &g, const NODE_FEATURES_IN &nodeFeaturesIn, const EDGE_INDICATOR &edgeIndicator, const float lambda, const float edgeThreshold, const float scale, NODE_FEATURES_OUT &nodeFeaturesOut)
smooth node features of a graph
Definition: graph_algorithms.hxx:1099
bool allLessEqual(TinyVectorBase< V1, SIZE, D1, D2 > const &l, TinyVectorBase< V2, SIZE, D3, D4 > const &r)
pointwise less-equal
Definition: tinyvector.hxx:1399
size_type size() const
Definition: array_vector.hxx:358
void run(const WEIGHTS &weights, const Node &source, const Node &target=lemon::INVALID, WeightType maxDistance=NumericTraits< WeightType >::max())
run shortest path given edge weights
Definition: graph_algorithms.hxx:334
void reRun(const WEIGHTS &weights, const Node &source, const Node &target=lemon::INVALID, WeightType maxDistance=NumericTraits< WeightType >::max())
run shortest path again with given edge weights
Definition: graph_algorithms.hxx:377
detail_adjacency_list_graph::ItemIter< GraphType, Edge > EdgeIt
edge iterator
Definition: adjacency_list_graph.hxx:253
const Graph & graph() const
get the graph
Definition: graph_algorithms.hxx:419
WeightType distance(const Node &target) const
get the distance to a rarget node (after a call of run)
Definition: graph_algorithms.hxx:452
ShortestPathDijkstra(const Graph &g)
\ brief constructor from graph
Definition: graph_algorithms.hxx:313
const DiscoveryOrder & discoveryOrder() const
get an array with all visited nodes, sorted by distance from source
Definition: graph_algorithms.hxx:437

© Ullrich Köthe (ullrich.koethe@iwr.uni-heidelberg.de)
Heidelberg Collaboratory for Image Processing, University of Heidelberg, Germany

html generated using doxygen and Python
vigra 1.11.1 (Fri May 19 2017)