GCoptimization.h 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661
  1. /*#########################################################################
  2. # #
  3. # GC_optimization - software for energy minimization with graph cuts #
  4. # Version 2.3 #
  5. # http://www.csd.uwo.ca/faculty/olga/software.html #
  6. # #
  7. # Copyright 2007 Olga Veksler (olga@csd.uwo.ca) #
  8. # #
  9. # I would like to thank Andrew Delong for his invaluable help #
  10. # with C++ when redesigning the GC interface. Thank you for #
  11. # helping me to make my code 5 times shorter and 100 times more #
  12. # debuggable. And not for scaring me with DLL's :) #
  13. #########################################################################
  14. */
  15. // Copyright 2007 Olga Veksler (olga@csd.uwo.ca)
  16. // email olga@csd.uwo.ca for any questions, suggestions and bug reports
  17. ////////////////////////////////////////////////////////////////////////////////////
  18. // IMPORTANT!!!!!!
  19. // If you use this software, YOU HAVE TO REFERENCE (at least) 3 papers, the citations [1]
  20. // [2] and [3] below
  21. ///////////////////////////////////////////////////////////////////////////////////
  22. // For description and example usage see GC_README.TXT
  23. ///////////////////////////////////////////////////////////////////////////////////
  24. /*
  25. This software library implements the Graph Cuts Energy Minimization methods
  26. described in
  27. [1] Efficient Approximate Energy Minimization via Graph Cuts
  28. Yuri Boykov, Olga Veksler, Ramin Zabih,
  29. IEEE transactions on PAMI, vol. 20, no. 12, p. 1222-1239, November 2001.
  30. This software can be used only for research purposes, you should cite
  31. the aforementioned paper in any resulting publication.
  32. If you wish to use this software (or the algorithms described in the aforementioned paper)
  33. for commercial purposes, you should be aware that there is a US patent:
  34. R. Zabih, Y. Boykov, O. Veksler,
  35. "System and method for fast approximate energy minimization via graph cuts ",
  36. United Stated Patent 6,744,923, June 1, 2004
  37. */
  38. /* Together with the library implemented by O. Veksler, we provide, with the permission of the
  39. V. Kolmogorov and Y. Boykov the following libraries: */
  40. /*1) energy.h, which was developed by Vladimir Kolmogorov and implements binary energy minimization
  41. technique described in
  42. [2] What Energy Functions can be Minimized via Graph Cuts?
  43. Vladimir Kolmogorov and Ramin Zabih.
  44. To appear in IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI).
  45. Earlier version appeared in European Conference on Computer Vision (ECCV), May 2002.
  46. We use "energy.h" to implement the binary energy minimization step
  47. for the alpha-expansion and swap algorithms. The graph construction provided by "energy.h" is
  48. more efficient (and slightly more general) than the original graph construction for the
  49. alpha-expansion algorithm in the paper cited as [1]
  50. This software can be used only for research purposes. IF YOU USE THIS SOFTWARE,
  51. YOU SHOULD CITE THE AFOREMENTIONED PAPER [2] IN ANY RESULTING PUBLICATION.
  52. 2) graph.h, block.h, maxflow.cpp
  53. This software library implements the maxflow algorithm
  54. described in
  55. [3] An Experimental Comparison of Min-Cut/Max-Flow Algorithms
  56. for Energy Minimization in Vision.
  57. Yuri Boykov and Vladimir Kolmogorov.
  58. In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI),
  59. September 2004
  60. This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov
  61. at Siemens Corporate Research. To make it available for public use,
  62. it was later reimplemented by Vladimir Kolmogorov based on open publications.
  63. If you use this software for research purposes, you should cite
  64. the aforementioned paper in any resulting publication.
  65. */
  66. /* These 4 files (energy.h,graph.h, block.h, maxflow.cpp) are included in the curent library with permission of
  67. Vladimir Kolmogorov and Yuri Boykov.
  68. The can also be downloaded independently from Vladimir Kolmogorov's
  69. website:http://www.adastral.ucl.ac.uk/~vladkolm/software.html
  70. */
  71. ///////////////////////////////////////////////////////////////////////////////////
  72. /*
  73. This program is free software; you can redistribute it and/or modify
  74. it under the terms of the GNU General Public License as published by
  75. the Free Software Foundation; either version 2 of the License, or
  76. (at your option) any later version.
  77. This program is distributed in the hope that it will be useful,
  78. but WITHOUT ANY WARRANTY; without even the implied warranty of
  79. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  80. GNU General Public License for more details.
  81. You should have received a copy of the GNU General Public License
  82. along with this program; if not, write to the Free Software
  83. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  84. */
  85. ///////////////////////////////////////////////////////////////////////////////////
  86. #ifndef __GCOPTIMIZATION_H__
  87. #define __GCOPTIMIZATION_H__
  88. #include "energy.h"
  89. #include "graph.h"
  90. #include <memory.h>
  91. #include <stdio.h>
  92. #include <limits.h>
  93. #ifdef _MSC_EXTENSIONS
  94. #define OLGA_INLINE __forceinline
  95. #else
  96. #define OLGA_INLINE inline
  97. #endif
  98. namespace OBJREC {
  99. class LinkedBlockList;
  100. class GCoptimization
  101. {
  102. public:
  103. typedef Graph::flowtype EnergyType; // Type for the total energy the energy function.Change it in Graph.h
  104. typedef Graph::captype EnergyTermType; // Type for the individual terms in the energy function.Change it in Graph.h
  105. typedef Energy::Var VarID;
  106. typedef int LabelID; // Type for labels
  107. typedef int SiteID; // Type for sites
  108. typedef EnergyTermType (*SmoothCostFn)(SiteID s1, SiteID s2, LabelID l1, LabelID l2);
  109. typedef EnergyTermType (*DataCostFn)(SiteID s, LabelID l);
  110. typedef EnergyTermType (*SmoothCostFnExtra)(SiteID s1, SiteID s2, LabelID l1, LabelID l2, void *);
  111. typedef EnergyTermType (*DataCostFnExtra)(SiteID s, LabelID l, void *);
  112. GCoptimization(SiteID num_sites, LabelID num_labels);
  113. virtual ~GCoptimization();
  114. // Peforms expansion algorithm. Runs the number of iterations specified by max_num_iterations
  115. // If no input specified,runs until convergence. Returns total energy of labeling.
  116. EnergyType expansion(int max_num_iterations = INT_MAX);
  117. // Peforms expansion on one label, specified by the input parameter alpha_label
  118. void alpha_expansion(LabelID alpha_label);
  119. // Peforms expansion on label alpha_label only for sites specified by *sites.
  120. // num is the size of array "sites"
  121. void alpha_expansion(LabelID alpha_label, SiteID *sites, SiteID num);
  122. // Peforms swap algorithm. Runs it the specified number of iterations. If no
  123. // input is specified,runs until convergence
  124. EnergyType swap(int max_num_iterations = INT_MAX);
  125. // Peforms swap on a pair of labels, specified by the input parameters alpha_label, beta_label
  126. void alpha_beta_swap(LabelID alpha_label, LabelID beta_label);
  127. // Peforms swap on a pair of labels, specified by the input parameters alpha_label, beta_label
  128. // only on the sitess in the specified arrays, alphaSites and betaSitess, and the array sizes
  129. // are, respectively, alpha_size and beta_size
  130. void alpha_beta_swap(LabelID alpha_label, LabelID beta_label, SiteID *alphaSites,
  131. SiteID alpha_size, SiteID *betaSites, SiteID beta_size);
  132. struct DataCostFunctor; // use this class to pass a functor to setDataCost
  133. struct SmoothCostFunctor; // use this class to pass a functor to setSmoothCost
  134. void setDataCost(DataCostFn fn);
  135. void setDataCost(DataCostFnExtra fn, void *extraData);
  136. void setDataCost(EnergyTermType *dataArray);
  137. void setDataCost(SiteID s, LabelID l, EnergyTermType e);
  138. void setDataCostFunctor(DataCostFunctor* f);
  139. struct DataCostFunctor {
  140. virtual EnergyTermType compute(SiteID s, LabelID l) = 0;
  141. };
  142. void setSmoothCost(SmoothCostFn fn);
  143. void setSmoothCost(SmoothCostFnExtra fn, void *extraData);
  144. void setSmoothCost(LabelID l1, LabelID l2, EnergyTermType e);
  145. void setSmoothCost(EnergyTermType *smoothArray);
  146. void setSmoothCostFunctor(SmoothCostFunctor* f);
  147. struct SmoothCostFunctor {
  148. virtual EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2) = 0;
  149. };
  150. // Returns current label assigned to input site
  151. inline LabelID whatLabel(SiteID site) {
  152. assert(site >= 0 && site < m_num_sites);
  153. return(m_labeling[site]);
  154. };
  155. // This function can be used to change the label of any site at any time
  156. inline void setLabel(SiteID site, LabelID label) {
  157. assert(label >= 0 && label < m_num_labels && site >= 0 && site < m_num_sites);
  158. m_labeling[site] = label;
  159. };
  160. // setLabelOrder(false) sets the order to be not random; setLabelOrder(true)
  161. // sets the order to random. By default, the labels are visited in non-random order
  162. // for both the swap and alpha-expansion moves
  163. void setLabelOrder(bool RANDOM_LABEL_ORDER);
  164. // returns total energy
  165. EnergyType compute_energy();
  166. // Returns Data Energy of current labeling
  167. EnergyType giveDataEnergy();
  168. // Returns Smooth Energy of current labeling
  169. EnergyType giveSmoothEnergy();
  170. // For advanced users who want to squeeze maximum performance out of
  171. // their custom functors. By specializing the GCoptimization class
  172. // (via this method), the compiler knows the exact class you intend
  173. // to use to compute costs. The compiler then inlines your compute
  174. // function in all the right places, provided it's not virtual.
  175. // The functor class need not derive from anything in this case.
  176. template <typename UserFunctor> void specializeDataCostFunctor(const UserFunctor f);
  177. template <typename UserFunctor> void specializeSmoothCostFunctor(const UserFunctor f);
  178. protected:
  179. LabelID m_num_labels;
  180. SiteID m_num_sites;
  181. LabelID *m_labeling;
  182. SiteID *m_lookupSiteVar; // holds index of variable corresponding to site participating in a move,
  183. // -1 for nonparticipating site
  184. LabelID *m_labelTable; // to figure out label order in which to do expansion/swaps
  185. int m_random_label_order;
  186. EnergyTermType* m_datacostIndividual;
  187. EnergyTermType* m_smoothcostIndividual;
  188. void* m_datacostFn;
  189. void* m_smoothcostFn;
  190. EnergyType (GCoptimization::*m_giveDataEnergyInternal)();
  191. EnergyType (GCoptimization::*m_giveSmoothEnergyInternal)();
  192. void (GCoptimization::*m_set_up_n_links_expansion)(SiteID, LabelID, Energy*, VarID*, SiteID*);
  193. void (GCoptimization::*m_set_up_t_links_expansion)(SiteID, LabelID, Energy*, VarID*, SiteID*);
  194. void (GCoptimization::*m_set_up_n_links_swap)(SiteID, LabelID, LabelID, Energy*, VarID*, SiteID*);
  195. void (GCoptimization::*m_set_up_t_links_swap)(SiteID, LabelID, LabelID, Energy*, VarID*, SiteID*);
  196. void (*m_datacostFnDelete)(void* f);
  197. void (*m_smoothcostFnDelete)(void* f);
  198. // returns a pointer to the neighbors of a site and the weights
  199. virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights) = 0;
  200. virtual bool readyToOptimise();
  201. template <typename DataCostT>
  202. void set_up_t_links_expansion(SiteID size, LabelID alpha_label, Energy *e, VarID *variables, SiteID *activeSites );
  203. template <typename DataCostT>
  204. void set_up_t_links_swap(SiteID size, LabelID alpha_label, LabelID beta_label, Energy *e, VarID *variables, SiteID *activeSites );
  205. template <typename SmoothCostT>
  206. void set_up_n_links_expansion(SiteID size, LabelID alpha_label, Energy *e, VarID *variables, SiteID *activeSites );
  207. template <typename SmoothCostT>
  208. void set_up_n_links_swap(SiteID size, LabelID alpha_label, LabelID beta_label, Energy *e, VarID *variables, SiteID *activeSites );
  209. // Returns Data Energy of current labeling
  210. template <typename DataCostT>
  211. EnergyType giveDataEnergyInternal();
  212. // Returns Smooth Energy of current labeling
  213. template <typename SmoothCostT>
  214. EnergyType giveSmoothEnergyInternal();
  215. template <typename Functor>
  216. static void deleteFunctor(void* f) {
  217. delete reinterpret_cast<Functor*>(f);
  218. }
  219. struct DataCostFnFromArray {
  220. DataCostFnFromArray(EnergyTermType* theArray, LabelID num_labels)
  221. : m_array(theArray), m_num_labels(num_labels) {}
  222. OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l) {
  223. return m_array[s*m_num_labels+l];
  224. }
  225. private:
  226. const EnergyTermType* const m_array;
  227. const LabelID m_num_labels;
  228. };
  229. struct DataCostFnFromFunction {
  230. DataCostFnFromFunction(DataCostFn fn): m_fn(fn) {}
  231. OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l) {
  232. return m_fn(s, l);
  233. }
  234. private:
  235. const DataCostFn m_fn;
  236. };
  237. struct DataCostFnFromFunctionExtra {
  238. DataCostFnFromFunctionExtra(DataCostFnExtra fn, void *extraData): m_fn(fn), m_extraData(extraData) {}
  239. OLGA_INLINE EnergyTermType compute(SiteID s, LabelID l) {
  240. return m_fn(s, l, m_extraData);
  241. }
  242. private:
  243. const DataCostFnExtra m_fn;
  244. void *m_extraData;
  245. };
  246. struct SmoothCostFnFromArray {
  247. SmoothCostFnFromArray(EnergyTermType* theArray, LabelID num_labels)
  248. : m_array(theArray), m_num_labels(num_labels) {}
  249. OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2) {
  250. return m_array[l1*m_num_labels+l2];
  251. }
  252. private:
  253. const EnergyTermType* const m_array;
  254. const LabelID m_num_labels;
  255. };
  256. struct SmoothCostFnFromFunction {
  257. SmoothCostFnFromFunction(SmoothCostFn fn)
  258. : m_fn(fn) {}
  259. OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2) {
  260. return m_fn(s1, s2, l1, l2);
  261. }
  262. private:
  263. const SmoothCostFn m_fn;
  264. };
  265. struct SmoothCostFnFromFunctionExtra {
  266. SmoothCostFnFromFunctionExtra(SmoothCostFnExtra fn, void *extraData)
  267. : m_fn(fn), m_extraData(extraData) {}
  268. OLGA_INLINE EnergyTermType compute(SiteID s1, SiteID s2, LabelID l1, LabelID l2) {
  269. return m_fn(s1, s2, l1, l2, m_extraData);
  270. }
  271. private:
  272. const SmoothCostFnExtra m_fn;
  273. void *m_extraData;
  274. };
  275. void handleError(const char *message);
  276. private:
  277. void solveExpansion(SiteID size, SiteID *activeSites, LabelID alpha_label);
  278. EnergyType oneExpansionIteration();
  279. void set_up_expansion_energy(SiteID size, LabelID alpha_label, Energy *e, VarID *variables, SiteID *activeSites );
  280. void solveSwap(SiteID size, SiteID *activeSites, LabelID alpha_label, LabelID beta_label);
  281. // Peforms one iteration (one pass over all pairs of labels) of swap algorithm
  282. EnergyType oneSwapIteration();
  283. void set_up_swap_energy(SiteID size, LabelID alpha_label, LabelID beta_label,
  284. Energy* e, Energy::Var *variables, SiteID *activeSites);
  285. void scramble_label_table();
  286. };
  287. //////////////////////////////////////////////////////////////////////////////////////////////////
  288. // Use this derived class for grid graphs
  289. //////////////////////////////////////////////////////////////////////////////////////////////////
  290. class GCoptimizationGridGraph: public GCoptimization
  291. {
  292. public:
  293. GCoptimizationGridGraph(SiteID width, SiteID height, LabelID num_labels);
  294. virtual ~GCoptimizationGridGraph();
  295. void setSmoothCostVH(EnergyTermType *smoothArray, EnergyTermType *vCosts, EnergyTermType *hCosts);
  296. virtual bool readyToOptimise();
  297. protected:
  298. virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights);
  299. EnergyTermType m_unityWeights[4];
  300. int m_weightedGraph; // true if spatially varying w_pq's are present. False otherwise.
  301. private:
  302. SiteID m_width;
  303. SiteID m_height;
  304. SiteID *m_numNeighbors; // holds num of neighbors
  305. SiteID *m_neighbors; // holds neighbor indexes
  306. EnergyTermType *m_neighborsWeights; // holds neighbor weights
  307. void setupNeighbData(SiteID startY, SiteID endY, SiteID startX, SiteID endX, SiteID maxInd, SiteID *indexes);
  308. void computeNeighborWeights(EnergyTermType *vCosts, EnergyTermType *hCosts);
  309. };
  310. //////////////////////////////////////////////////////////////////////////////////////////////////
  311. class GCoptimizationGeneralGraph: public GCoptimization
  312. {
  313. public:
  314. // This is the constructor for non-grid graphs. Neighborhood structure must be specified by
  315. // setNeighbors() function
  316. GCoptimizationGeneralGraph(SiteID num_sites, LabelID num_labels);
  317. virtual ~GCoptimizationGeneralGraph();
  318. virtual bool readyToOptimise();
  319. // Makes site1 and site2 neighbors of each other. Can be called only 1 time for each
  320. // unordered pair of sites. Parameter weight can be used to set spacially varying terms
  321. // If the desired penalty for neighboring sites site1 and site2 is
  322. // V(label1,label2) = weight*SmoothnessPenalty(label1,label2), then
  323. // member function setLabel should be called as: setLabel(site1,site2,weight)
  324. void setNeighbors(SiteID site1, SiteID site2, EnergyTermType weight = 1);
  325. // passes pointers to arrays storing neighbor information
  326. // numNeighbors[i] is the number of neighbors for site i
  327. // neighborsIndexes[i] is a pointer to the array storing the sites which are neighbors to site i
  328. // neighborWeights[i] is a pointer to array storing the weights between site i and its neighbors
  329. // in the same order as neighborIndexes[i] stores the indexes
  330. void setAllNeighbors(SiteID *numNeighbors, SiteID **neighborsIndexes, EnergyTermType **neighborsWeights);
  331. protected:
  332. virtual void giveNeighborInfo(SiteID site, SiteID *numSites, SiteID **neighbors, EnergyTermType **weights);
  333. private:
  334. typedef struct NeighborStruct {
  335. SiteID to_node;
  336. EnergyTermType weight;
  337. } Neighbor;
  338. LinkedBlockList *m_neighbors;
  339. bool m_needToFinishSettingNeighbors;
  340. SiteID *m_numNeighbors;
  341. SiteID **m_neighborsIndexes;
  342. EnergyTermType **m_neighborsWeights;
  343. bool m_needTodeleteNeighbors;
  344. //Call this function when you are finished setting neibhbors
  345. void finishSettingNeighbors();
  346. };
  347. /////////////////////////////////////////////////////////////////////
  348. // Class for handling errors
  349. /////////////////////////////////////////////////////////////////////
  350. class GCException
  351. {
  352. public:
  353. const char* message;
  354. GCException( const char* m ) {
  355. message = m;
  356. }
  357. void Report() {
  358. printf("\n%s\n", message);
  359. exit(0);
  360. }
  361. };
  362. ////////////////////////////////////////////////////////////////////
  363. // Methods
  364. ////////////////////////////////////////////////////////////////////
  365. template <typename UserFunctor>
  366. void GCoptimization::specializeDataCostFunctor(const UserFunctor f) {
  367. if ( m_datacostFn ) handleError("Data Costs are already initialized");
  368. m_datacostFn = new UserFunctor(f);
  369. m_datacostFnDelete = &GCoptimization::deleteFunctor<UserFunctor>;
  370. m_giveDataEnergyInternal = &GCoptimization::giveDataEnergyInternal<UserFunctor>;
  371. m_set_up_t_links_expansion = &GCoptimization::set_up_t_links_expansion<UserFunctor>;
  372. m_set_up_t_links_swap = &GCoptimization::set_up_t_links_swap<UserFunctor>;
  373. }
  374. template <typename UserFunctor>
  375. void GCoptimization::specializeSmoothCostFunctor(const UserFunctor f) {
  376. if ( m_smoothcostFn ) handleError("Smoothness Costs are already initialized");
  377. m_smoothcostFn = new UserFunctor(f);
  378. m_smoothcostFnDelete = &GCoptimization::deleteFunctor<UserFunctor>;
  379. m_giveSmoothEnergyInternal = &GCoptimization::giveSmoothEnergyInternal<UserFunctor>;
  380. m_set_up_n_links_expansion = &GCoptimization::set_up_n_links_expansion<UserFunctor>;
  381. m_set_up_n_links_swap = &GCoptimization::set_up_n_links_swap<UserFunctor>;
  382. }
  383. //-------------------------------------------------------------------
  384. template <typename DataCostT>
  385. GCoptimization::EnergyType GCoptimization::giveDataEnergyInternal()
  386. {
  387. EnergyType eng = (EnergyType) 0;
  388. DataCostT* tc = (DataCostT*)m_datacostFn;
  389. for ( SiteID i = 0; i < m_num_sites; i++ )
  390. {
  391. assert(m_labeling[i] >= 0 && m_labeling[i] < m_num_labels);
  392. eng = eng + tc->compute(i, m_labeling[i]);
  393. }
  394. return(eng);
  395. }
  396. //-------------------------------------------------------------------
  397. template <typename SmoothCostT>
  398. GCoptimization::EnergyType GCoptimization::giveSmoothEnergyInternal()
  399. {
  400. EnergyType eng = (EnergyType) 0;
  401. SiteID i, numN, *nPointer, nSite, n;
  402. EnergyTermType *weights;
  403. SmoothCostT* sc = (SmoothCostT*) m_smoothcostFn;
  404. for ( i = 0; i < m_num_sites; i++ )
  405. {
  406. giveNeighborInfo(i, &numN, &nPointer, &weights);
  407. for ( n = 0; n < numN; n++ )
  408. {
  409. nSite = nPointer[n];
  410. if ( nSite < i ) eng =
  411. eng + weights[n] * (sc->compute(i, nSite, m_labeling[i], m_labeling[nSite]));
  412. }
  413. }
  414. return(eng);
  415. }
  416. //-------------------------------------------------------------------//
  417. // METHODS for EXPANSION MOVES //
  418. //-------------------------------------------------------------------//
  419. template <typename DataCostT>
  420. void GCoptimization::set_up_t_links_expansion(SiteID size, LabelID alpha_label, Energy *e,
  421. VarID *variables, SiteID *activeSites )
  422. {
  423. DataCostT* dc = (DataCostT*)m_datacostFn;
  424. for ( SiteID i = 0; i < size; i++ )
  425. {
  426. e -> add_term1(variables[i], dc->compute(activeSites[i], alpha_label),
  427. dc->compute(activeSites[i], m_labeling[activeSites[i]]));
  428. }
  429. }
  430. //-------------------------------------------------------------------
  431. template <typename SmoothCostT>
  432. void GCoptimization::set_up_n_links_expansion(SiteID size, LabelID alpha_label, Energy *e,
  433. VarID *variables, SiteID *activeSites )
  434. {
  435. SiteID i, nSite, site, n, nNum, *nPointer;
  436. EnergyTermType *weights;
  437. SmoothCostT* sc = (SmoothCostT*)m_smoothcostFn;
  438. for ( i = size - 1; i >= 0; i-- )
  439. {
  440. site = activeSites[i];
  441. giveNeighborInfo(site, &nNum, &nPointer, &weights);
  442. for ( n = 0; n < nNum; n++ )
  443. {
  444. nSite = nPointer[n];
  445. if ( nSite < site )
  446. {
  447. if ( m_lookupSiteVar[nSite] != -1 )
  448. e ->add_term2(variables[i], variables[m_lookupSiteVar[nSite]],
  449. sc->compute(site, nSite, alpha_label, alpha_label)*weights[n],
  450. sc->compute(site, nSite, alpha_label, m_labeling[nSite])*weights[n],
  451. sc->compute(site, nSite, m_labeling[site], alpha_label)*weights[n],
  452. sc->compute(site, nSite, m_labeling[site], m_labeling[nSite])*weights[n]);
  453. else e ->add_term1(variables[i], sc->compute(site, nSite, alpha_label, m_labeling[nSite])*weights[n],
  454. sc->compute(site, nSite, m_labeling[site], m_labeling[nSite])*weights[n]);
  455. }
  456. else
  457. {
  458. if (m_lookupSiteVar[nSite] == -1 )
  459. e ->add_term1(variables[i], sc->compute(site, nSite, alpha_label, m_labeling[nSite])*weights[n],
  460. sc->compute(site, nSite, m_labeling[site], m_labeling[nSite])*weights[n]);
  461. }
  462. }
  463. }
  464. }
  465. //-------------------------------------------------------------------//
  466. // METHODS for SWAP MOVES //
  467. //-------------------------------------------------------------------//
  468. template <typename DataCostT>
  469. void GCoptimization::set_up_t_links_swap(SiteID size, LabelID alpha_label, LabelID beta_label,
  470. Energy *e, VarID *variables, SiteID *activeSites )
  471. {
  472. DataCostT* dc = (DataCostT*)m_datacostFn;
  473. for ( SiteID i = 0; i < size; i++ )
  474. {
  475. e -> add_term1(variables[i], dc->compute(activeSites[i], alpha_label),
  476. dc->compute(activeSites[i], beta_label) );
  477. }
  478. }
  479. //-------------------------------------------------------------------
  480. template <typename SmoothCostT>
  481. void GCoptimization::set_up_n_links_swap(SiteID size, LabelID alpha_label, LabelID beta_label,
  482. Energy *e, VarID *variables, SiteID *activeSites )
  483. {
  484. SiteID i, nSite, site, n, nNum, *nPointer;
  485. EnergyTermType *weights;
  486. SmoothCostT* sc = (SmoothCostT*)m_smoothcostFn;
  487. for ( i = size - 1; i >= 0; i-- )
  488. {
  489. site = activeSites[i];
  490. giveNeighborInfo(site, &nNum, &nPointer, &weights);
  491. for ( n = 0; n < nNum; n++ )
  492. {
  493. nSite = nPointer[n];
  494. if ( nSite < site )
  495. {
  496. if ( m_lookupSiteVar[nSite] != -1 )
  497. e ->add_term2(variables[i], variables[m_lookupSiteVar[nSite]],
  498. sc->compute(site, nSite, alpha_label, alpha_label)*weights[n],
  499. sc->compute(site, nSite, alpha_label, beta_label)*weights[n],
  500. sc->compute(site, nSite, beta_label, alpha_label)*weights[n],
  501. sc->compute(site, nSite, beta_label, beta_label)*weights[n]);
  502. else e ->add_term1(variables[i], sc->compute(site, nSite, alpha_label, m_labeling[nSite])*weights[n],
  503. sc->compute(site, nSite, beta_label, m_labeling[nSite])*weights[n]);
  504. }
  505. else
  506. {
  507. if (m_lookupSiteVar[nSite] == -1 )
  508. e ->add_term1(variables[i], sc->compute(site, nSite, alpha_label, m_labeling[nSite])*weights[n],
  509. sc->compute(site, nSite, beta_label, m_labeling[nSite])*weights[n]);
  510. }
  511. }
  512. }
  513. }
  514. } //namespace
  515. #endif