Move the sources to trunk
[opencv] / cvaux / src / enmin.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                        Intel License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000, Intel Corporation, all rights reserved.
14 // Third party copyrights are property of their respective owners.
15 //
16 // Redistribution and use in source and binary forms, with or without modification,
17 // are permitted provided that the following conditions are met:
18 //
19 //   * Redistribution's of source code must retain the above copyright notice,
20 //     this list of conditions and the following disclaimer.
21 //
22 //   * Redistribution's in binary form must reproduce the above copyright notice,
23 //     this list of conditions and the following disclaimer in the documentation
24 //     and/or other materials provided with the distribution.
25 //
26 //   * The name of Intel Corporation may not be used to endorse or promote products
27 //     derived from this software without specific prior written permission.
28 //
29 // This software is provided by the copyright holders and contributors "as is" and
30 // any express or implied warranties, including, but not limited to, the implied
31 // warranties of merchantability and fitness for a particular purpose are disclaimed.
32 // In no event shall the Intel Corporation or contributors be liable for any direct,
33 // indirect, incidental, special, exemplary, or consequential damages
34 // (including, but not limited to, procurement of substitute goods or services;
35 // loss of use, data, or profits; or business interruption) however caused
36 // and on any theory of liability, whether in contract, strict liability,
37 // or tort (including negligence or otherwise) arising in any way out of
38 // the use of this software, even if advised of the possibility of such damage.
39 //
40 //M*/
41
42 #include "_cvaux.h"
43
44 #if 0
45
46 //#include "windows.h"
47
48 //#define ALPHA_EXPANSION
49
50 #ifndef ALPHA_EXPANSION
51     #define ALPHA_BETA_EXCHANGE
52 #endif
53
54 #define MAX_LABEL 20
55
56 #define CV_MODULE(xxx) \
57     ( (xxx) < 0 ? -(xxx) : (xxx) )
58
59 #define CV_MAX3(xxx1,xxx2,xxx3) \
60     ( (xxx1) > (xxx2) && (xxx1) > (xxx3) ? (xxx1) : \
61         (xxx2) > (xxx3) ? (xxx2) : (xxx3) )
62
63 #define CV_MIN2(xxx1,xxx2) \
64     ( (xxx1) < (xxx2) ? (xxx1) : (xxx2) )
65
66 #define getSizeForGraph(xxxType) \
67     ( sizeof(xxxType) < 8 ? 8 : sizeof(xxxType) + 4 - sizeof(xxxType) % 4 )
68
69 #define INT_INFINITY 1000000000
70 #define MAX_DIFFERENCE 10
71
72
73 // struct Vertex is used for storing vertices of graph
74 //      coord       - coordinate corresponding pixel on the real image line
75 struct Vertex
76 {
77     CvGraphVtx vtx;
78     int coord;
79 };
80
81 // struct Edge is used for storing edges of graph
82 //      weight      - weight of the edge ( maximum flow via the edge )
83 //      flow        - current flow via the edge
84 //      srcVtx      - coordinate of source vertex on the real image line
85 //      destVtx     - coordinate of destination vertex on the real image line
86 struct Edge
87 {
88     CV_GRAPH_EDGE_FIELDS()
89     int weight;
90     int flow;
91     int srcVtx;
92     int destVtx;
93 };
94
95 // function vFunc is energy function which determines the difference
96 //   between two labels ( alpha and beta )
97 //      alpha       - label number one
98 //      beta        - label number two
99 inline int vFunc( int alpha, int beta )
100 {
101     if( alpha == beta )
102         return 0;
103     else
104         return /*1*//*5*/10;
105 }
106
107 // function dFunc is energy function which determines energy of interaction
108 //   between pixel ( having coordinate xCoord ) and label
109 //          leftLine        - line of left image
110 //          rightLine       - line of right image
111 //          xCoord          - coordinate of pixel on the left image
112 //          label           - label corresponding to the pixel
113 //          width           - width of the image line in pixels
114 inline int dFunc( unsigned char* leftLine,
115                   unsigned char* rightLine,
116                   int xCoord,
117                   int label,
118                   int width)
119 {
120     assert( xCoord >= 0 && xCoord < width );
121     int r, g, b;
122     int yCoord = xCoord + label;
123
124     if( yCoord >= width )
125         yCoord = width;
126     if( yCoord < 0 )
127         yCoord = 0;
128
129     r = leftLine[ 3 * xCoord     ] - rightLine[ 3 * yCoord     ];
130     g = leftLine[ 3 * xCoord + 1 ] - rightLine[ 3 * yCoord + 1 ];
131     b = leftLine[ 3 * xCoord + 2 ] - rightLine[ 3 * yCoord + 2 ];
132
133     r = CV_MODULE( r );
134     g = CV_MODULE( g );
135     b = CV_MODULE( b );
136
137     return CV_MAX3( r, g, b );
138 }
139
140 // function allocTempMem allocates all temporary memory needed for work
141 //   of some function
142 //      memPtr          - pointer to pointer to the large block of memory
143 //      verticesPtr     - pointer to pointer to block of memory for
144 //                        temporary storing vertices
145 //      width           - width of line in pixels
146 void allocTempMem( int** memPtr,
147                    int** verticesPtr,
148                    int width )
149 {
150     int* tempPtr = ( int* ) malloc( ( width + 2 ) * 7 * sizeof( int ) );
151     *verticesPtr = tempPtr;
152     *memPtr = *verticesPtr + width + 2;
153 }
154
155 // function freeTempMem frees all allocated by allocTempMem function memory
156 //      memPtr          - pointer to pointer to the large block of memory
157 //      verticesPtr     - pointer to pointer to block of memory for
158 //                        temporary storing vertices
159 void freeTempMem( int** memPtr,
160                   int** verticesPtr )
161 {
162     free( ( void* )( *verticesPtr ) );
163     *verticesPtr = NULL;
164     *memPtr = NULL;
165 }
166
167 // function makeGraph creates initial graph to find maximum flow in it
168 //      graphPtr        - pointer to pointer to CvGraph structure to be filled
169 //      leftLine        - pointer to the left image line
170 //      rightLine       - pointer to the right image line
171 //      alpha           - label number one for doing exchange
172 //      beta            - label number two for doing exchange
173 //      corr            - pointer to array of correspondences ( each element
174 //                        of array includes disparity of pixel on right image
175 //                        for pixel each on left image ). This pointer direct
176 //                        to correspondence ofr one line only
177 //      width           - width of image lines in pixels
178 //      storage         - pointer to CvMemStorage structure which contains
179 //                        memory storage
180 void makeGraph( CvGraph** graphPtr,
181                 unsigned char* leftLine,
182                 unsigned char* rightLine,
183                 int alpha,
184                 int beta,
185                 int* corr,
186                 int width,
187                 CvMemStorage* storage )
188 {
189     int i;
190
191     if( *graphPtr )  {
192         cvClearGraph( *graphPtr );
193     }
194     /*else {*/
195         *graphPtr = cvCreateGraph( CV_SEQ_KIND_GRAPH | CV_GRAPH_FLAG_ORIENTED,
196                                    sizeof( CvGraph ),
197                                    getSizeForGraph( Vertex ),
198                                    getSizeForGraph( Edge ),
199                                    storage );
200     /*}*/
201
202     CvGraph* graph = *graphPtr;
203
204     #ifdef ALPHA_BETA_EXCHANGE
205
206     CvGraphVtx* newVtxPtr;
207     for( i = 0; i < width; i ++ )
208     {
209         if( corr[i] == alpha || corr[i] == beta ) {
210             cvGraphAddVtx( graph, NULL, &newVtxPtr );
211             ( ( Vertex* )newVtxPtr ) -> coord = i;
212         }
213     } /* for( i = 0; i < width; i ++ ) */
214     cvGraphAddVtx( graph, NULL, &newVtxPtr );
215     if( newVtxPtr )
216         ( ( Vertex* )newVtxPtr ) -> coord = -2; /* adding alpha vertex */
217     cvGraphAddVtx( graph, NULL, &newVtxPtr );
218     if( newVtxPtr )
219         ( ( Vertex* )newVtxPtr ) -> coord = -1; /* adding beta vertex */
220
221     int alphaVtx = graph -> total - 2;
222     int betaVtx = graph -> total - 1;
223     CvGraphEdge* newEdgePtr;
224     CvGraphVtx* vtxPtr;
225     if( graph -> total > 2 )
226     {
227         for( i = 0; i < alphaVtx; i ++ )
228         {
229             vtxPtr = cvGetGraphVtx( graph, i );
230
231             /* adding edge oriented from alpha vertex to current vertex */
232             cvGraphAddEdge( graph, alphaVtx, i, NULL, &newEdgePtr );
233             ( ( Edge* )newEdgePtr ) -> weight = dFunc( leftLine,
234                 rightLine,
235                 ( ( Vertex* )vtxPtr ) -> coord,
236                 alpha,
237                 width );
238             ( ( Edge* )newEdgePtr ) -> flow = 0;
239             if( i != 0 ) {
240                 CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i - 1 );
241                 /* if vertices are neighbours */
242                 if( ( ( Vertex* )tempVtxPtr ) -> coord + 1 ==
243                     ( ( Vertex* )vtxPtr ) -> coord )
244                 {
245                     ( ( Edge* )newEdgePtr ) -> weight +=
246                         vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
247                                alpha );
248                     /* adding neighbour edge oriented from current vertex
249                        to the previous one */
250                     CvGraphEdge* tempEdgePtr;
251                     cvGraphAddEdge( graph, i, i - 1, NULL, &tempEdgePtr );
252                     ( ( Edge* )tempEdgePtr ) -> weight = vFunc( alpha, beta );
253                     ( ( Edge* )tempEdgePtr ) -> flow = 0;
254                     ( ( Edge* )tempEdgePtr ) -> srcVtx =
255                         ( ( Vertex* )vtxPtr ) -> coord;
256                     ( ( Edge* )tempEdgePtr ) -> destVtx =
257                         ( ( Vertex* )tempVtxPtr ) -> coord;
258                 }
259             } /* if( i != 0 ) */
260             if( i != alphaVtx - 1 ) {
261                 CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i + 1 );
262                 /* if vertices are neighbours */
263                 if( ( ( Vertex* )tempVtxPtr ) -> coord - 1 ==
264                     ( ( Vertex* )vtxPtr ) -> coord )
265                 {
266                     ( ( Edge* )newEdgePtr ) -> weight +=
267                         vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
268                                alpha );
269                     /* adding neighbour edge oriented from current vertex
270                        to the next one */
271                     CvGraphEdge* tempEdgePtr;
272                     cvGraphAddEdge( graph, i, i + 1, NULL, &tempEdgePtr );
273                     ( ( Edge* )tempEdgePtr ) -> weight = vFunc( alpha, beta );
274                     ( ( Edge* )tempEdgePtr ) -> flow = 0;
275                     ( ( Edge* )tempEdgePtr ) -> srcVtx =
276                         ( ( Vertex* )vtxPtr ) -> coord;
277                     ( ( Edge* )tempEdgePtr ) -> destVtx =
278                         ( ( Vertex* )tempVtxPtr ) -> coord;
279                 }
280             } /* if( i != alphaVtx - 1 ) */
281             ( ( Edge* )newEdgePtr ) -> flow = 0;
282             ( ( Edge* )newEdgePtr ) -> srcVtx = -1; /* source vertex is alpha
283                                                        vertex */
284             ( ( Edge* )newEdgePtr ) -> destVtx = ( ( Vertex* )vtxPtr ) -> coord;
285
286             /* adding edge oriented from current vertex to beta vertex */
287             cvGraphAddEdge( graph, i, betaVtx, NULL, &newEdgePtr );
288             ( ( Edge* )newEdgePtr ) -> weight = dFunc( leftLine,
289                 rightLine,
290                 ( ( Vertex* )vtxPtr ) -> coord,
291                 beta,
292                 width );
293             ( ( Edge* )newEdgePtr ) -> flow = 0;
294             if( i != 0 ) {
295                 CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i - 1 );
296                 /* if vertices are neighbours */
297                 if( ( ( Vertex* )tempVtxPtr ) -> coord + 1 ==
298                     ( ( Vertex* )vtxPtr ) -> coord )
299                 {
300                     ( ( Edge* )newEdgePtr ) -> weight +=
301                         vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
302                                beta );
303                 }
304             } /* if( i != 0 ) */
305             if( i != alphaVtx - 1 ) {
306                 CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i + 1 );
307                 /* if vertices are neighbours */
308                 if( ( ( Vertex* )tempVtxPtr ) -> coord - 1 ==
309                     ( ( Vertex* )vtxPtr ) -> coord )
310                 {
311                     ( ( Edge* )newEdgePtr ) -> weight +=
312                         vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
313                                beta );
314                 }
315             } /* if( i != alphaVtx - 1 ) */
316             ( ( Edge* )newEdgePtr ) -> flow = 0;
317             ( ( Edge* )newEdgePtr ) -> srcVtx =
318                 ( ( Vertex* )vtxPtr ) -> coord;
319             ( ( Edge* )newEdgePtr ) -> destVtx = -2; /* destination vertex is
320                                                         beta vertex */
321
322         } /* for( i = 0; i < graph -> total - 2; i ++ ) */
323
324     } /* if( graph -> total > 2 ) */
325
326     #endif /* #ifdef ALPHA_BETA_EXCHANGE */
327
328     #ifdef ALPHA_EXPANSION
329     #endif /* #ifdef ALPHA_EXPANSION */
330
331 } /* makeGraph */
332
333 // function makeHelpGraph creates help graph using initial graph
334 //      graph           - pointer to initial graph ( represented by CvGraph
335 //                        structure )
336 //      hlpGraphPtr     - pointer to pointer to new help graph
337 //      storage         - pointer to CvStorage structure
338 //      mem             - pointer to memory allocated by allocTempMem function
339 //      vertices        - pointer to memory allocated by allocTempMem function
340 //      verticesCountPtr- pointer to value containing number of vertices
341 //                        in vertices array
342 //      width           - width of image line in pixels
343 int makeHelpGraph( CvGraph* graph,
344                    CvGraph** hlpGraphPtr,
345                    CvMemStorage* storage,
346                    int* mem,
347                    int* vertices,
348                    int* verticesCountPtr,
349                    int width )
350 {
351     int u, v;
352     int* order = mem;
353     int* lengthArr = order + width + 2;
354     int s = graph -> total - 2; /* source vertex */
355     int t = graph -> total - 1; /* terminate vertex */
356     int orderFirst;
357     int orderCount;
358     int &verticesCount = *verticesCountPtr;
359     CvGraph* hlpGraph;
360
361     if( *hlpGraphPtr )  {
362         cvClearGraph( *hlpGraphPtr );
363     }
364     else {
365         *hlpGraphPtr = cvCreateGraph( CV_SEQ_KIND_GRAPH |
366                                           CV_GRAPH_FLAG_ORIENTED,
367                                       sizeof( CvGraph ),
368                                       getSizeForGraph( Vertex ),
369                                       getSizeForGraph( Edge ),
370                                       storage );
371     }
372
373     hlpGraph = *hlpGraphPtr;
374
375     /* initialization */
376     for( u = 0; u < graph -> total; u ++ )
377     {
378         lengthArr[ u ] = INT_INFINITY;
379         cvGraphAddVtx( hlpGraph, NULL, NULL );
380     } /* for( u = 0; u < graph -> total - 1; u ++ ) */
381
382     orderFirst = 0;
383     orderCount = 0;
384     verticesCount = 0;
385     lengthArr[ s ] = 0;
386
387     /* add vertex s to order */
388     order[ orderCount ] = s;
389     orderCount ++;
390
391     while( orderCount != orderFirst )
392     {
393         /* getting u from order */
394         u = order[ orderFirst ];
395         orderFirst ++;
396
397         /* adding u to vertex array */
398         vertices[ verticesCount ] = u;
399         verticesCount ++;
400
401         int ofs;
402         CvGraphVtx* graphVtx = cvGetGraphVtx( graph, u );
403
404         /* processing all vertices outgoing from vertex u */
405         CvGraphEdge* graphEdge = graphVtx -> first;
406         while( graphEdge )
407         {
408             int tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[1] );
409             ofs = tempVtxIdx == u;
410             if( !ofs )
411             {
412                 v = tempVtxIdx;
413
414                 CvGraphEdge* tempGraphEdge = cvFindGraphEdge( graph, u, v );
415                 if( ( lengthArr[ u ] < lengthArr[ v ] )
416                     && ( lengthArr[ v ] <= lengthArr[ t ] )
417                     && ( ( ( Edge* )tempGraphEdge ) -> flow <
418                         ( ( Edge* )tempGraphEdge ) -> weight ) )
419                 {
420                     if( lengthArr[ v ] == INT_INFINITY )
421                     {
422                         /* adding vertex v to order */
423                         order[ orderCount ] = v;
424                         orderCount ++;
425
426                         lengthArr[ v ] = lengthArr[ u ] + 1;
427                         CvGraphEdge* tempGraphEdge2;
428
429                         cvGraphAddEdge( hlpGraph, u, v, NULL, &tempGraphEdge2 );
430                         ( ( Edge* )tempGraphEdge2 ) -> flow = 0;
431
432                         ( ( Edge* )tempGraphEdge2 ) -> weight =
433                             ( ( Edge* )tempGraphEdge ) -> weight -
434                             ( ( Edge* )tempGraphEdge ) -> flow;
435
436                     } /* if( length[ v ] == INT_INFINITY ) */
437
438                 } /* if( ( lengthArr[ u ] < lengthArr[ v ] ) ... */
439
440             } /* if( !ofs ) */
441
442             graphEdge = graphEdge -> next[ ofs ];
443
444         } /* while( graphEdge ) */
445
446         /* processing all vertices incoming to vertex u */
447         graphEdge = graphVtx -> first;
448         while( graphEdge )
449         {
450             int tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[1] );
451             ofs = tempVtxIdx == u;
452             if( ofs )
453             {
454                 tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[0] );
455                 v = tempVtxIdx;
456
457                 CvGraphEdge* tempGraphEdge = cvFindGraphEdge( graph, v, u );
458                 if( ( lengthArr[ u ] < lengthArr[ v ] )
459                     && ( lengthArr[ v ] <= lengthArr[ t ] )
460                     && ( ( ( Edge* )tempGraphEdge ) -> flow > 0 ) )
461                 {
462                     if( lengthArr[ v ] == INT_INFINITY )
463                     {
464                         /* adding vertex v to order */
465                         order[ orderCount ] = v;
466                         orderCount ++;
467
468                         lengthArr[ v ] = lengthArr[ u ] + 1;
469                         CvGraphEdge* tempGraphEdge3 = cvFindGraphEdge( hlpGraph, u, v );
470
471                         if( tempGraphEdge3 == NULL ||
472                             ( ( Edge* )tempGraphEdge3 ) -> weight == 0 )
473                         {
474                             CvGraphEdge* tempGraphEdge2;
475                             cvGraphAddEdge( hlpGraph, u, v, NULL,
476                                 &tempGraphEdge2 );
477                             ( ( Edge* )tempGraphEdge2 ) -> flow = 0;
478                             ( ( Edge* )tempGraphEdge2 ) -> weight = 0;
479                         } /* if( tempGraphEdge3 == NULL || ... */
480
481                         ( ( Edge* )tempGraphEdge3 ) -> weight +=
482                             ( ( Edge* )tempGraphEdge ) -> flow;
483
484                     } /* if( length[ v ] == INT_INFINITY ) */
485
486                 } /* if( ( lengthArr[ u ] < lengthArr[ v ] ) ... */
487
488             } /* if( ofs ) */
489
490             graphEdge = graphEdge -> next[ ofs ];
491
492         } /* while( graphEdge ) */
493   
494     } /* while( orderCount != orderFirst ) */
495
496     int i;
497     for( i = 0; i < hlpGraph -> total - 2; i ++ )
498     {
499         CvGraphVtx* hlpGraphVtxTemp = cvGetGraphVtx( hlpGraph, i );
500         if( hlpGraphVtxTemp ) {
501             if( !hlpGraphVtxTemp -> first ) {
502                 cvGraphRemoveVtxByPtr( hlpGraph, hlpGraphVtxTemp );
503             }
504         }
505     } /* for( i = 0; i < hlpGraph -> total - 2; i ++ ) */
506
507     return lengthArr[ t ];
508
509 } /* makeHelpGraph */
510
511 // function makePseudoMaxFlow increases flow in graph by using hlpGraph
512 //      graph           - pointer to initial graph
513 //      hlpGraph        - pointer to help graph
514 //      vertices        - pointer to vertices array
515 //      verticesCount   - number of vertices in vertices array
516 //      mem             - pointer to memory allocated by allocTempMem function
517 //      width           - width of image line in pixels
518 void makePseudoMaxFlow( CvGraph* graph,
519                         CvGraph* hlpGraph,
520                         int* vertices,
521                         int verticesCount,
522                         int* mem,
523                         int width )
524 {
525     int stekCount;
526     int orderFirst;
527     int orderCount;
528     int i;
529     int v, u;
530     int* stek = mem;
531     int* order = stek + width + 2;
532     int* incomFlow = order + width + 2;
533     int* outgoFlow = incomFlow + width + 2;
534     int* flow = outgoFlow + width + 2;
535     int* cargo = flow+ width + 2;
536     int s = graph -> total - 2; /* source vertex */
537     int t = graph -> total - 1; /* terminate vertex */
538     int realVerticesCount = verticesCount;
539
540     stekCount = 0;
541
542     for( i = 0; i < verticesCount; i ++ )
543     {
544         v = vertices[ i ];
545
546         incomFlow[ v ] = outgoFlow[ v ] = 0;
547
548         if( v == s ) {
549             incomFlow[ v ] = INT_INFINITY;
550         } /* if( v == s ) */
551         else {
552             CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
553             CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
554             int ofs;
555
556             while( hlpGraphEdge )
557             {
558                 int vtxIdx = cvGraphVtxIdx( hlpGraph,
559                     hlpGraphEdge -> vtx[1] );
560                 ofs = vtxIdx == v;
561
562                 if( ofs )
563                 {
564                     incomFlow[ v ] += ( ( Edge* )hlpGraphEdge ) -> weight;
565                 } /* if( ofs ) */
566
567                 hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
568             } /* while( hlpGraphEdge ) */
569
570         } /* if( v == s ) else */
571
572         if( v == t ) {
573             outgoFlow[ v ] = INT_INFINITY;
574         } /* if( v == t ) */
575         else {
576             CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
577             CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
578             int ofs;
579
580             while( hlpGraphEdge )
581             {
582                 int vtxIdx = cvGraphVtxIdx( hlpGraph,
583                     hlpGraphEdge -> vtx[1] );
584                 ofs = vtxIdx == v;
585
586                 if( !ofs )
587                 {
588                     outgoFlow[ v ] += ( ( Edge* )hlpGraphEdge ) -> weight;
589                 } /* if( ofs ) */
590
591                 hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
592             } /* while( hlpGraphEdge ) */
593
594         } /* if( v == t ) else */
595
596         flow[ v ] = CV_MIN2( incomFlow[ v ], outgoFlow[ v ] );
597
598         if( !flow[ v ] ) {
599             stek[ stekCount ] = v;
600             stekCount ++;
601         } /* if( !flow[ v ] ) */
602
603     } /* for( i = 0; i < verticesCount; i ++ ) */
604
605     for( i = 0; i < verticesCount; i ++ )
606     {
607         v = vertices[ i ];
608         cargo[ v ] = 0;
609     } /* for( i = 0; i < verticesCount; i ++ ) */
610
611     while( realVerticesCount > 2 )
612     {
613         /* deleting all vertices included in stek */
614         while( stekCount )
615         {
616             v = stek[ stekCount - 1 ];
617             stekCount --;
618
619             /* deleting edges incoming to v and outgoing from v */
620             int ofs;
621             CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
622             CvGraphEdge* hlpGraphEdge;
623             if( hlpGraphVtx ) {
624                 hlpGraphEdge = hlpGraphVtx -> first;
625             }
626             else {
627                 hlpGraphEdge = NULL;
628             }
629             while( hlpGraphEdge )
630             {
631                 CvGraphVtx* hlpGraphVtx2 = hlpGraphEdge -> vtx[ 1 ];
632                 int hlpGraphVtxIdx2 = cvGraphVtxIdx( hlpGraph,
633                     hlpGraphVtx2 );
634                 ofs = hlpGraphVtxIdx2 == v;
635
636                 if( ofs )
637                 {
638                     /* hlpGraphEdge is incoming edge */
639                     CvGraphVtx* hlpGraphVtx3 = hlpGraphEdge -> vtx[0];
640                     u = cvGraphVtxIdx( hlpGraph,
641                                        hlpGraphVtx3 );
642                     outgoFlow[ u ] -= ( ( Edge* )hlpGraphEdge ) -> weight
643                         - ( ( Edge* )hlpGraphEdge ) -> flow;
644                     cvGraphRemoveEdgeByPtr( hlpGraph,
645                                             hlpGraphVtx3,
646                                             hlpGraphVtx2 );
647                     if( flow[ u ] != 0 ) {
648                         flow[ u ] = CV_MIN2( incomFlow[u], outgoFlow[u] );
649                         if( flow[ u ] == 0 ) {
650                             stek[ stekCount ] = u;
651                             stekCount ++;
652                         }
653                     }
654                 } /* if( ofs ) */
655                 else
656                 {
657                     /* hlpGraphEdge is outgoing edge */
658                     CvGraphVtx* hlpGraphVtx3 = hlpGraphEdge -> vtx[1];
659                     int u = cvGraphVtxIdx( hlpGraph,
660                                               hlpGraphVtx3 );
661                     incomFlow[ u ] -= ( ( Edge* )hlpGraphEdge ) -> weight
662                         - ( ( Edge* )hlpGraphEdge ) -> flow;
663                     cvGraphRemoveEdgeByPtr( hlpGraph,
664                                             hlpGraphVtx2,
665                                             hlpGraphVtx3 );
666                     if( flow[ u ] != 0 ) {
667                         flow[ u ] = CV_MIN2( incomFlow[u], outgoFlow[u] );
668                         if( flow[ u ] == 0 ) {
669                             stek[ stekCount ] = u;
670                             stekCount ++;
671                         }
672                     }
673                 } /* if( ofs ) else */
674
675                 hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
676
677             } /* while( hlpGraphEdge ) */
678
679             /* deleting vertex v */
680             cvGraphRemoveVtx( hlpGraph, v );
681             realVerticesCount --;
682
683         } /* while( stekCount ) */
684
685         if( realVerticesCount > 2 ) /* the flow is not max still */
686         {
687             int p = INT_INFINITY;
688             int r = -1;
689             CvGraphVtx* graphVtx;
690
691             if( realVerticesCount == 3 ) {
692                 r = r;
693             }
694             for( i = 0; i < hlpGraph -> total - 2; i ++ )
695             {
696                 graphVtx = cvGetGraphVtx( hlpGraph, i );
697                 if( graphVtx ) {
698                     v = cvGraphVtxIdx( hlpGraph, graphVtx );
699                     if( flow[ v ] < p ) {
700                         r = v;
701                         p = flow[ v ];
702                     }
703                 }
704
705             } /* for( i = 0; i < hlpGraph -> total - 2; i ++ ) */
706
707             /* building of size p flow from r to t */
708             orderCount = orderFirst = 0;
709             order[ orderCount ] = r;
710             orderCount ++;
711
712             v = order[ orderFirst ];
713             orderFirst ++;
714
715             cargo[ r ] = p;
716             do /* while( v != t ) */
717             {
718                 incomFlow[ v ] -= cargo[ v ];
719                 outgoFlow[ v ] -= cargo[ v ];
720                 flow[ v ] -= cargo[ v ];
721
722                 if( flow[ v ] == 0 ) {
723                     stek[ stekCount ] = v;
724                     stekCount ++;
725                 }
726
727                 if( v == t ) {
728                     cargo[ v ] = p;
729                 }
730                 else
731                 {
732                     int ofs;
733                     CvGraphVtx* hlpGraphVtx2;
734                     CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
735                     CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
736                     CvGraphEdge* hlpGraphEdge2 = NULL;
737
738                     while( hlpGraphEdge && cargo[ v ] > 0 )
739                     {
740                         hlpGraphVtx2 = hlpGraphEdge -> vtx[ 1 ];
741                         u = cvGraphVtxIdx( hlpGraph, hlpGraphVtx2 );
742                         ofs = u == v;
743
744                         if( !ofs )
745                         {
746                             if( cargo[ u ] == 0 ) {
747                                 order[ orderCount ] = u;
748                                 orderCount ++;
749                             }
750                             int delta = ( ( Edge* )hlpGraphEdge ) -> weight
751                                 - ( ( Edge* )hlpGraphEdge ) -> flow;
752                             delta = CV_MIN2( cargo[ v ], delta );
753                             ( ( Edge* )hlpGraphEdge ) -> flow += delta;
754                             cargo[ v ] -= delta;
755                             cargo[ u ] += delta;
756                             if( ( ( Edge* )hlpGraphEdge ) -> weight ==
757                                 ( ( Edge* )hlpGraphEdge ) -> flow )
758                             {
759                                 /* deleting hlpGraphEdge */
760                                 hlpGraphEdge2 = hlpGraphEdge -> next[ ofs ];
761                                 CvGraphEdge* graphEdge =
762                                     cvFindGraphEdge( graph, v, u );
763                                 ( ( Edge* )graphEdge ) -> flow +=
764                                     ( ( Edge* )hlpGraphEdge ) -> flow;
765                                 cvGraphRemoveEdgeByPtr( hlpGraph,
766                                     hlpGraphEdge -> vtx[0],
767                                     hlpGraphEdge -> vtx[1] );
768                             }
769                         } /* if( !ofs ) */
770
771                         if( hlpGraphEdge2 ) {
772                             hlpGraphEdge = hlpGraphEdge2;
773                             hlpGraphEdge2 = NULL;
774                         }
775                         else {
776                             hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
777                         }
778                     } /* while( hlpGraphEdge && cargo[ v ] > 0 ) */
779
780                 } /* if( v == t ) else */
781
782                 v = order[ orderFirst ];
783                 orderFirst ++;
784
785             } while( v != t ); /* do */
786
787             /* building of size p flow from s to r */
788             orderCount = orderFirst = 0;
789             order[ orderCount ] = r;
790             orderCount ++;
791
792             v = order[ orderFirst ];
793             orderFirst ++;
794
795             cargo[ r ] = p;
796             do /* while( v != s ) */
797             {
798                 if( v != r )
799                 {
800                     incomFlow[ v ] -= cargo[ v ];
801                     outgoFlow[ v ] -= cargo[ v ];
802                     flow[ v ] -= cargo[ v ];
803                     if( flow[ v ] == 0 ) {
804                         stek[ stekCount ] = v;
805                         stekCount ++;
806                     }
807                 } /* if( v != r ) */
808
809                 if( v == s ) {
810                     cargo[ v ] = 0;
811                 } /* if( v == s ) */
812                 else
813                 {
814                     int ofs;
815
816                     CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
817                     CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
818                     CvGraphEdge* hlpGraphEdge2 = NULL;
819                     while( hlpGraphEdge && cargo[ v ] > 0 )
820                     {
821                         u = cvGraphVtxIdx( hlpGraph,
822                                 hlpGraphEdge -> vtx[ 1 ] );
823                         ofs = u == v;
824
825                         if( ofs )
826                         {
827                             u = cvGraphVtxIdx( hlpGraph,
828                                     hlpGraphEdge -> vtx[ 0 ] );
829
830                             if( cargo[ u ] == 0 ) {
831                                 order[ orderCount ] = u;
832                                 orderCount ++;
833                             }
834
835                             int delta = ( ( Edge* )hlpGraphEdge ) -> weight
836                                 - ( ( Edge* )hlpGraphEdge ) -> flow;
837
838                             delta = CV_MIN2( cargo[ v ], delta );
839                             
840                             (( ( Edge* )hlpGraphEdge ) -> flow) += delta;
841
842                             cargo[ v ] -= delta;
843                             cargo[ u ] += delta;
844
845                             if( ( ( Edge* )hlpGraphEdge ) -> weight ==
846                                 ( ( Edge* )hlpGraphEdge ) -> flow )
847                             {
848                                 hlpGraphEdge2 = hlpGraphEdge -> next[ ofs ];
849                                 CvGraphEdge* graphEdge =
850                                     cvFindGraphEdge( graph, u, v );
851                                 ( ( Edge* )graphEdge ) -> flow +=
852                                     ( ( Edge* )hlpGraphEdge ) -> flow;
853                                 cvGraphRemoveEdgeByPtr( hlpGraph,
854                                     hlpGraphEdge -> vtx[0],
855                                     hlpGraphEdge -> vtx[1] );
856                             }
857                         } /* if( ofs ) */
858
859                         if( hlpGraphEdge2 ) {
860                             hlpGraphEdge = hlpGraphEdge2;
861                             hlpGraphEdge2 = NULL;
862                         }
863                         else {
864                             hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
865                         }
866                     } /* while( hlpGraphEdge && cargo[ v ] > 0 ) */
867
868                 } /* if( v == s ) else */
869
870                 v = order[ orderFirst ]; //added
871                 orderFirst ++; //added
872
873             } while( v != s ); /* do */
874
875         } /* if( hlpGraph -> total > 2 ) */
876
877     } /* while( hlpGraph -> total > 2 ) */
878
879 } /* makePseudoMaxFlow */
880
881
882 // function oneStep produces one alpha-beta exchange for one line of images
883 //      leftLine        - pointer to the left image line
884 //      rightLine       - pointer to the right image line
885 //      alpha           - label number one
886 //      beta            - label number two
887 //      corr            - pointer to correspondence array for this line
888 //      width           - width of image line in pixels
889 //      mem             - pointer to memory allocated by allocTempMem function
890 //      vertices        - pointer to vertices array allocated by allocTempMem
891 //                        function
892 //      storage         - pointer to CvMemStorage structure
893 bool oneStep( unsigned char* leftLine,
894               unsigned char* rightLine,
895               int alpha,
896               int beta,
897               int* corr,
898               int width,
899               int* mem,
900               int* vertices,
901               CvMemStorage* storage )
902 {
903     CvGraph* graph = NULL;
904     CvGraph* hlpGraph = NULL;
905     CvMemStoragePos storagePos;
906     int i;
907     bool change = false;
908     cvSaveMemStoragePos( storage, &storagePos );
909
910     int verticesCount;
911
912     makeGraph( &graph, leftLine, rightLine, alpha, beta, corr, width, storage );
913
914     int s = graph -> total - 2; /* source vertex - alpha vertex */
915     //int t = graph -> total - 1; /* terminate vertex - beta vertex */
916
917     int length = makeHelpGraph( graph,
918                                 &hlpGraph,
919                                 storage,
920                                 mem,
921                                 vertices,
922                                 &verticesCount,
923                                 width );
924     while( length != INT_INFINITY )
925     {
926         change = true;
927         makePseudoMaxFlow( graph,
928                            hlpGraph,
929                            vertices,
930                            verticesCount,
931                            mem,
932                            width );
933         cvClearGraph( hlpGraph );
934         length = makeHelpGraph( graph,
935                                 &hlpGraph,
936                                 storage,
937                                 mem,
938                                 vertices,
939                                 &verticesCount,
940                                 width );
941     } /* while( length != INT_INFINITY ) */
942
943     int coord;
944     CvGraphVtx* graphVtx;
945     for( i = 0; i < s; i ++ )
946     {
947         CvGraphEdge* graphEdge = cvFindGraphEdge( graph, s, i );
948
949         if( ( ( Edge* )graphEdge ) -> weight ==
950             ( ( Edge* )graphEdge ) -> flow )
951         { /* this vertex must have alpha label */
952             graphVtx = cvGetGraphVtx( graph, i );
953             coord = ( ( Vertex* )graphVtx )-> coord;
954             if( corr[ coord ] != alpha ) {
955                 corr[ coord ] = alpha; //added
956                 change = true;
957             }
958             else {
959                 corr[ coord ] = alpha;
960             }
961         } /* if( ( ( Edge* )graphEdge ) -> weight == ... */
962         else
963         { /* this vertex must have beta label */
964             graphVtx = cvGetGraphVtx( graph, i );
965             coord = ( ( Vertex* )graphVtx )-> coord;
966             if( corr[ coord ] != beta ) {
967                 corr[ coord ] = beta; //added
968                 change = true;
969             }
970             else {
971                 corr[ coord ] = beta;
972             }
973         } /* if( ( ( Edge* )graphEdge ) -> weight == ... else */
974
975     } /* for( i = 0; i < s; i ++ ) */
976
977     cvClearGraph( hlpGraph );
978     cvClearGraph( graph );
979
980     cvRestoreMemStoragePos( storage, &storagePos );
981
982     return change;
983
984 } /* oneStep */
985
986 // function initCorr fills correspondence array with initial values
987 //      corr                - pointer to correspondence array for this line
988 //      width               -  width of image line in pixels
989 //      maxPixelDifference  - maximum value of difference between the same
990 //                            point painted on two images
991 void initCorr( int* corr, int width, int maxPixelDifference )
992 {
993     int i;
994     int pixelDifferenceRange = maxPixelDifference * 2 + 1;
995
996     for( i = 0; i < width; i ++ )
997     {
998         corr[ i ] = i % pixelDifferenceRange - maxPixelDifference;
999     }
1000 } /* initCorr */
1001
1002 // function oneLineCorr fully computes one line of images
1003 //      leftLine                - pointer to the left image line
1004 //      rightLine               - pointer to the right image line
1005 //      corr                    - pointer to the correspondence array for one
1006 //                                line
1007 //      mem                     - pointer to memory allocated by allocTempMem
1008 //                                function
1009 //      vertices                - pointer to memory allocated by allocTempMem
1010 //                                function
1011 //      width                   - width of image line in pixels
1012 //      maxPixelDifference      - maximum value of pixel differences in pixels
1013 //      storage                 - pointer to CvMemStorage struct which
1014 //                                contains memory storage
1015 void oneLineCorr( unsigned char* leftLine,
1016                   unsigned char* rightLine,
1017                   int* corr,
1018                   int* mem,
1019                   int* vertices,
1020                   int width,
1021                   int maxPixelDifference,
1022                   CvMemStorage* storage )
1023 {
1024     int result = 1;
1025     int count = 0;
1026     int i, j;
1027
1028     initCorr( corr, width, maxPixelDifference );
1029     while( result )
1030     {
1031         result = 0;
1032
1033         for( i = - maxPixelDifference; i < maxPixelDifference; i ++ )
1034         for( j = i + 1; j <= maxPixelDifference; j ++ )
1035         {
1036             result += (int)oneStep( leftLine,
1037                                rightLine,
1038                                i,
1039                                j,
1040                                corr,
1041                                width,
1042                                mem,
1043                                vertices,
1044                                storage );
1045         } /* for( j = i + 1; j < width; j ++ ) */
1046
1047         count ++;
1048         if( count > /*0*//*1*/2 ) {
1049             break;
1050         }
1051
1052     } /* while( result ) */
1053
1054 } /* oneLineCorr */
1055
1056 // function allLinesCorr computes all lines on the images
1057 //      leftImage           - pointer to the left image
1058 //      leftLineStep        - size of line on the left image in bytes
1059 //      rightImage          - pointer to the right image
1060 //      rightLineStep       - size of line on the right image in bytes
1061 //      width               - width of line in pixels
1062 //      height              - height of image in pixels
1063 //      corr                - pointer to correspondence array for all lines
1064 //      maxPixelDifference  - maximum value of difference between the same
1065 //                            point painted on two images
1066 //      storage             - pointer to CvMemStorage which contains memory
1067 //                            storage
1068 void allLinesCorr( unsigned char* leftImage,
1069                    int leftLineStep,
1070                    unsigned char* rightImage,
1071                    int rightLineStep,
1072                    int width,
1073                    int height,
1074                    int* corr,
1075                    int maxPixelDifference,
1076                    CvMemStorage* storage )
1077 {
1078     int i;
1079     unsigned char* leftLine = leftImage;
1080     unsigned char* rightLine = rightImage;
1081     int* mem;
1082     int* vertices;
1083
1084     allocTempMem( &mem,
1085                   &vertices,
1086                   width );
1087
1088     for( i = 0; i < height; i ++ )
1089     {
1090         oneLineCorr( leftLine,
1091                      rightLine,
1092                      corr + i * width,
1093                      mem,
1094                      vertices,
1095                      width,
1096                      maxPixelDifference,
1097                      storage );
1098         leftLine += leftLineStep;
1099         rightLine += rightLineStep;
1100     } /* for( i = 0; i < height; i ++ ) */
1101
1102     freeTempMem( &mem,
1103                  &vertices );
1104
1105 } /* allLinesCorr */
1106
1107 // This function produces morphing of two images into one image, which includes morphed
1108 // image or depth map
1109 //      _leftImage              - pointer to left image
1110 //      _leftLineStep           - size of line on left image in bytes
1111 //      _rightImage             - pointer to right image
1112 //      _rightLineStep          - size of line on right image in bytes
1113 //      _resultImage            - pointer to result morphed image
1114 //      _resultLineStep         - size of line on result image in bytes
1115 //      _corrArray              - pointer to array with correspondences
1116 //      _numCorrArray           - pointer to array with numbers correspondeces on each line
1117 //      width                   - width of images
1118 //      height                  - height of images
1119 //      alpha                   - position of virtual camera ( 0 corresponds to left image, 1 - to right one )
1120 //      imageNeed               - defines your wishes. if you want to see normal morphed image you have to set
1121 //                                this parameter to morphNormalImage ( this is default value ), else if you want
1122 //                                to see depth map you have to set this parameter to morphDepthMap and set the
1123 //                                next parameter ( maxPixelDifference ) to real value
1124 //      maxPixelDifference      - maximum value of pixel difference on two images
1125 void CCvGraphCutMorpher::Morph( unsigned char* _leftImage,
1126             int _leftLineStep,
1127             unsigned char* _rightImage,
1128             int _rightLineStep,
1129             unsigned char* _resultImage,
1130             int _resultLineStep,
1131             int* _corrArray,
1132             int width,
1133             int height,
1134             float alpha,
1135             morphImageType imageNeed,
1136             int maxDifference
1137           )
1138 {
1139     unsigned char* leftArray    = _leftImage;
1140     unsigned char* middleArray  = _resultImage;
1141     unsigned char* rightArray   = _rightImage;
1142     int leftLineSize            = _leftLineStep;
1143     int middleLineSize          = _resultLineStep;
1144     int rightLineSize           = _rightLineStep;
1145
1146     int lineNumber;
1147     unsigned char* leftTemp;
1148     unsigned char* middleTemp;
1149     unsigned char* rightTemp;
1150     int leftPixel;
1151     int prevLeftPixel;
1152     int middlePixel;
1153     int prevMiddlePixel;
1154     int rightPixel;
1155     int prevRightPixel;
1156     int leftPixel3;
1157     int middlePixel3;
1158     int rightPixel3;
1159     int i;
1160     int j;
1161     int tempIndex;
1162     int* result;
1163     int number;
1164     float alpha1        = 1.0f - alpha;
1165     
1166     for( lineNumber = 0; lineNumber < height; lineNumber ++ )
1167     {
1168         leftTemp    = leftArray + leftLineSize * lineNumber;
1169         middleTemp  = middleArray + middleLineSize * lineNumber;
1170         rightTemp   = rightArray + rightLineSize * lineNumber;
1171         memset( ( void* )middleTemp, 0, middleLineSize );
1172
1173         result = _corrArray + width * lineNumber;
1174         number = width;
1175         
1176         prevLeftPixel   = 0;
1177         prevRightPixel  = prevLeftPixel + result[ 0 ];
1178         if( prevRightPixel >= width ) {
1179             prevRightPixel = width - 1;
1180         }
1181         else if ( prevRightPixel < 0 ) {
1182             prevRightPixel = 0;
1183         }
1184         prevMiddlePixel =
1185             (int)( prevLeftPixel * alpha1 + prevRightPixel * alpha );
1186         for( i = 0; i < number - 1; i ++ )
1187         {
1188             leftPixel       = i;
1189             rightPixel      = i + result[ i ];
1190             if( rightPixel >= width ) {
1191                 rightPixel = width - 1;
1192             }
1193             else if( rightPixel < 0 ) {
1194                 rightPixel = 0;
1195             }
1196             middlePixel     =
1197                 (int)( leftPixel * alpha1 + rightPixel * alpha );
1198             leftPixel3      = leftPixel * 3;
1199             middlePixel3    = middlePixel * 3;
1200             rightPixel3     = rightPixel * 3;
1201             
1202             if( imageNeed == morphDepthMap ) {
1203                 int t   = leftPixel - rightPixel + maxDifference;
1204                 t       = t < 0 ? -t : t;
1205                 t       = t * 255 / maxDifference / 2;
1206                 middleTemp[ middlePixel3 ]      = ( unsigned char )t;
1207                 middleTemp[ middlePixel3 + 1 ]  = ( unsigned char )t;
1208                 middleTemp[ middlePixel3 + 2 ]  = ( unsigned char )t;
1209             } // if( imageNeed == morphDepthMap )
1210             else
1211             {
1212                 middleTemp[ middlePixel3 ] =
1213                     (unsigned char)( leftTemp[ leftPixel3 ] * alpha1
1214                     + rightTemp[ rightPixel3 ] * alpha );
1215                 middleTemp[ middlePixel3 + 1 ] =
1216                     (unsigned char)( leftTemp[ leftPixel3 + 1 ] * alpha1
1217                     + rightTemp[ rightPixel3 + 1 ] * alpha );
1218                 middleTemp[ middlePixel3 + 2 ] =
1219                     (unsigned char)( leftTemp[ leftPixel3 + 2 ] * alpha1
1220                     + rightTemp[ rightPixel3 + 2 ] * alpha );
1221
1222                 if( middlePixel - prevMiddlePixel > 1 ) // occlusion
1223                 {
1224                     if( leftPixel - prevLeftPixel > 1 )
1225                     {
1226                         int LenSrc  = leftPixel - prevLeftPixel - 2;
1227                         int LenDest = middlePixel - prevMiddlePixel - 1;
1228                         for( j = prevMiddlePixel + 1; j < middlePixel; j ++ )
1229                         {
1230                             tempIndex   = prevLeftPixel + 1 + LenSrc *
1231                                 ( j - prevMiddlePixel - 1 ) / LenDest;
1232                             middleTemp[ j * 3 ]     =
1233                                 leftTemp[ tempIndex * 3 ];
1234                             middleTemp[ j * 3 + 1 ] =
1235                                 leftTemp[ tempIndex * 3 + 1 ];
1236                             middleTemp[ j * 3 + 2 ] =
1237                                 leftTemp[ tempIndex * 3 + 2 ];
1238                         }
1239                     } // if( leftPixel - prevLeftPixel > 1 )
1240                     else
1241                     {
1242                         int LenSrc  = rightPixel - prevRightPixel - 2;
1243                         int LenDest = middlePixel - prevMiddlePixel - 1;
1244                         for( j = prevMiddlePixel + 1; j < middlePixel; j ++ )
1245                         {
1246                             tempIndex   = prevRightPixel + 1 + LenSrc *
1247                                 ( j - prevMiddlePixel - 1 ) / LenDest;
1248                             middleTemp[ j * 3 ]     =
1249                                 rightTemp[ tempIndex * 3 ];
1250                             middleTemp[ j * 3 + 1 ] =
1251                                 rightTemp[ tempIndex * 3 + 1 ];
1252                             middleTemp[ j * 3 + 2 ] =
1253                                 rightTemp[ tempIndex * 3 + 2 ];
1254                         }
1255                     } // if( leftPixel - prevLeftPixel > 1 ) else
1256                     
1257                 } // if( middlePixel - prevMiddlePixel > 1 )
1258
1259             } // if( imageNeed == morphDepthMap ) else
1260
1261             if( middlePixel > prevMiddlePixel ) {
1262                 if( leftPixel > prevLeftPixel )
1263                     prevLeftPixel   = leftPixel;
1264                 if( rightPixel > prevRightPixel )
1265                     prevRightPixel  = rightPixel;
1266                 prevMiddlePixel = middlePixel;
1267             }
1268         } // for( i = number - 1; i >= 0; i -- )
1269         
1270     } // for( lineNumber = 0; lineNumber < LeftImage -> m_Raster -> GetHeight() )
1271
1272 } // Morph
1273
1274 bool  CCvGraphCutMorpher::OnCalculateStereo()
1275 {
1276     CvSize imageSizeLeft = GetImageSize( m_left_img ),
1277            imageSizeRight = GetImageSize( m_right_img );
1278
1279     if( ( imageSizeLeft.width != imageSizeRight.width )
1280         || ( imageSizeLeft.height != imageSizeRight.height ) )
1281     {
1282         return false;
1283     }
1284
1285     if( m_corr ) {
1286         free( m_corr );
1287         m_corr = NULL;
1288     }
1289     m_corr = ( int* ) malloc( m_left_img -> width
1290         * m_left_img -> height
1291         * sizeof( int ) );
1292
1293     if( !m_storage ) {
1294         m_storage = cvCreateMemStorage( 0 );
1295         m_isStorageAllocated = true;
1296     }
1297     // Find correspondence for full image and store it to corr array
1298     allLinesCorr( ( unsigned char* )m_left_img -> imageData,
1299                   m_left_img -> widthStep,
1300                   ( unsigned char* )m_right_img -> imageData,
1301                   m_right_img -> widthStep,
1302                   m_left_img -> width,
1303                   m_left_img -> height,
1304                   m_corr,
1305                   m_maxPixelDifference,
1306                   m_storage );
1307
1308     m_isStereoReady = true;
1309
1310     return true;
1311 }
1312
1313 bool  CCvGraphCutMorpher::OnCalculateVirtualImage()
1314 {
1315     // Output image to ResultImage window
1316     Morph( ( unsigned char* )m_left_img -> imageData,
1317            m_left_img ->widthStep,
1318            ( unsigned char* )m_right_img -> imageData,
1319            m_right_img -> widthStep,
1320            ( unsigned char* )m_virtual_img -> imageData,
1321            m_virtual_img -> widthStep,
1322            m_corr,
1323            m_left_img -> width,
1324            m_left_img -> height,
1325            m_pan );
1326
1327     m_isVirtualImageReady = true;
1328
1329     return true;
1330 }
1331
1332 bool  CCvGraphCutMorpher::OnCalculateDisparity()
1333 {
1334     Morph( ( unsigned char* )m_left_img -> imageData,
1335            m_left_img ->widthStep,
1336            ( unsigned char* )m_right_img -> imageData,
1337            m_right_img -> widthStep,
1338            ( unsigned char* )m_disparity_img -> imageData,
1339            m_disparity_img -> widthStep,
1340            m_corr,
1341            m_left_img -> width,
1342            m_left_img -> height,
1343            m_pan,
1344            morphDepthMap,
1345            m_maxPixelDifference );
1346
1347     return true;
1348 }
1349
1350 bool  CCvGraphCutMorpher::OnCalculateDisparityImage()
1351 {
1352     Morph( ( unsigned char* )m_left_img -> imageData,
1353            m_left_img ->widthStep,
1354            ( unsigned char* )m_right_img -> imageData,
1355            m_right_img -> widthStep,
1356            ( unsigned char* )m_disparity_img -> imageData,
1357            m_disparity_img -> widthStep,
1358            m_corr,
1359            m_left_img -> width,
1360            m_left_img -> height,
1361            m_pan,
1362            morphDepthMap,
1363            m_maxPixelDifference );
1364
1365     return true;
1366 }
1367
1368 CCvGraphCutMorpher::CCvGraphCutMorpher()
1369 {
1370     m_maxPixelDifference = MAX_DIFFERENCE;
1371     m_corr = 0;
1372     m_isStereoReady = false;
1373     m_isVirtualImageReady = false;
1374     m_isDisparityReady = false;
1375     m_storage = NULL;
1376     m_isStorageAllocated = false;
1377 }
1378
1379 #endif
1380
1381 /* End of file */