1 #ifndef OPENGM_PERMUTABLE_LABEL_FUSION_MOVER_HXX 2 #define OPENGM_PERMUTABLE_LABEL_FUSION_MOVER_HXX 12 #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) 24 #ifndef WITH_BOOST_GRAPH 25 #define WITH_BOOST_GRAPH 29 #include <vigra/adjacency_list_graph.hxx> 30 #include <vigra/merge_graph_adaptor.hxx> 31 #include <vigra/hierarchical_clustering.hxx> 32 #include <vigra/priority_queue.hxx> 33 #include <vigra/random.hxx> 34 #include <vigra/graph_algorithms.hxx> 47 template<
class GM,
class ACC >
54 typedef vigra::AdjacencyListGraph
Graph;
58 typedef typename MergeGraph::Edge
Edge;
67 const float stopWeight = 0.0
77 MergeGraph & mergegraph,
79 std::vector<ValueType> & weights
88 for(
size_t i=0; i<
graph_.edgeNum(); ++i){
105 index_type minLabel =
pq_.top();
107 pq_.deleteItem(minLabel);
108 minLabel =
pq_.top();
110 return Edge(minLabel);
115 index_type minLabel =
pq_.top();
117 pq_.deleteItem(minLabel);
118 minLabel =
pq_.top();
120 return pq_.topPriority();
136 pq_.deleteItem(b.id());
140 pq_.deleteItem(edge.id());
145 vigra::ChangeablePriorityQueue< ValueType ,std::greater<ValueType> >
pq_;
157 template<
class GM,
class ACC>
165 typedef std::map<UInt64Type, ValueType>
MapType;
184 const FusionSolver fusionSolver = SelfType::DefaultSolver,
185 const bool planar =
false,
186 const std::string workflow = std::string(),
187 const int nThreads = 1,
188 const bool decompose =
false,
189 const std::vector<bool> & allowCutsWithin = std::vector<bool>()
192 fusionSolver_(fusionSolver),
196 decompose_(decompose),
197 allowCutsWithin_(allowCutsWithin)
221 if(
param_.fusionSolver_ == DefaultSolver){
224 param_.fusionSolver_ = MulticutSolver;
227 if(
param_.fusionSolver_ == DefaultSolver){
228 #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) 229 param_.fusionSolver_ = CgcSolver;
232 if(
param_.fusionSolver_ == DefaultSolver){
235 param_.fusionSolver_ = HierachicalClusteringSolver;
239 if(
param_.fusionSolver_ == DefaultSolver){
240 throw RuntimeError(
"WITH_CLEX || defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) must be enabled");
243 else if(
param_.fusionSolver_ == MulticutSolver){
245 throw RuntimeError(
"WITH_CLEX must be enabled for this fusionSolver");
248 else if(
param_.fusionSolver_ == CgcSolver){
249 #if ! (defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) ) 250 throw RuntimeError(
"defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) must be enabled for this fusionSolver");
253 else if(
param_.fusionSolver_ == HierachicalClusteringSolver){
255 throw RuntimeError(
"WITH_VIGRA must be enabled for this fusionSolver");
265 const size_t numberOfLabels = nx*ny;
268 for(
size_t y = 0; y < ny; ++y){
270 for(
size_t x = 0; x < nx; ++x) {
271 std::cout<<arg[i]<<
" ";
281 const std::vector<LabelType> & a,
282 const std::vector<LabelType> & b,
283 std::vector<LabelType> & res
286 for(
size_t fi=0; fi< gm_.numberOfFactors(); ++fi){
287 if(gm_[fi].numberOfVariables()==2){
289 const size_t vi0 = gm_[fi].variableIndex(0);
290 const size_t vi1 = gm_[fi].variableIndex(1);
294 if(a[vi0] == a[vi1] && b[vi0] == b[vi1]){
298 else if(gm_[fi].numberOfVariables()==1){
302 throw RuntimeError(
"only implemented for second order");
305 std::map<LabelType, LabelType> repr;
306 ufd.representativeLabeling(repr);
307 for(
size_t vi=0; vi<gm_.numberOfVariables(); ++vi){
308 res[vi]=repr[ufd.find(vi)];
317 return ufd.numberOfSets();
321 const std::vector<LabelType> & a,
322 const std::vector<LabelType> & b,
323 std::vector<LabelType> & res,
324 const ValueType valA,
325 const ValueType valB,
329 if(
param_.fusionSolver_ == ClassicFusion)
330 return fuseClassic(a,b,res,valA,valB,valRes);
332 std::vector<LabelType> ab(gm_.numberOfVariables());
333 IndexType numNewVar = this->intersect(a, b, ab);
340 const ValueType intersectedVal = gm_.evaluate(ab);
348 size_t erasedEdges = 0;
349 size_t notErasedEdges = 0;
358 for(
size_t fi=0; fi< gm_.numberOfFactors(); ++fi){
359 if(gm_[fi].numberOfVariables()==2){
360 const size_t vi0 = gm_[fi].variableIndex(0);
361 const size_t vi1 = gm_[fi].variableIndex(1);
363 const size_t cVi0 = ab[vi0] < ab[vi1] ? ab[vi0] : ab[vi1];
364 const size_t cVi1 = ab[vi0] < ab[vi1] ? ab[vi1] : ab[vi0];
377 ValueType val00 = gm_[fi](lAA);
378 ValueType val01 = gm_[fi](lAB);
379 ValueType weight = val01 - val00;
387 MapIter iter = accWeights.find(key);
390 if(iter == accWeights.end()){
391 accWeights[key] = weight;
395 iter->second += weight;
402 OPENGM_CHECK_OP(erasedEdges+notErasedEdges, == , gm_.numberOfFactors(),
"something wrong");
411 if(
param_.fusionSolver_ == CgcSolver){
412 return doMoveCgc(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
414 else if(
param_.fusionSolver_ == MulticutSolver){
415 return doMoveMulticut(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
417 else if(
param_.fusionSolver_ == MulticutNativeSolver){
418 return doMoveMulticutNative(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
420 else if(
param_.fusionSolver_ == HierachicalClusteringSolver){
421 return doMoveHierachicalClustering(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
423 else if(
param_.fusionSolver_ == BaseSolver){
424 return doMoveBase(accWeights,ab,numNewVar, a, b, res, valA, valB, valRes);
435 const std::vector<LabelType> & a,
436 const std::vector<LabelType> & b,
437 std::vector<LabelType> & res,
438 const ValueType valA,
439 const ValueType valB,
442 LabelType maxL = *std::max_element(a.begin(), a.end());
443 std::vector<LabelType> bb = b;
444 for(
size_t i=0; i<bb.size(); ++i){
449 hlf.
fuse(a,b,res, valA, valB, valRes);
451 std::map<LabelType, LabelType> mdense;
454 for(
size_t i=0;i<res.size(); ++i){
456 if(mdense.find(resL) == mdense.end()){
461 res[i] = mdense[res[i]];
464 valRes = gm_.evaluate(res);
465 if(valRes< std::min(valA,valB)){
467 std::map<LabelType, LabelType> mdense;
470 for(
size_t i=0;i<res.size(); ++i){
472 if(mdense.find(resL) == mdense.end()){
477 res[i] = mdense[res[i]];
481 else if(valA<valRes){
496 const MapType & accWeights,
497 const std::vector<LabelType> & ab,
498 const IndexType numNewVar,
499 const std::vector<LabelType> & a,
500 const std::vector<LabelType> & b,
501 std::vector<LabelType> & res,
502 const ValueType valA,
503 const ValueType valB,
506 #if defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5)) 509 SubSpace subSpace(numNewVar, numNewVar);
510 SubModel subGm(subSpace);
513 subGm.
template reserveFunctions<PFunction>(accWeights.size());
517 for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
519 const ValueType weight = i->second;
525 PFunction pf(numNewVar, numNewVar, 0.0, weight);
529 std::vector<LabelType> subArg;
533 typedef typename Inf::Parameter Param;
536 p.planar_ =
param_.planar_;
542 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
543 res[vi] = subArg[ab[vi]];
545 const ValueType resultVal = subGm.
evaluate(subArg);
546 const ValueType projectedResultVal = gm_.evaluate(res);
547 const std::vector<LabelType> & bestArg = valA < valB ? a : b;
548 const ValueType bestProposalVal = valA < valB ? valA : valB;
550 valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
551 if(projectedResultVal < bestProposalVal){
557 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
558 res[vi] = bestArg[vi];
563 throw RuntimeError(
"defined(WITH_QPBO) || (defined(WITH_PLANARITY) && defined(WITH_BLOSSOM5))");
569 const MapType & accWeights,
570 const std::vector<LabelType> & ab,
571 const IndexType numNewVar,
572 const std::vector<LabelType> & a,
573 const std::vector<LabelType> & b,
574 std::vector<LabelType> & res,
575 const ValueType valA,
576 const ValueType valB,
579 const std::vector<LabelType> & bestArg = valA < valB ? a : b;
580 valRes = valA < valB ? valA : valB;
581 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
582 res[vi] = bestArg[vi];
588 const MapType & accWeights,
589 const std::vector<LabelType> & ab,
590 const IndexType numNewVar,
591 const std::vector<LabelType> & a,
592 const std::vector<LabelType> & b,
593 std::vector<LabelType> & res,
594 const ValueType valA,
595 const ValueType valB,
600 SubSpace subSpace(numNewVar, numNewVar);
601 SubModel subGm(subSpace);
604 subGm.
template reserveFunctions<PFunction>(accWeights.size());
608 for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
610 const ValueType weight = i->second;
616 PFunction pf(numNewVar, numNewVar, 0.0, weight);
620 std::vector<LabelType> subArg;
625 typedef typename McInf::Parameter McParam;
628 if(
param_.nThreads_ <= 0){
632 pmc.numThreads_ =
param_.nThreads_;
634 pmc.workFlow_ =
param_.workflow_;
637 if(
param_.decompose_ ==
false){
638 McInf inf(subGm,pmc);
644 typedef typename DmcInf::Parameter DmcParam;
645 typedef typename DmcInf::InfParam DmcInfParam;
647 DmcInfParam dmcInfParam(pmc);
649 dmcParam.infParam_ = dmcInfParam;
651 DmcInf inf(subGm, dmcParam);
660 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
661 res[vi] = subArg[ab[vi]];
663 const ValueType resultVal = subGm.
evaluate(subArg);
664 const ValueType projectedResultVal = gm_.evaluate(res);
665 const std::vector<LabelType> & bestArg = valA < valB ? a : b;
666 const ValueType bestProposalVal = valA < valB ? valA : valB;
668 valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
669 if(projectedResultVal < bestProposalVal){
675 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
676 res[vi] = bestArg[vi];
688 const MapType & accWeights,
689 const std::vector<LabelType> & ab,
690 const IndexType numNewVar,
691 const std::vector<LabelType> & a,
692 const std::vector<LabelType> & b,
693 std::vector<LabelType> & res,
694 const ValueType valA,
695 const ValueType valB,
699 std::vector<LabelType> subArg;
703 typedef typename Inf::Parameter Param;
706 if(
param_.nThreads_ <= 0){
710 p.numThreads_ =
param_.nThreads_;
712 p.workFlow_ =
param_.workflow_;
714 Inf inf(numNewVar, accWeights, p);
720 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
721 res[vi] = subArg[ab[vi]];
724 const ValueType projectedResultVal = gm_.evaluate(res);
725 const std::vector<LabelType> & bestArg = valA < valB ? a : b;
726 const ValueType bestProposalVal = valA < valB ? valA : valB;
728 valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
729 if(projectedResultVal < bestProposalVal){
735 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
736 res[vi] = bestArg[vi];
747 const MapType & accWeights,
748 const std::vector<LabelType> & ab,
749 const IndexType numNewVar,
750 const std::vector<LabelType> & a,
751 const std::vector<LabelType> & b,
752 std::vector<LabelType> & res,
753 const ValueType valA,
754 const ValueType valB,
758 typedef vigra::AdjacencyListGraph
Graph;
759 typedef typename Graph::Edge
Edge;
760 typedef vigra::MergeGraphAdaptor< Graph >
MergeGraph;
762 typedef typename ClusterOp::Parameter ClusterOpParam;
763 typedef vigra::HierarchicalClusteringImpl< ClusterOp > HC;
764 typedef typename HC::Parameter HcParam;
766 std::vector<ValueType> weights(accWeights.size(),0.0);
768 Graph graph(numNewVar, accWeights.size());
769 for(MapCIter i = accWeights.begin(); i!=accWeights.end(); ++i){
771 const ValueType weight = i->second;
776 const Edge e = graph.addEdge(cVi0, cVi1);
777 weights[graph.id(e)] = weight;
780 MergeGraph mg(graph);
785 const ClusterOpParam clusterOpParam;
786 ClusterOp clusterOp(graph, mg, clusterOpParam, weights);
799 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
800 res[vi] = hc.reprNodeId(ab[vi]);
803 const ValueType projectedResultVal = gm_.evaluate(res);
804 const std::vector<LabelType> & bestArg = valA < valB ? a : b;
805 const ValueType bestProposalVal = valA < valB ? valA : valB;
807 valRes = bestProposalVal < projectedResultVal ? bestProposalVal : projectedResultVal;
808 if(projectedResultVal < bestProposalVal){
814 for(IndexType vi=0; vi<gm_.numberOfVariables(); ++vi){
815 res[vi] = bestArg[vi];
IndexType addFactor(const FunctionIdentifier &, ITERATOR, ITERATOR)
add a factor to the graphical model
MergeGraph & mergeGraph()
get a reference to the merge
McClusterOp(const Graph &graph, MergeGraph &mergegraph, const Parameter ¶m, std::vector< ValueType > &weights)
PermutableLabelFusionMove< GM, ACC > SelfType
vigra::AdjacencyListGraph Graph
SimpleDiscreteSpace< IndexType, LabelType > SubSpace
size_t intersect(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res)
FunctionIdentifier addFunction(const FUNCTION_TYPE &)
add a function to the graphical model
void merge(value_type, value_type)
Merge two sets.
FusionSolver fusionSolver_
Discrete space in which all variables have the same number of labels.
void printArg(const std::vector< LabelType > arg)
void reserveFactors(const size_t numF)
bool doMoveHierachicalClustering(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
std::vector< bool > allowCutsWithin_
detail_types::UInt64Type UInt64Type
uint64
MapType::const_iterator MapCIter
PermutableLabelFusionMove(const GraphicalModelType &gm, const Parameter ¶m=Parameter())
void mergeEdges(const Edge &a, const Edge &b)
PottsFunction< ValueType, IndexType, LabelType > PFunction
Parameter(const FusionSolver fusionSolver=SelfType::DefaultSolver, const bool planar=false, const std::string workflow=std::string(), const int nThreads=1, const bool decompose=false, const std::vector< bool > &allowCutsWithin=std::vector< bool >())
bool doMoveBase(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
WeightType contractionWeight()
get the edge weight of the edge which should be contracted next
bool doMoveMulticut(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
void reserveFactorsVarialbeIndices(const size_t size)
vigra::MergeGraphAdaptor< Graph > MergeGraph
bool doMoveMulticutNative(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
bool doMoveCgc(const MapType &accWeights, const std::vector< LabelType > &ab, const IndexType numNewVar, const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
bool fuse(const LabelVector &argA, const LabelVector argB, LabelVector &argRes, const ValueType valA, const ValueType valB, ValueType &valRes)
ExplicitFunction< ValueType, IndexType, LabelType > EFunction
std::map< UInt64Type, ValueType > MapType
#define OPENGM_CHECK_OP(A, OP, B, TXT)
Potts function for two variables.
std::vector< ValueType > & weights_
MapType::iterator MapIter
Disjoint set data structure with path compression.
bool fuse(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
ValueType evaluate(ITERATOR) const
evaluate the modeled function for a given labeling
void eraseEdge(const Edge &edge)
GraphicalModel< ValueType, Adder, OPENGM_TYPELIST_2(EFunction, PFunction), SubSpace > SubModel
Parameter(const float stopWeight=0.0)
bool fuseClassic(const std::vector< LabelType > &a, const std::vector< LabelType > &b, std::vector< LabelType > &res, const ValueType valA, const ValueType valB, ValueType &valRes)
vigra::ChangeablePriorityQueue< ValueType,std::greater< ValueType > > pq_