GCoptimization.h
Go to the documentation of this file.
00001 /*
00002 ##############################################################################
00003 #                                                                            #
00004 #    GCoptimization - software for energy minimization with graph cuts       #
00005 #                        Version 3.0                                         #
00006 #    http://www.csd.uwo.ca/faculty/olga/software.html                        #
00007 #                                                                            #
00008 #    Copyright 2007-2010 Olga Veksler (olga@csd.uwo.ca)                      #
00009 #                        Andrew Delong (andrew.delong@gmail.com)             #
00010 #                                                                            #
00011 ##############################################################################
00012 
00013   C++ requires at least Visual C++ 2005 (VC8) or GCC 4.03. Supports 32 or 64-bit.
00014   See matlab/README.TXT for bundled MATLAB wrapper and its documentation.
00015 
00016   IMPORTANT:
00017   To use this software, YOU MUST CITE the following in any resulting publication:
00018 
00019     [1] Efficient Approximate Energy Minimization via Graph Cuts.
00020         Y. Boykov, O. Veksler, R.Zabih. IEEE TPAMI, 20(12):1222-1239, Nov 2001.
00021 
00022     [2] What Energy Functions can be Minimized via Graph Cuts?
00023         V. Kolmogorov, R.Zabih. IEEE TPAMI, 26(2):147-159, Feb 2004. 
00024 
00025     [3] An Experimental Comparison of Min-Cut/Max-Flow Algorithms for 
00026         Energy Minimization in Vision. Y. Boykov, V. Kolmogorov. 
00027         IEEE TPAMI, 26(9):1124-1137, Sep 2004.
00028 
00029   Furthermore, if you use the label cost feature (setLabelCost), you should cite
00030 
00031     [4] Fast Approximate Energy Minimization with Label Costs. 
00032         A. Delong, A. Osokin, H. N. Isack, Y. Boykov. In CVPR, June 2010. 
00033 
00034   This software can be used only for research purposes. For commercial purposes, 
00035   be aware that there is a US patent on the main algorithm itself:
00036 
00037         R. Zabih, Y. Boykov, O. Veksler,
00038         "System and method for fast approximate energy minimization via graph cuts",
00039         United Stated Patent 6,744,923, June 1, 2004
00040 
00041   Together with this library implemented by O. Veksler, we provide, with the 
00042   permission of the V. Kolmogorov and Y. Boykov, the following two libraries:
00043 
00044   1) energy.h
00045      Developed by V. Kolmogorov, this implements the binary energy minimization 
00046      technique described in [2] above. We use this to implement the binary 
00047      energy minimization step for the alpha-expansion and swap algorithms. 
00048      The graph construction provided by "energy.h" is more efficient than 
00049      the original graph construction for alpha-expansion described in [1].
00050 
00051      Again, this software can be used only for research purposes. IF YOU USE 
00052      THIS SOFTWARE (energy.h), YOU SHOULD CITE THE AFOREMENTIONED PAPER [2] 
00053      IN ANY RESULTING PUBLICATION.
00054 
00055   2) maxflow.cpp, graph.cpp, graph.h, block.h
00056      Developed by Y. Boykov and V. Kolmogorov while at Siemens Corporate Research,
00057      algorithm [3] was later reimplemented by V. Kolmogorov based on open publications
00058      and we use his implementation here with permission.
00059 
00060   If you use either of these libraries for research purposes, you should cite
00061   the aforementioned papers in any resulting publication.
00062 
00063 ##################################################################
00064 
00065     License & disclaimer.
00066 
00067     Copyright 2007-2010 Olga Veksler  <olga@csd.uwo.ca>
00068                         Andrew Delong <andrew.delong@gmail.com>
00069 
00070     This software and its modifications can be used and distributed for 
00071     research purposes only. Publications resulting from use of this code
00072     must cite publications according to the rules given above. Only
00073     Olga Veksler has the right to redistribute this code, unless expressed
00074     permission is given otherwise. Commercial use of this code, any of 
00075     its parts, or its modifications is not permited. The copyright notices 
00076     must not be removed in case of any modifications. This Licence 
00077     commences on the date it is electronically or physically delivered 
00078     to you and continues in effect unless you fail to comply with any of 
00079     the terms of the License and fail to cure such breach within 30 days 
00080     of becoming aware of the breach, in which case the Licence automatically 
00081     terminates. This Licence is governed by the laws of Canada and all 
00082     disputes arising from or relating to this Licence must be brought 
00083     in Toronto, Ontario.
00084 
00085     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00086     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00087     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00088     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00089     OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00090     SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00091     LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00092     DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00093     THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00094     (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00095     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00096 
00097 ##################################################################
00098 */
00099 
00100 #ifndef __GCOPTIMIZATION_H__
00101 #define __GCOPTIMIZATION_H__
00102 // Due to quiet bugs in function template specialization, it is not 
00103 // safe to use earlier MS compilers. 
00104 #if defined(_MSC_VER) && _MSC_VER < 1400
00105 #error Requires Visual C++ 2005 (VC8) compiler or later.
00106 #endif
00107 
00108 #include "energy.h"
00109 #include "graph.cpp"
00110 #include "maxflow.cpp"
00111 #include <cstddef>
00113 // Utility functions, classes, and macros
00115 
00116 class GCException {
00117 public:
00118         const char* message;
00119         GCException( const char* m ): message(m) { }
00120         void Report();
00121 };
00122 
00123 #ifdef _WIN32
00124 typedef __int64 gcoclock_t;
00125 #else
00126 #include <ctime>
00127 typedef clock_t gcoclock_t;
00128 #endif
00129 extern "C" gcoclock_t gcoclock(); // fairly high-resolution timer... better than clock() when available
00130 extern "C" gcoclock_t GCO_CLOCKS_PER_SEC; // this variable will stay 0 until gcoclock() is called for the first time
00131 
00132 #ifdef _MSC_EXTENSIONS
00133 #define OLGA_INLINE __forceinline
00134 #else
00135 #define OLGA_INLINE inline
00136 #endif
00137 
00138 #ifndef GCO_MAX_ENERGYTERM
00139 #define GCO_MAX_ENERGYTERM 10000000  // maximum safe coefficient to avoid integer overflow
00140                                      // if a data/smooth/label cost term is larger than this,
00141                                      // the library will raise an exception
00142 #endif
00143 
00144 
00146 // GCoptimization class
00148 class LinkedBlockList;
00149 
00150 class GCoptimization
00151 {
00152 public: 
00153 #ifdef GCO_ENERGYTYPE32
00154         typedef int EnergyType;        // 32-bit energy total
00155 #else
00156         typedef long long EnergyType;  // 64-bit energy total
00157 #endif
00158         typedef int EnergyTermType;    // 32-bit energy terms
00159         typedef Energy<EnergyTermType,EnergyTermType,EnergyType> EnergyT;
00160         typedef EnergyT::Var VarID;
00161         typedef int LabelID;                     // Type for labels
00162         typedef VarID SiteID;                    // Type for sites
00163         typedef EnergyTermType (*SmoothCostFn)(SiteID s1, SiteID s2, LabelID l1, LabelID l2);
00164         typedef EnergyTermType (*DataCostFn)(SiteID s, LabelID l);
00165         typedef EnergyTermType (*SmoothCostFnExtra)(SiteID s1, SiteID s2, LabelID l1, LabelID l2,void *);
00166         typedef EnergyTermType (*DataCostFnExtra)(SiteID s, LabelID l,void *);
00167 
00168         GCoptimization(SiteID num_sites, LabelID num_labels);
00169         virtual ~GCoptimization();
00170 
00171         // Peforms expansion algorithm. Runs the number of iterations specified by max_num_iterations 
00172         // If no input specified,runs until convergence. Returns total energy of labeling. 
00173         EnergyType expansion(int max_num_iterations=-1);
00174 
00175         // Peforms  expansion on one label, specified by the input parameter alpha_label 
00176         bool alpha_expansion(LabelID alpha_label);
00177 
00178         // Peforms swap algorithm. Runs it the specified number of iterations. If no  
00179         // input is specified,runs until convergence                                  
00180         EnergyType swap(int max_num_iterations=-1);
00181 
00182         // Peforms  swap on a pair of labels, specified by the input parameters alpha_label, beta_label 
00183         void alpha_beta_swap(LabelID alpha_label, LabelID beta_label);
00184 
00185         // Peforms  swap on a pair of labels, specified by the input parameters alpha_label, beta_label 
00186         // only on the sitess in the specified arrays, alphaSites and betaSitess, and the array sizes  
00187         // are, respectively, alpha_size and beta_size                                                  
00188         void alpha_beta_swap(LabelID alpha_label, LabelID beta_label, SiteID *alphaSites, 
00189                                  SiteID alpha_size, SiteID *betaSites, SiteID beta_size);
00190 
00191         struct DataCostFunctor;      // use this class to pass a functor to setDataCost 
00192         struct SmoothCostFunctor;    // use this class to pass a functor to setSmoothCost 
00193 
00194         // Set cost for all (SiteID,LabelID) pairs. Default data cost is all zeros.
00195         void setDataCost(DataCostFn fn);
00196         void setDataCost(DataCostFnExtra fn, void *extraData);
00197         void setDataCost(EnergyTermType *dataArray);
00198         void setDataCost(SiteID s, LabelID l, EnergyTermType e); 
00199         void setDataCostFunctor(DataCostFunctor* f);
00200         struct DataCostFunctor {
00201                 virtual EnergyTermType compute(SiteID s, LabelID l) = 0;
00202         };
00203         // Set cost of assigning 'l' to a specific subset of sites.
00204         // The sites are listed as (SiteID,cost) pairs.
00205         struct SparseDataCost {
00206                 SiteID site;
00207                 EnergyTermType cost;
00208         };
00209         void setDataCost(LabelID l, SparseDataCost *costs, SiteID count);
00210 
00211         // Set cost for all (LabelID,LabelID) pairs; the actual smooth cost is then weighted
00212         // at each pair of on neighbors. Defaults to Potts model (0 if l1==l2, 1 otherwise)
00213         void setSmoothCost(SmoothCostFn fn);
00214         void setSmoothCost(SmoothCostFnExtra fn, void *extraData);
00215         void setSmoothCost(LabelID l1, LabelID l2, EnergyTermType e); 
00216         void setSmoothCost(EnergyTermType *smoothArray);
00217         void setSmoothCostFunctor(SmoothCostFunctor* f);
00218         struct SmoothCostFunctor {
00219                 virtual EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2) = 0;
00220         };
00221 
00222         // Sets the cost of using label in the solution. 
00223         // Set either as uniform cost, or an individual per-label cost.
00224         void setLabelCost(EnergyTermType cost);
00225         void setLabelCost(EnergyTermType* costArray);
00226         void setLabelSubsetCost(LabelID* labels, LabelID numLabels, EnergyTermType cost);
00227 
00228         // Returns current label assigned to input site 
00229         LabelID whatLabel(SiteID site);
00230         void    whatLabel(SiteID start, SiteID count, LabelID* labeling);
00231 
00232         // This function can be used to change the label of any site at any time      
00233         void setLabel(SiteID site, LabelID label);
00234 
00235         // setLabelOrder(false) sets the order to be not random; setLabelOrder(true) 
00236         //      sets the order to random. By default, the labels are visited in non-random order 
00237         //      for both the swap and alpha-expansion moves                         
00238         //      Note that srand() must be initialized with an appropriate seed in order for 
00239         //      random order to take effect!
00240         void setLabelOrder(bool isRandom);
00241         void setLabelOrder(const LabelID* order, LabelID size);
00242 
00243         // Returns total energy for the current labeling
00244         EnergyType compute_energy();
00245 
00246         // Returns separate Data, Smooth, and Label energy of current labeling 
00247         EnergyType giveDataEnergy();
00248         EnergyType giveSmoothEnergy();
00249         EnergyType giveLabelEnergy();
00250 
00251         // Returns number of sites/labels as specified in the constructor
00252         SiteID  numSites() const;
00253         LabelID numLabels() const;
00254 
00255         // Prints output to stdout during exansion/swap execution.
00256         //   0 => no output
00257         //   1 => cycle-level output (cycle number, current energy)
00258         //   2 => expansion-/swap-level output (label(s), current energy)
00259         void setVerbosity(int level) { m_verbosity = level; }
00260 
00261 protected:
00262         struct LabelCost {
00263                 ~LabelCost() { delete [] labels; }
00264                 EnergyTermType cost; 
00265                 bool active;     // flag indicates if this particular labelcost is in effect (i.e. wrt m_labeling)
00266                 VarID aux;
00267                 LabelCost* next; // global list of LabelSetCost records
00268                 LabelID numLabels;
00269                 LabelID* labels;
00270         };
00271 
00272         struct LabelCostIter {
00273                 LabelCost* node;
00274                 LabelCostIter* next; // local list of LabelSetCost records that contain this label
00275         };
00276 
00277         LabelID m_num_labels;
00278         SiteID  m_num_sites;
00279         LabelID *m_labeling;
00280         SiteID  *m_lookupSiteVar; // holds index of variable corresponding to site participating in a move,
00281                                   // -1 for nonparticipating site
00282         LabelID *m_labelTable;    // to figure out label order in which to do expansion/swaps
00283         int      m_stepsThisCycle;
00284         int      m_stepsThisCycleTotal;
00285         int      m_random_label_order;
00286         EnergyTermType* m_datacostIndividual;
00287         EnergyTermType* m_smoothcostIndividual;
00288         EnergyTermType* m_labelingDataCosts;
00289         SiteID*         m_labelCounts;
00290         SiteID*         m_activeLabelCounts;
00291         LabelCost*      m_labelcostsAll;
00292         LabelCostIter** m_labelcostsByLabel;
00293         int             m_labelcostCount;
00294         bool            m_labelingInfoDirty;
00295         int             m_verbosity;
00296 
00297         void*   m_datacostFn;
00298         void*   m_smoothcostFn;
00299         EnergyType m_beforeExpansionEnergy;
00300 
00301         SiteID *m_numNeighbors;              // holds num of neighbors for each site
00302         SiteID  m_numNeighborsTotal;         // holds total num of neighbor relationships
00303 
00304         EnergyType (GCoptimization::*m_giveSmoothEnergyInternal)();
00305         SiteID (GCoptimization::*m_queryActiveSitesExpansion)(LabelID, SiteID*);
00306         void (GCoptimization::*m_setupDataCostsExpansion)(SiteID,LabelID,EnergyT*,SiteID*);
00307         void (GCoptimization::*m_setupSmoothCostsExpansion)(SiteID,LabelID,EnergyT*,SiteID*);
00308         void (GCoptimization::*m_setupDataCostsSwap)(SiteID,LabelID,LabelID,EnergyT*,SiteID*);
00309         void (GCoptimization::*m_setupSmoothCostsSwap)(SiteID,LabelID,LabelID,EnergyT*,SiteID*);
00310         void (GCoptimization::*m_applyNewLabeling)(EnergyT*,SiteID*,SiteID,LabelID);
00311         void (GCoptimization::*m_updateLabelingDataCosts)();
00312 
00313         void (*m_datacostFnDelete)(void* f);
00314         void (*m_smoothcostFnDelete)(void* f);
00315         bool (GCoptimization::*m_solveSpecialCases)(EnergyType&);
00316 
00317         // returns a pointer to the neighbors of a site and the weights
00318         virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights)=0;
00319         virtual void finalizeNeighbors() = 0;
00320 
00321         struct DataCostFnFromArray {
00322                 DataCostFnFromArray(EnergyTermType* theArray, LabelID num_labels)
00323                         : m_array(theArray), m_num_labels(num_labels){}
00324                 OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l){return m_array[s*m_num_labels+l];}
00325         private:
00326                 const EnergyTermType* const m_array;
00327                 const LabelID m_num_labels;
00328         };
00329 
00330         struct DataCostFnFromFunction {
00331                 DataCostFnFromFunction(DataCostFn fn): m_fn(fn){}
00332                 OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l){return m_fn(s,l);}
00333         private:
00334                 const DataCostFn m_fn;
00335         };
00336 
00337         struct DataCostFnFromFunctionExtra {
00338                 DataCostFnFromFunctionExtra(DataCostFnExtra fn,void *extraData): m_fn(fn),m_extraData(extraData){}
00339                 OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l){return m_fn(s,l,m_extraData);}
00340         private:
00341                 const DataCostFnExtra m_fn;
00342                 void *m_extraData;
00343         };
00344 
00345         struct SmoothCostFnFromArray {
00346                 SmoothCostFnFromArray(EnergyTermType* theArray, LabelID num_labels)
00347                         : m_array(theArray), m_num_labels(num_labels){}
00348                 OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2){return m_array[l1*m_num_labels+l2];}
00349         private:
00350                 const EnergyTermType* const m_array;
00351                 const LabelID m_num_labels;
00352         };
00353 
00354         struct SmoothCostFnFromFunction {
00355                 SmoothCostFnFromFunction(SmoothCostFn fn)
00356                         : m_fn(fn){}
00357                 OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2){return m_fn(s1,s2,l1,l2);}
00358         private:
00359                 const SmoothCostFn m_fn;
00360         };
00361 
00362         struct SmoothCostFnFromFunctionExtra {
00363                 SmoothCostFnFromFunctionExtra(SmoothCostFnExtra fn,void *extraData)
00364                         : m_fn(fn),m_extraData(extraData){}
00365                 OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2){return m_fn(s1,s2,l1,l2,m_extraData);}
00366         private:
00367                 const SmoothCostFnExtra m_fn;
00368                 void *m_extraData;
00369         };
00370 
00371         struct SmoothCostFnPotts {
00372                 OLGA_INLINE EnergyTermType compute(SiteID, SiteID, LabelID l1, LabelID l2){return l1 != l2 ? 1 : 0;}
00373         };
00374 
00376         // DataCostFnSparse
00377         //   This data cost functor maintains a simple sparse structure
00378         //   to quickly find the cost associated with any (site,label) pair.
00380         class DataCostFnSparse {
00381                 // cLogSitesPerBucket basically controls the compression ratio
00382                 // of the sparse structure: 1 => a dense array, num_sites => a single sparse list.
00383                 // The amount (cLogSitesPerBucket - cLinearSearchSize) determines the maximum 
00384                 // number of binary search steps taken for a cost lookup for specific (site,label).
00385                 //
00386                 static const int cLogSitesPerBucket = 9;
00387                 static const int cSitesPerBucket = (1 << cLogSitesPerBucket); 
00388                 static const size_t    cDataCostPtrMask = ~(sizeof(SparseDataCost)-1);
00389                 static const ptrdiff_t cLinearSearchSize = 64/sizeof(SparseDataCost);
00390 
00391                 struct DataCostBucket {
00392                         const SparseDataCost* begin;
00393                         const SparseDataCost* end;     // one-past-the-last item in the range
00394                         const SparseDataCost* predict; // predicts the next cost to be needed
00395                 };
00396 
00397         public:
00398                 DataCostFnSparse(SiteID num_sites, LabelID num_labels);
00399                 DataCostFnSparse(const DataCostFnSparse& src);
00400                 ~DataCostFnSparse();
00401 
00402                 void           set(LabelID l, const SparseDataCost* costs, SiteID count);
00403                 EnergyTermType compute(SiteID s, LabelID l);
00404                 SiteID         queryActiveSitesExpansion(LabelID alpha_label, const LabelID* labeling, SiteID* activeSites);
00405 
00406                 class iterator {
00407                 public:
00408                         OLGA_INLINE iterator(): m_ptr(0) { }
00409                         OLGA_INLINE iterator& operator++() { m_ptr++; return *this; }
00410                         OLGA_INLINE SiteID         site() const { return m_ptr->site; }
00411                         OLGA_INLINE EnergyTermType cost() const { return m_ptr->cost; }
00412                         OLGA_INLINE bool      operator==(const iterator& b) const { return m_ptr == b.m_ptr; }
00413                         OLGA_INLINE bool      operator!=(const iterator& b) const { return m_ptr != b.m_ptr; }
00414                         OLGA_INLINE ptrdiff_t operator- (const iterator& b) const { return m_ptr  - b.m_ptr; }
00415                 private:
00416                         OLGA_INLINE iterator(const SparseDataCost* ptr): m_ptr(ptr) { }
00417                         const SparseDataCost* m_ptr;
00418                         friend class DataCostFnSparse;
00419                 };
00420 
00421                 OLGA_INLINE iterator begin(LabelID label) const { return m_buckets[label*m_buckets_per_label].begin; }
00422                 OLGA_INLINE iterator end(LabelID label)   const { return m_buckets[label*m_buckets_per_label + m_buckets_per_label-1].end; }
00423 
00424         private:
00425                 EnergyTermType search(DataCostBucket& b, SiteID s);
00426                 const SiteID  m_num_sites;
00427                 const LabelID m_num_labels;
00428                 const int m_buckets_per_label;
00429                 mutable DataCostBucket* m_buckets;
00430         };
00431 
00432         template <typename DataCostT> SiteID queryActiveSitesExpansion(LabelID alpha_label, SiteID* activeSites);
00433         template <typename DataCostT>   void setupDataCostsExpansion(SiteID size,LabelID alpha_label,EnergyT *e,SiteID *activeSites);
00434         template <typename DataCostT>   void setupDataCostsSwap(SiteID size,LabelID alpha_label,LabelID beta_label,EnergyT *e,SiteID *activeSites);
00435         template <typename SmoothCostT> void setupSmoothCostsExpansion(SiteID size,LabelID alpha_label,EnergyT *e,SiteID *activeSites);
00436         template <typename SmoothCostT> void setupSmoothCostsSwap(SiteID size,LabelID alpha_label,LabelID beta_label,EnergyT *e,SiteID *activeSites);
00437         template <typename DataCostT>   void applyNewLabeling(EnergyT *e,SiteID *activeSites,SiteID size,LabelID alpha_label);
00438         template <typename DataCostT>   void updateLabelingDataCosts();
00439         template <typename UserFunctor> void specializeDataCostFunctor(const UserFunctor f);
00440         template <typename UserFunctor> void specializeSmoothCostFunctor(const UserFunctor f);
00441 
00442         EnergyType setupLabelCostsExpansion(SiteID size,LabelID alpha_label,EnergyT *e,SiteID *activeSites);
00443         void       updateLabelingInfo(bool updateCounts=true,bool updateActive=true,bool updateCosts=true);
00444         
00445         // Check for overflow and submodularity issues when setting up binary graph cut
00446         void addterm1_checked(EnergyT *e,VarID i,EnergyTermType e0,EnergyTermType e1);
00447         void addterm1_checked(EnergyT *e,VarID i,EnergyTermType e0,EnergyTermType e1,EnergyTermType w);
00448         void addterm2_checked(EnergyT *e,VarID i,VarID j,EnergyTermType e00,EnergyTermType e01,EnergyTermType e10,EnergyTermType e11,EnergyTermType w);
00449 
00450         // Returns Smooth Energy of current labeling
00451         template <typename SmoothCostT> EnergyType giveSmoothEnergyInternal();
00452         template <typename Functor> static void deleteFunctor(void* f) { delete reinterpret_cast<Functor*>(f); }
00453 
00454         static void handleError(const char *message);
00455         static void checkInterrupt();
00456 
00457 private:
00458         // Peforms one iteration (one pass over all pairs of labels) of expansion/swap algorithm
00459         EnergyType oneExpansionIteration();
00460         EnergyType oneSwapIteration();
00461         void printStatus1(const char* extraMsg=0);
00462         void printStatus1(int cycle, bool isSwap, gcoclock_t ticks0);
00463         void printStatus2(int alpha, int beta, int numVars, gcoclock_t ticks0);
00464         
00465         void permuteLabelTable();
00466 
00467         template <typename DataCostT> bool       solveSpecialCases(EnergyType& energy);
00468         template <typename DataCostT> EnergyType solveGreedy();
00469 
00471         // GreedyIter
00472         //   Lets solveGreedy efficiently traverse the datacosts when 
00473         //   searching for the next greedy move.
00475         template <typename DataCostT>
00476         class GreedyIter {
00477         public:
00478                 GreedyIter(DataCostT& dc, SiteID numSites)
00479                 : m_dc(dc), m_site(0), m_numSites(numSites), m_label(0), m_lbegin(0), m_lend(0)
00480                 { }
00481 
00482                 OLGA_INLINE void start(const LabelID* labels, LabelID labelCount=1)
00483                 {
00484                         m_site = labelCount ? 0 : m_numSites;
00485                         m_label = m_lbegin = labels;
00486                         m_lend = labels + labelCount;
00487                 }
00488                 OLGA_INLINE SiteID site()  const { return m_site; }
00489                 OLGA_INLINE SiteID label() const { return *m_label; }
00490                 OLGA_INLINE bool   done()  const { return m_site == m_numSites; }
00491                 OLGA_INLINE GreedyIter& operator++() 
00492                 {
00493                         // The inner loop is over labels, not sites, to improve memory locality.
00494                         // When dc() is pulling datacosts from an array (the typical format), this can
00495                         // improve performance by a factor of 2x, often more like 4x.
00496                         if (++m_label >= m_lend) {
00497                                 m_label = m_lbegin;
00498                                 ++m_site;
00499                         }
00500                         return *this;
00501                 }
00502                 OLGA_INLINE EnergyTermType compute() const { return m_dc.compute(m_site,*m_label); }
00503                 OLGA_INLINE SiteID feasibleSites() const { return m_numSites; }
00504 
00505         private:
00506                 SiteID m_site;
00507                 DataCostT& m_dc;
00508                 const SiteID m_numSites;
00509                 const LabelID* m_label;
00510                 const LabelID* m_lbegin;
00511                 const LabelID* m_lend;
00512         };
00513 };
00514 
00515 
00517 // Use this derived class for grid graphs
00519 
00520 class GCoptimizationGridGraph: public GCoptimization
00521 {
00522 public:
00523         GCoptimizationGridGraph(SiteID width,SiteID height,LabelID num_labels);
00524         virtual ~GCoptimizationGridGraph();
00525 
00526         void setSmoothCostVH(EnergyTermType *smoothArray, EnergyTermType *vCosts, EnergyTermType *hCosts);
00527 
00528 protected:
00529         virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights);
00530         virtual void finalizeNeighbors();
00531         EnergyTermType m_unityWeights[4];
00532         int m_weightedGraph;  // true if spatially varying w_pq's are present. False otherwise.
00533 
00534 private:
00535         SiteID m_width;
00536         SiteID m_height;
00537         SiteID *m_neighbors;                 // holds neighbor indexes
00538         EnergyTermType *m_neighborsWeights;    // holds neighbor weights
00539         
00540         void setupNeighbData(SiteID startY,SiteID endY,SiteID startX,SiteID endX,SiteID maxInd,SiteID *indexes);
00541         void computeNeighborWeights(EnergyTermType *vCosts,EnergyTermType *hCosts);
00542 };
00543 
00545 
00546 class GCoptimizationGeneralGraph:public GCoptimization
00547 {
00548 public:
00549         // This is the constructor for non-grid graphs. Neighborhood structure must  be specified by 
00550         // setNeighbors()  function
00551         GCoptimizationGeneralGraph(SiteID num_sites,LabelID num_labels);
00552         virtual ~GCoptimizationGeneralGraph();
00553 
00554         // Makes site1 and site2 neighbors of each other. Can be called only 1 time for each      
00555         // unordered pair of sites. Parameter weight can be used to set spacially varying terms     
00556         // If the desired penalty for neighboring sites site1 and site2 is                        
00557         // V(label1,label2) = weight*SmoothnessPenalty(label1,label2), then                        
00558         // member function setLabel should be called as: setLabel(site1,site2,weight)             
00559         void setNeighbors(SiteID site1, SiteID site2, EnergyTermType weight=1);
00560 
00561         // passes pointers to arrays storing neighbor information
00562         // numNeighbors[i] is the number of neighbors for site i
00563         // neighborsIndexes[i] is a pointer to the array storing the sites which are neighbors to site i
00564         // neighborWeights[i] is a pointer to array storing the weights between site i and its neighbors
00565         // in the same order as neighborIndexes[i] stores the indexes
00566         void setAllNeighbors(SiteID *numNeighbors,SiteID **neighborsIndexes,EnergyTermType **neighborsWeights);
00567 
00568 protected: 
00569         virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights);
00570         virtual void finalizeNeighbors();
00571 
00572 private:
00573 
00574         typedef struct NeighborStruct{
00575                 SiteID  to_node;
00576                 EnergyTermType weight;
00577         } Neighbor;
00578 
00579         LinkedBlockList *m_neighbors;
00580         bool m_needToFinishSettingNeighbors;
00581         SiteID **m_neighborsIndexes;
00582         EnergyTermType **m_neighborsWeights;
00583         bool m_needTodeleteNeighbors;
00584 };
00585 
00586 
00588 // Methods
00590 
00591 
00592 OLGA_INLINE GCoptimization::SiteID GCoptimization::numSites() const
00593 {
00594         return m_num_sites;
00595 }
00596 
00597 OLGA_INLINE GCoptimization::LabelID GCoptimization::numLabels() const
00598 {
00599         return m_num_labels;
00600 }
00601 
00602 OLGA_INLINE void GCoptimization::setLabel(SiteID site, LabelID label)
00603 {
00604         assert(label >= 0 && label < m_num_labels && site >= 0 && site < m_num_sites);
00605         m_labeling[site] = label;
00606         m_labelingInfoDirty = true;
00607 }
00608 
00609 OLGA_INLINE GCoptimization::LabelID GCoptimization::whatLabel(SiteID site)
00610 {
00611         assert(site >= 0 && site < m_num_sites);
00612         return m_labeling[site];
00613 }
00614 
00615 #endif


tabletop_pushing
Author(s): Tucker Hermans
autogenerated on Wed Nov 27 2013 11:59:44