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
75struct 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
86struct 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
99inline 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
114inline 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
146void 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
159void 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
180void 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
343int 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
518void 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
893bool 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
991void 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
1015void 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
1068void 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
1125void 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
1274bool  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
1313bool  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
1332bool  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
1350bool  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
1368CCvGraphCutMorpher::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 */
1382