1 #########################################################################
\r
3 # GC_optimization - software for energy minimization with graph cuts #
\r
5 # http://www.csd.uwo.ca/faculty/olga/software.html #
\r
7 # Copyright 2005 Olga Veksler (olga@csd.uwo.ca) #
\r
9 #########################################################################
\r
11 /* email olga@csd.uwo.ca for any questions, suggestions and bug reports
\r
13 /***************** IMPORTANT!!!!!!!!!!!***********************************************************
\r
15 If you use this software, YOU HAVE TO REFERENCE (at least) 3 papers, the citations [1]
\r
18 /****************************************************************************************************/
\r
21 This README file was written by Olga Veksler and reffers to the C++ core implementation.
\r
22 In order to use the Matlab Wrapper you should
\r
23 a. unzip the bundle into a directory within your Matlab's path
\r
24 b. compile the required mex-files using
\r
26 (You might need to set your mex compiler first. Type mex -setup on Matlab's prompt)
\r
27 c. type doc GraphCut and you will have the rest of the necessary documentation.
\r
29 This software is for academic use ONLY.
\r
30 If you are using this software please note required citations in the Matlab documenation.
\r
32 For any questions/remarks/problems with the Matlab wrapper please contact shai.bagon@weizmann.ac.il
\r
39 This software library implements the Graph Cuts Energy Minimization methods
\r
43 [1] Efficient Approximate Energy Minimization via Graph Cuts
\r
44 Yuri Boykov, Olga Veksler, Ramin Zabih,
\r
45 IEEE transactions on PAMI, vol. 20, no. 12, p. 1222-1239, November 2001.
\r
49 This software can be used only for research purposes, you should cite
\r
50 the aforementioned paper in any resulting publication.
\r
51 If you wish to use this software (or the algorithms described in the aforementioned paper)
\r
52 for commercial purposes, you should be aware that there is a US patent:
\r
54 R. Zabih, Y. Boykov, O. Veksler,
\r
55 "System and method for fast approximate energy minimization via graph cuts ",
\r
56 United Stated Patent 6,744,923, June 1, 2004
\r
60 /* Together with the library implemented by O. Veksler, we provide, with the permission of the
\r
61 V. Kolmogorov and Y. Boykov the following libraries:
\r
64 1) energy.h, which was developed by Vladimir Kolmogorov and implements binary energy minimization
\r
65 technique described in
\r
67 [2] What Energy Functions can be Minimized via Graph Cuts?
\r
68 Vladimir Kolmogorov and Ramin Zabih.
\r
69 To appear in IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI).
\r
70 Earlier version appeared in European Conference on Computer Vision (ECCV), May 2002.
\r
73 We use "energy.h" to implement the binary energy minimization step
\r
74 for the alpha-expansion and swap algorithms. The graph construction provided by "energy.h" is
\r
75 more efficient (and slightly more general) than the original graph construction for the
\r
76 alpha-expansion algorithm in the paper cited as [1]
\r
79 This software can be used only for research purposes. IF YOU USE THIS SOFTWARE,
\r
80 YOU SHOULD CITE THE AFOREMENTIONED PAPER [2] IN ANY RESULTING PUBLICATION.
\r
84 2) graph.h, block.h, maxflow.cpp
\r
86 This software library implements the maxflow algorithm
\r
89 [3] An Experimental Comparison of Min-Cut/Max-Flow Algorithms
\r
90 for Energy Minimization in Vision.
\r
91 Yuri Boykov and Vladimir Kolmogorov.
\r
92 In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI),
\r
95 This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov
\r
96 at Siemens Corporate Research. To make it available for public use,
\r
97 it was later reimplemented by Vladimir Kolmogorov based on open publications.
\r
99 If you use this software for research purposes, you should cite
\r
100 the aforementioned paper in any resulting publication.
\r
103 /* These 4 files (energy.h,graph.h, block.h, maxflow.cpp) are included in the curent library with permission of
\r
104 Vladimir Kolmogorov and Yuri Boykov. They are included in a separate subdirectory named NotVekslerCode.
\r
105 The can also be downloaded independently from Vladimir Kolmogorov's
\r
106 website:http://research.microsoft.com/~vnk/
\r
107 Please Note that Vladimir's website is likely to move in the future */
\r
110 Tested under windows, Visual C++ 6.0 compiler
\r
112 ##################################################################
\r
116 This program is free software; you can redistribute it and/or modify
\r
117 it under the terms of the GNU General Public License as published by
\r
118 the Free Software Foundation; either version 2 of the License, or
\r
119 (at your option) any later version.
\r
121 This program is distributed in the hope that it will be useful,
\r
122 but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
123 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
124 GNU General Public License for more details.
\r
126 You should have received a copy of the GNU General Public License
\r
127 along with this program; if not, write to the Free Software
\r
128 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
\r
131 ##################################################################
\r
133 3. Energy Minimization
\r
135 This software is for minimizing energy functions of the form:
\r
137 E(l) = sum_p D(p,l_p) + sum_{p,q} Vpq(l_p,l_q)
\r
139 Here we have a finite set of sites (or pixels) P and a finite set of labels L.
\r
140 A labeling l is assignments of labels in L to pixels in P. The individual pixels
\r
141 are referred to with small letters p and q, label of pixel p is denoted by l_p,
\r
142 and the set of all label-pixel assignments is denoted by l, that is
\r
143 l = {l_p | p in P}.
\r
145 The first term in the energy function E(l) is typically called the data term, and
\r
146 it consists of the sum over all pixels p of the penalty(or cost) D(p,l_p), what
\r
147 should be the cost of assigning label l_p to pixel p. D(p,l_p) can be arbitrary.
\r
149 The second term is a sum over all pairs of neighboring pixels {p,q}.
\r
150 That is there is a neighborhood relation on the set of pixels (this relationship
\r
151 is symmetric, that is if p is a neighbor of q then q is a neighbor of p).
\r
152 Here we assume that the neighbor pairs are unordered. This means that if pixels p and q are
\r
153 neighbors, then there is either Vpq(l_p,l_q) in the second sum of the energy,
\r
154 or Vqp(l_q,l_p), but not both. This is not a restriction, since in practice, one can always go
\r
155 from the ordered energy to the unordered one. This second term is typically called the smoothness
\r
158 The expansion algorithm for energy minimization can be used whenever for any 3 labels a,b,c
\r
159 V(a,a) + V(b,c) <= V(a,c)+V(b,a). In other words, expansion algorithm can be used if
\r
160 the binary energy for the expansion algorithm step is regular, using V. Kolmogorov's terminology.
\r
162 The swap algorithm for energy minimization can be used whenever for any 2 labels a,b
\r
163 V(a,a) + V(b,b) <= V(a,b)+V(b,a). In other words, swap algorithm can be used if
\r
164 the binary energy for the swap algorithm step is regular, using V. Kolmogorov's terminology.
\r
166 ##################################################################
\r
170 a) EnergyTermType. This is the type for each individual energy term,
\r
171 that is for the terms D and V. By default, it is set to short.
\r
172 To change it, go into file "graph.h" and modify the statement
\r
174 "typedef int captype;" from short to any desired type.
\r
177 b) EnergyType. This is the type for the total energy (for the sum of all
\r
178 the D and V terms). By default, it is set to int. To change it, go into file "graph.h"
\r
179 and change the statement "typedef int flowtype;" to any desired type. Be very careful to
\r
180 avoid overflow if you change this type.
\r
181 The sum of many terms of type EnergyTermType shouldn't overflow the EnergyType.
\r
184 c) Label type, is the type to use for the label names. Currently set to integers. In order
\r
185 to save space, you may want to change it to char or short. Can be also set to long,
\r
186 but not to float or double. To change this type, go to "GCoptimization.h"
\r
188 typedef int LabelType;
\r
190 d) PixelType: the type to use for pixel names. Currently set to integers. For
\r
191 smaller problems, to save space, you may want to change it to short. Can be also set to long,
\r
192 but not to float or double. To change this type, go to "GCoptimization.h"
\r
194 /* Type for pixel. Can be set to short, int, long */
\r
195 typedef int PixelType;
\r
199 ###########################################################################
\r
202 5. Specifying the energy
\r
204 Before optimizing the energy, one has to specify it, that is specify the number of
\r
205 labels, number of pixels, neighborhood system, the data terms, and the smoothness terms.
\r
206 There are 2 main constructors to use, one in case of the grid graph, and another in case
\r
207 of a general graph.
\r
208 In all cases, it is assumed that the pixels are numbered from
\r
209 from 0...num_pixels-1, where num_pixels is the number of pixels, and the number of labels,
\r
210 which are assumed to be numbered from 0....num_labels-1, where num_labels is the number of labels.
\r
211 For a grid (4-connected) graph, pixel at coordinates (x,y) is numbered with x+y*width, where width
\r
212 is the width of the grid, that is the row-major ordering of arrays is assumed.
\r
213 ________________________________________________________________________________________________
\r
217 GCoptimization(PixelType width,PixelType height,int num_labels,int dataSetup, int smoothSetup);
\r
219 Use this constructor only for grid of size width by height. If you use this constructor,
\r
220 4 connected grid neigbhorhood structure is assumed, so you don't need to specify neighborhood
\r
221 structure separately (and indeed cannot do so). Input parameters dataSetup and smoothSetup are
\r
222 explained below, in "Section 6. Setting the data and smoothness terms"
\r
223 _______________________________________________________________________________________________
\r
227 GCoptimization(PixelType num_pixels,int num_labels,int dataSetup, int smoothSetup);
\r
229 Use this constructor for general graphs. If you use this constructor, you must setup up
\r
230 neighborhood system using function setNeighbors() for each pair of neighboring pixels.
\r
231 There are 2 types of setNeighbor functions:
\r
233 void setNeighbors(PixelType p, PixelType q, EnergyTermType w_pq);
\r
234 void setNeighbors(PixelType p, PixelType q);
\r
236 Coefficient w_pq is used whenever the smoothness term between pixels p and q depends on
\r
237 the individual pixels p and q, or in other words, is "spacially varying". For example,
\r
238 if Vpq(l_p,l_q) = penalty(l_p,l_q)*w_pq, where penalty(l_p,l_q) is some function that
\r
239 depends only on the labels l_p,l_q, then setNeighbors(p,q,w_pq) should be called.
\r
240 If w_pq = 1 for all neighbor pixels p and q, than you can call setNeighbors(p,q)
\r
241 (calling setNeighbors(p,q,1) achieves the same thing).
\r
242 Note that this function setNeighbor has to be called exactly one time for each neighbor pair.
\r
243 That is if pixels p and q are neighbors, you can call either setNeighbors(p,q) or setNeighbors(q,p)
\r
246 Input parameters dataSetup and smoothSetup are explained below in "Section 6 Setting the data and smoothness terms"
\r
247 _______________________________________________________________________________________________
\r
251 GCoptimization(LabelType *m_answer,PixelType num_pixels,int nLabels,int dataSetup, int smoothSetup);
\r
253 This constructor is exactly the same as constructor A, but in addition, pointer to the array where
\r
254 the final labels should be stored is passed, namely m_answer. m_answer should point to the
\r
255 array of size num_pixels (which is width*height for the grid graph). This is done to save space,
\r
256 if needed, so that the as the answer will not have to be stored twice, once in the current class,
\r
257 and once in the class which calls this optimization.
\r
259 _______________________________________________________________________________________________
\r
263 GCoptimization(LabelType *m_answer,PixelType width,PixelType height,int num_labels,int dataSetup, int smoothSetup);
\r
265 This constructor is exactly the same as constructor B, but in addition, pointer to the array where
\r
266 the final labels should be stored is passed, namely m_answer. m_answer should point to the
\r
267 array of size num_pixels (which is width*height for the grid graph). This is done to save space,
\r
268 if needed, so that the as the answer will not have to be stored twice, once in the current class,
\r
269 and once in the class which calls this optimization.
\r
271 _______________________________________________________________________________________________
\r
274 6. Setting the data and smoothness terms.
\r
276 The way the data and smoothness terms are setup is controlled by the input parameters
\r
277 to the constructor (these parameters are common to all constructors), namely
\r
278 parameters dataSetup and smoothSetup. These parameters can take only 2 values, namely SET_INDIVIDUALLY (0) and
\r
279 SET_ALL_AT_ONCE(1).
\r
281 ------------------------dataSetup-----------------------
\r
282 In case dataSetup = SET_INDIVIDUALLY, to set the data cost you must use the
\r
283 member function setDataCost(pixel,label,cost), for each pixel and label combination. That is each
\r
284 data term is set up individually. This function sets D_pixel (label) = cost.
\r
285 If dataSetup = SET_ALL_AT_ONCE, to set the data costs you must use one of the three setData() functions,
\r
286 either by passing an array of data costs (of appropriate size), or a pointer to a function which
\r
287 returns data cost term. More details on different setData() functions:
\r
289 (a) void setData(EnergyTermType *DataCost);
\r
290 DataCost is an array s.t. the data cost for pixel p and label l is stored at
\r
291 DataCost[pixel*num_labels+l]. If the current neighborhood system is a grid, then
\r
292 the data term for label l and pixel with coordinates (x,y) is stored at
\r
293 DataCost[(x+y*width)*num_labels + l]. Thus the size of array DataCost is num_pixels*num_labels
\r
295 (b) void setData(dataFnPix dataFn);
\r
296 dataFn is a pointer to a function f(Pixel p, Label l), s.t. the data cost for pixel p to have
\r
297 label l is given by f(p,l)
\r
299 (c) void setData(dataFnCoord dataFn);
\r
300 This function can be used only for a grid graph. dataFn is a pointer to a function
\r
301 f(x, y, l), s.t. the data cost for pixel with coordinates (x,y) to have label l
\r
302 is given by f(x,y,l)
\r
304 Note that only one of the above setData() functions can be used.
\r
306 ------------------------dataSetup-----------------------
\r
307 In case smoothSetup = SET_INDIVIDUALLY, to set the smooth cost you must use the member function
\r
308 setSmoothCost(label1,label2,cost). This function sets V(label1,label2) = cost. Notice that
\r
309 no spatially varying coefficient w_pq is allowed in this case.
\r
310 If smoothSetup = SET_ALL_AT_ONCE, to set the smoothness costs you must use any of the setSmoothness()
\r
311 functions, either by passing an array of smoothness costs, or a pointer to a function which returns
\r
312 smoothness cost. More details on different setSmoothness() functions:
\r
314 (a) void setSmoothness(EnergyTermType* V);
\r
315 V is an array of smoothness costs, such that V_pq(label1,label2) is stored at V[label1+num_labels*label2]
\r
316 If graph is a grid, then using this function only if the smooth costs are not spacially varying
\r
317 that is the smoothness penalty V depends only on labels, but not on pixels. If the graph is
\r
318 not a grid, then you can specify spacially varying coefficients w_pq when you set up the
\r
319 neighborhood system using setNeighbor(p,q,w_pq) function. In this case,
\r
320 V_pq(label1,label2) = V[label1+num_labels*label2]*w_pq
\r
322 (b) void setSmoothness(EnergyTermType* V,EnergyTermType* hCue, EnergyTermType* vCue);
\r
323 This function should be used only if the graph is a grid. Array V is the same as above, under (a).
\r
324 Arrays hCue and vCue have the same size as the image (that is width*height), and are used to set
\r
325 the spatially varying coefficients w_pq. If p = (x,y) and q = (x+1,y), then
\r
326 w_pq = hCue[x+y*width], and so the smoothness penalty for pixels (x,y) and (x+1,y) to have labels
\r
327 label1 and label2, that is V_pq(label1,label2) = V[label1+num_labels*label2]*hCue[x+y*width]
\r
328 If p = (x,y) and q = (x,y+q), then
\r
329 w_pq = vCue[x+y*width], and so the smoothness penalty for pixels (x,y) and (x,y+1) to have labels
\r
330 label1 and label2, that is V_pq(label1,label2) = V[label1+num_labels*label2]*vCue[x+y*width]
\r
332 (c) void setSmoothness(smoothFnCoord cost);
\r
334 cost is pointer to a function f(pix1,pix2,label1,label2) such that smoothness penalty for neigboring pixels
\r
335 pix1 and pix2 to have labels, respectively, label1 and label2 is f(pix1,pix2,label1,label2)
\r
337 (d) void setSmoothness(smoothFnCoord horz_cost, smoothFnCoord vert_cost);
\r
339 This function can be used only if the graph is a grid.
\r
340 horz_cost is a poineter to a function f(x,y,label1,label2) such that smoothness penalty for neigboring pixels
\r
341 (x,y) and (x+1,y) to have labels, respectively, label1 and label2 is f(x,y,label1,label2)
\r
342 vert_cost is a pointer to a function f(x,y,label1,label2) such that smoothness penalty for neigboring pixels
\r
343 /* (x,y) and (x,y+1) to have labels, respectively, label1 and label2 is f(x,y,label1,label2)
\r
346 Note that only one of the above setSmoothness() functions can be used.
\r
349 ##################################################################
\r
351 6. Optimizing the energy
\r
353 You can optimize the energy and get the resulting labeling using the following functions. Notice that they can
\r
354 be called as many times as one wishes after the constructor has been called and the data/smoothness terms
\r
355 (and the neighborhood system, if general graph) has beeen set. The initial labeling is set to consists of
\r
356 all 0's. Use function setLabel(PixelType pixelP, LabelType labelL), described under heading (x) in this section
\r
357 to initialize the labeling to anything else (but in the valid range, of course, labels must be between
\r
358 0 and num_labels-1)
\r
361 i) expansion(int max_num_iterations)
\r
362 Will run the expansion algorithm up to the specified number of iterations.
\r
363 Returns the energy of the resulting labeling.
\r
366 Will run the expansion algorithm to convergence (convergence is guaranteed)
\r
367 Returns the energy of the resulting labeling
\r
369 iii) oneExpansionIteration();
\r
370 Performs one iteration (one pass over all labels) of expansion algorithm, see the paper for more details.
\r
371 Returns the energy of the resulting labeling
\r
374 iv) alpha_expansion(LabelType alpha_label);
\r
375 Performs expansion on the label specified by alpha_label. Returns the energy of the resulting labeling
\r
377 v) swap(int max_num_iterations);
\r
378 Will run the swap algorithm up to the specified number of iterations.
\r
379 Returns the energy of the resulting labeling.
\r
383 Will run the swap algorithm up to convergence (convergence is guaranteed)
\r
384 Returns the energy of the resulting labeling
\r
387 vii) oneSwapIteration();
\r
388 Performs one iteration (one pass over all pairs of labels) of the swap algorithm, see the paper for more details.
\r
389 Returns the energy of the resulting labeling.
\r
392 viii) alpha_beta_swap(LabelType alpha_label, LabelType beta_label);
\r
393 Performs swap on a pair of labels, specified by the input parameters alpha_label, beta_label.
\r
394 Returns the energy of the resulting labeling.
\r
397 ix) whatLabel(PixelType pixelP)
\r
398 Returns the current label assigned to pixelP. Can be called at any time after the constructor call.
\r
400 x) setLabel(PixelType pixelP, LabelType labelL)
\r
401 Sets the label of pixelP to the the input parameter labelL. Can be called at any time after the constructor call.
\r
402 This function is useful, in particular, to initialize the labeling to something specific before optimization starts.
\r
404 xi) setLabelOrder(bool RANDOM_LABEL_ORDER)
\r
405 By default, the labels for the swap and expansion algorithms are visited in random order, thus the results
\r
406 are going to be slightly different each time the optimization is invoked. To set the label order to
\r
407 be not random, call setLabelOrder(0). To set it to be random again, call setLabelOrder(1). Notice,
\r
408 that by using functions under heading (iv) and (viii) you can completely and exactly specify the desired
\r
411 xii) EnergyType giveDataEnergy();
\r
412 Returns the data part of the energy of the current labling
\r
415 xiii) EnergyType giveSmoothEnergy();
\r
416 Returns the smoothness part of the energy of the current labling
\r
418 ##################################################################
\r
422 Example 1, uses constructor A.
\r
424 __________________________________________________________________
\r
428 #include "GCoptimization.h"
\r
430 void main(int argc, char **argv)
\r
433 GCoptimization *optimize = (GCoptimization *) new GCoptimization(3,2, SET_INDIVIDUALLY, SET_INDIVIDUALLY);
\r
434 GCoptimization::EnergyType engS,engD,engT;
\r
436 // First set the data costs terms for each pixel and each label
\r
437 optimize ->setDataCost(0,0,5);
\r
438 optimize ->setDataCost(0,1,1);
\r
439 optimize ->setDataCost(1,0,3);
\r
440 optimize ->setDataCost(1,1,0);
\r
441 optimize ->setDataCost(2,0,-3);
\r
442 optimize ->setDataCost(2,1,3);
\r
445 //Next set the neighboring pixels
\r
446 optimize->setNeighbors(0,1,7);
\r
448 optimize->setNeighbors(1,2,5);
\r
450 //Finally, specify the remaining part of Vpq. This is the part that
\r
451 // depends just on labels, not on pixels, and in this case
\r
452 // it is penalty(label1,label2) = |label1-label2|
\r
454 optimize->setSmoothCost(0,0,0);
\r
455 optimize->setSmoothCost(0,1,1);
\r
456 optimize->setSmoothCost(1,0,1);
\r
457 optimize->setSmoothCost(1,1,0);
\r
459 ////////////////////////////////////////////////////////////////////////
\r
460 /* Now the energy is completely specified. Can call any optimization */
\r
463 engD = optimize->giveDataEnergy();
\r
464 engS = optimize->giveSmoothEnergy();
\r
466 printf("\nBefore optimization, the smooth energy is %d, data energy %d, total %d",engS,engD,engS+engD);
\r
468 engT = optimize->expansion(); //to run expansion algorithm to convergence
\r
469 //eng = optimize->swap(); //to run swap algorithm to convergence
\r
471 engD = optimize->giveDataEnergy();
\r
472 engS = optimize->giveSmoothEnergy();
\r
474 printf("\nAfter optimization, the smooth energy is %d, data energy %d, total %d",engS,engD,engS+engD);
\r
475 for( int i = 0; i < 3; i++ )
\r
476 printf("\nPixel %d has label %d",i,optimize->whatLabel(i));
\r
481 __________________________________________________________________
\r
483 Example 2, uses constructor A
\r
488 #include "GCoptimization.h"
\r
491 // Suppose we have a grid of width 3 and height 2. That is there are 6 pixels
\r
492 // Suppose there are 7 labels.
\r
493 // The neighborhood structure is the usual grid, so we will use constructor C
\r
494 // Let the data costs be:
\r
495 // D(pixel,label) = 0 if pixel < 3 and label = 1
\r
496 // = 10 if pixel < 3 and label is not equal to 1
\r
497 // = 0 if pixel >= 3 and label = 6
\r
498 // = 10 if pixel >= 3 and label is not equal to 6
\r
500 // Let the smoothness terms be the so called "Potts model",
\r
501 // that is Vpq(l_p,l_q) = w_pq if |l_p-l_q| > 1
\r
502 // = 0 if l_p = l_q
\r
503 // and let w_pq be as pictured:
\r
506 // o __2__ o __10__ o
\r
511 // o __8__ o __4__ o
\r
514 /****************************************************************************/
\r
516 void main(int argc, char **argv)
\r
519 int num_pixels = 6, num_labels = 7, width = 3, height = 2;
\r
520 GCoptimization::EnergyTermType *datacost,*smoothcost,*vertWeights,*horizWeights;
\r
521 GCoptimization::EnergyType engS,engD,engT;
\r
523 /* First call the constructor for a grid graph */
\r
524 GCoptimization *optimize = (GCoptimization *) new GCoptimization(width,height,num_labels,SET_ALL_AT_ONCE,SET_ALL_AT_ONCE);
\r
526 datacost = (GCoptimization::EnergyTermType *) new GCoptimization::EnergyTermType[num_pixels*num_labels];
\r
527 smoothcost = (GCoptimization::EnergyTermType *) new GCoptimization::EnergyTermType[num_labels*num_labels];
\r
528 vertWeights = (GCoptimization::EnergyTermType *) new GCoptimization::EnergyTermType[num_pixels];
\r
529 horizWeights = (GCoptimization::EnergyTermType *) new GCoptimization::EnergyTermType[num_pixels];
\r
531 // Fill in the datacost matrix with the correct values
\r
532 for ( int pix = 0; pix < num_pixels; pix++ )
\r
533 for ( int l = 0; l < num_labels; l++ )
\r
535 if ( pix < 3 && l == 1)
\r
536 datacost[pix*num_labels+l] = 0;
\r
537 else if ( pix < 3 && l != 1)
\r
538 datacost[pix*num_labels+l] = 10;
\r
539 else if ( pix >= 3 && l == 6 )
\r
540 datacost[pix*num_labels+l] = 0;
\r
541 else datacost[pix*num_labels+l] = 10;
\r
547 // Fill in the smoothcost matrix with the correct values
\r
548 for ( int i = 0; i < num_labels; i++ )
\r
549 for ( int j = 0; j < num_labels; j++ )
\r
551 smoothcost[i+j*num_labels] = 1;
\r
552 else smoothcost[i+j*num_labels] = 0;
\r
555 // Fill in the horizontal and vertical matrices with the correct values
\r
557 vertWeights[0] = 3;
\r
558 vertWeights[1] = 1;
\r
559 vertWeights[2] = 5;
\r
561 horizWeights[0] = 2;
\r
562 horizWeights[1] = 10;
\r
563 horizWeights[3] = 8;
\r
564 horizWeights[4] = 4;
\r
566 optimize->setData(datacost);
\r
567 optimize->setSmoothness(smoothcost,horizWeights,vertWeights);
\r
569 ///////////////////////////////////////////////////////////////////////
\r
570 /* Now the energy is completely specified. Can call any optimization */
\r
574 // Just for fun, start with random labeling
\r
575 for ( i = 0; i < num_pixels; i++ )
\r
576 optimize->setLabel(i,rand()%num_labels);
\r
580 engD = optimize->giveDataEnergy();
\r
581 engS = optimize->giveSmoothEnergy();
\r
583 printf("\nBefore optimization, the smooth energy is %d, data energy %d, total %d",engS,engD,engS+engD);
\r
585 engT = optimize->alpha_beta_swap(1,0); //run swap algorithm on labels 1 and 0
\r
586 engD = optimize->giveDataEnergy();
\r
587 engS = optimize->giveSmoothEnergy();
\r
590 printf("\nAfter swapping labels 0 and 1, the smooth energy is %d, data energy %d, total %d",engS,engD,engS+engD);
\r
592 engT = optimize->expansion(); //run expansion algorithm to convergence
\r
594 engD = optimize->giveDataEnergy();
\r
595 engS = optimize->giveSmoothEnergy();
\r
597 printf("\nAfter optimization, the smooth energy is %d, data energy %d, total %d",engS,engD,engS+engD);
\r
598 for( i = 0; i < num_pixels; i++ )
\r
599 printf("\nPixel %d has label %d",i,optimize->whatLabel(i));
\r
603 __________________________________________________________________
\r