Update to 2.0.0 tree from current Fremantle build
[opencv] / src / cvaux / enmin.cpp
diff --git a/src/cvaux/enmin.cpp b/src/cvaux/enmin.cpp
new file mode 100644 (file)
index 0000000..e083380
--- /dev/null
@@ -0,0 +1,1381 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                        Intel License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2000, Intel Corporation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of Intel Corporation may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+#include "_cvaux.h"
+
+#if 0
+
+//#include "windows.h"
+
+//#define ALPHA_EXPANSION
+
+#ifndef ALPHA_EXPANSION
+    #define ALPHA_BETA_EXCHANGE
+#endif
+
+#define MAX_LABEL 20
+
+#define CV_MODULE(xxx) \
+    ( (xxx) < 0 ? -(xxx) : (xxx) )
+
+#define CV_MAX3(xxx1,xxx2,xxx3) \
+    ( (xxx1) > (xxx2) && (xxx1) > (xxx3) ? (xxx1) : \
+        (xxx2) > (xxx3) ? (xxx2) : (xxx3) )
+
+#define CV_MIN2(xxx1,xxx2) \
+    ( (xxx1) < (xxx2) ? (xxx1) : (xxx2) )
+
+#define getSizeForGraph(xxxType) \
+    ( sizeof(xxxType) < 8 ? 8 : sizeof(xxxType) + 4 - sizeof(xxxType) % 4 )
+
+#define INT_INFINITY 1000000000
+#define MAX_DIFFERENCE 10
+
+
+// struct Vertex is used for storing vertices of graph
+//      coord       - coordinate corresponding pixel on the real image line
+struct Vertex
+{
+    CvGraphVtx vtx;
+    int coord;
+};
+
+// struct Edge is used for storing edges of graph
+//      weight      - weight of the edge ( maximum flow via the edge )
+//      flow        - current flow via the edge
+//      srcVtx      - coordinate of source vertex on the real image line
+//      destVtx     - coordinate of destination vertex on the real image line
+struct Edge
+{
+    CV_GRAPH_EDGE_FIELDS()
+    int weight;
+    int flow;
+    int srcVtx;
+    int destVtx;
+};
+
+// function vFunc is energy function which determines the difference
+//   between two labels ( alpha and beta )
+//      alpha       - label number one
+//      beta        - label number two
+inline int vFunc( int alpha, int beta )
+{
+    if( alpha == beta )
+        return 0;
+    else
+        return /*1*//*5*/10;
+}
+
+// function dFunc is energy function which determines energy of interaction
+//   between pixel ( having coordinate xCoord ) and label
+//          leftLine        - line of left image
+//          rightLine       - line of right image
+//          xCoord          - coordinate of pixel on the left image
+//          label           - label corresponding to the pixel
+//          width           - width of the image line in pixels
+inline int dFunc( unsigned char* leftLine,
+                  unsigned char* rightLine,
+                  int xCoord,
+                  int label,
+                  int width)
+{
+    assert( xCoord >= 0 && xCoord < width );
+    int r, g, b;
+    int yCoord = xCoord + label;
+
+    if( yCoord >= width )
+        yCoord = width;
+    if( yCoord < 0 )
+        yCoord = 0;
+
+    r = leftLine[ 3 * xCoord     ] - rightLine[ 3 * yCoord     ];
+    g = leftLine[ 3 * xCoord + 1 ] - rightLine[ 3 * yCoord + 1 ];
+    b = leftLine[ 3 * xCoord + 2 ] - rightLine[ 3 * yCoord + 2 ];
+
+    r = CV_MODULE( r );
+    g = CV_MODULE( g );
+    b = CV_MODULE( b );
+
+    return CV_MAX3( r, g, b );
+}
+
+// function allocTempMem allocates all temporary memory needed for work
+//   of some function
+//      memPtr          - pointer to pointer to the large block of memory
+//      verticesPtr     - pointer to pointer to block of memory for
+//                        temporary storing vertices
+//      width           - width of line in pixels
+void allocTempMem( int** memPtr,
+                   int** verticesPtr,
+                   int width )
+{
+    int* tempPtr = ( int* ) malloc( ( width + 2 ) * 7 * sizeof( int ) );
+    *verticesPtr = tempPtr;
+    *memPtr = *verticesPtr + width + 2;
+}
+
+// function freeTempMem frees all allocated by allocTempMem function memory
+//      memPtr          - pointer to pointer to the large block of memory
+//      verticesPtr     - pointer to pointer to block of memory for
+//                        temporary storing vertices
+void freeTempMem( int** memPtr,
+                  int** verticesPtr )
+{
+    free( ( void* )( *verticesPtr ) );
+    *verticesPtr = NULL;
+    *memPtr = NULL;
+}
+
+// function makeGraph creates initial graph to find maximum flow in it
+//      graphPtr        - pointer to pointer to CvGraph structure to be filled
+//      leftLine        - pointer to the left image line
+//      rightLine       - pointer to the right image line
+//      alpha           - label number one for doing exchange
+//      beta            - label number two for doing exchange
+//      corr            - pointer to array of correspondences ( each element
+//                        of array includes disparity of pixel on right image
+//                        for pixel each on left image ). This pointer direct
+//                        to correspondence ofr one line only
+//      width           - width of image lines in pixels
+//      storage         - pointer to CvMemStorage structure which contains
+//                        memory storage
+void makeGraph( CvGraph** graphPtr,
+                unsigned char* leftLine,
+                unsigned char* rightLine,
+                int alpha,
+                int beta,
+                int* corr,
+                int width,
+                CvMemStorage* storage )
+{
+    int i;
+
+    if( *graphPtr )  {
+        cvClearGraph( *graphPtr );
+    }
+    /*else {*/
+        *graphPtr = cvCreateGraph( CV_SEQ_KIND_GRAPH | CV_GRAPH_FLAG_ORIENTED,
+                                   sizeof( CvGraph ),
+                                   getSizeForGraph( Vertex ),
+                                   getSizeForGraph( Edge ),
+                                   storage );
+    /*}*/
+
+    CvGraph* graph = *graphPtr;
+
+    #ifdef ALPHA_BETA_EXCHANGE
+
+    CvGraphVtx* newVtxPtr;
+    for( i = 0; i < width; i ++ )
+    {
+        if( corr[i] == alpha || corr[i] == beta ) {
+            cvGraphAddVtx( graph, NULL, &newVtxPtr );
+            ( ( Vertex* )newVtxPtr ) -> coord = i;
+        }
+    } /* for( i = 0; i < width; i ++ ) */
+    cvGraphAddVtx( graph, NULL, &newVtxPtr );
+    if( newVtxPtr )
+        ( ( Vertex* )newVtxPtr ) -> coord = -2; /* adding alpha vertex */
+    cvGraphAddVtx( graph, NULL, &newVtxPtr );
+    if( newVtxPtr )
+        ( ( Vertex* )newVtxPtr ) -> coord = -1; /* adding beta vertex */
+
+    int alphaVtx = graph -> total - 2;
+    int betaVtx = graph -> total - 1;
+    CvGraphEdge* newEdgePtr;
+    CvGraphVtx* vtxPtr;
+    if( graph -> total > 2 )
+    {
+        for( i = 0; i < alphaVtx; i ++ )
+        {
+            vtxPtr = cvGetGraphVtx( graph, i );
+
+            /* adding edge oriented from alpha vertex to current vertex */
+            cvGraphAddEdge( graph, alphaVtx, i, NULL, &newEdgePtr );
+            ( ( Edge* )newEdgePtr ) -> weight = dFunc( leftLine,
+                rightLine,
+                ( ( Vertex* )vtxPtr ) -> coord,
+                alpha,
+                width );
+            ( ( Edge* )newEdgePtr ) -> flow = 0;
+            if( i != 0 ) {
+                CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i - 1 );
+                /* if vertices are neighbours */
+                if( ( ( Vertex* )tempVtxPtr ) -> coord + 1 ==
+                    ( ( Vertex* )vtxPtr ) -> coord )
+                {
+                    ( ( Edge* )newEdgePtr ) -> weight +=
+                        vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
+                               alpha );
+                    /* adding neighbour edge oriented from current vertex
+                       to the previous one */
+                    CvGraphEdge* tempEdgePtr;
+                    cvGraphAddEdge( graph, i, i - 1, NULL, &tempEdgePtr );
+                    ( ( Edge* )tempEdgePtr ) -> weight = vFunc( alpha, beta );
+                    ( ( Edge* )tempEdgePtr ) -> flow = 0;
+                    ( ( Edge* )tempEdgePtr ) -> srcVtx =
+                        ( ( Vertex* )vtxPtr ) -> coord;
+                    ( ( Edge* )tempEdgePtr ) -> destVtx =
+                        ( ( Vertex* )tempVtxPtr ) -> coord;
+                }
+            } /* if( i != 0 ) */
+            if( i != alphaVtx - 1 ) {
+                CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i + 1 );
+                /* if vertices are neighbours */
+                if( ( ( Vertex* )tempVtxPtr ) -> coord - 1 ==
+                    ( ( Vertex* )vtxPtr ) -> coord )
+                {
+                    ( ( Edge* )newEdgePtr ) -> weight +=
+                        vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
+                               alpha );
+                    /* adding neighbour edge oriented from current vertex
+                       to the next one */
+                    CvGraphEdge* tempEdgePtr;
+                    cvGraphAddEdge( graph, i, i + 1, NULL, &tempEdgePtr );
+                    ( ( Edge* )tempEdgePtr ) -> weight = vFunc( alpha, beta );
+                    ( ( Edge* )tempEdgePtr ) -> flow = 0;
+                    ( ( Edge* )tempEdgePtr ) -> srcVtx =
+                        ( ( Vertex* )vtxPtr ) -> coord;
+                    ( ( Edge* )tempEdgePtr ) -> destVtx =
+                        ( ( Vertex* )tempVtxPtr ) -> coord;
+                }
+            } /* if( i != alphaVtx - 1 ) */
+            ( ( Edge* )newEdgePtr ) -> flow = 0;
+            ( ( Edge* )newEdgePtr ) -> srcVtx = -1; /* source vertex is alpha
+                                                       vertex */
+            ( ( Edge* )newEdgePtr ) -> destVtx = ( ( Vertex* )vtxPtr ) -> coord;
+
+            /* adding edge oriented from current vertex to beta vertex */
+            cvGraphAddEdge( graph, i, betaVtx, NULL, &newEdgePtr );
+            ( ( Edge* )newEdgePtr ) -> weight = dFunc( leftLine,
+                rightLine,
+                ( ( Vertex* )vtxPtr ) -> coord,
+                beta,
+                width );
+            ( ( Edge* )newEdgePtr ) -> flow = 0;
+            if( i != 0 ) {
+                CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i - 1 );
+                /* if vertices are neighbours */
+                if( ( ( Vertex* )tempVtxPtr ) -> coord + 1 ==
+                    ( ( Vertex* )vtxPtr ) -> coord )
+                {
+                    ( ( Edge* )newEdgePtr ) -> weight +=
+                        vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
+                               beta );
+                }
+            } /* if( i != 0 ) */
+            if( i != alphaVtx - 1 ) {
+                CvGraphVtx* tempVtxPtr = cvGetGraphVtx( graph, i + 1 );
+                /* if vertices are neighbours */
+                if( ( ( Vertex* )tempVtxPtr ) -> coord - 1 ==
+                    ( ( Vertex* )vtxPtr ) -> coord )
+                {
+                    ( ( Edge* )newEdgePtr ) -> weight +=
+                        vFunc( corr[ ( ( Vertex* )tempVtxPtr ) -> coord ],
+                               beta );
+                }
+            } /* if( i != alphaVtx - 1 ) */
+            ( ( Edge* )newEdgePtr ) -> flow = 0;
+            ( ( Edge* )newEdgePtr ) -> srcVtx =
+                ( ( Vertex* )vtxPtr ) -> coord;
+            ( ( Edge* )newEdgePtr ) -> destVtx = -2; /* destination vertex is
+                                                        beta vertex */
+
+        } /* for( i = 0; i < graph -> total - 2; i ++ ) */
+
+    } /* if( graph -> total > 2 ) */
+
+    #endif /* #ifdef ALPHA_BETA_EXCHANGE */
+
+    #ifdef ALPHA_EXPANSION
+    #endif /* #ifdef ALPHA_EXPANSION */
+
+} /* makeGraph */
+
+// function makeHelpGraph creates help graph using initial graph
+//      graph           - pointer to initial graph ( represented by CvGraph
+//                        structure )
+//      hlpGraphPtr     - pointer to pointer to new help graph
+//      storage         - pointer to CvStorage structure
+//      mem             - pointer to memory allocated by allocTempMem function
+//      vertices        - pointer to memory allocated by allocTempMem function
+//      verticesCountPtr- pointer to value containing number of vertices
+//                        in vertices array
+//      width           - width of image line in pixels
+int makeHelpGraph( CvGraph* graph,
+                   CvGraph** hlpGraphPtr,
+                   CvMemStorage* storage,
+                   int* mem,
+                   int* vertices,
+                   int* verticesCountPtr,
+                   int width )
+{
+    int u, v;
+    int* order = mem;
+    int* lengthArr = order + width + 2;
+    int s = graph -> total - 2; /* source vertex */
+    int t = graph -> total - 1; /* terminate vertex */
+    int orderFirst;
+    int orderCount;
+    int &verticesCount = *verticesCountPtr;
+    CvGraph* hlpGraph;
+
+    if( *hlpGraphPtr )  {
+        cvClearGraph( *hlpGraphPtr );
+    }
+    else {
+        *hlpGraphPtr = cvCreateGraph( CV_SEQ_KIND_GRAPH |
+                                          CV_GRAPH_FLAG_ORIENTED,
+                                      sizeof( CvGraph ),
+                                      getSizeForGraph( Vertex ),
+                                      getSizeForGraph( Edge ),
+                                      storage );
+    }
+
+    hlpGraph = *hlpGraphPtr;
+
+    /* initialization */
+    for( u = 0; u < graph -> total; u ++ )
+    {
+        lengthArr[ u ] = INT_INFINITY;
+        cvGraphAddVtx( hlpGraph, NULL, NULL );
+    } /* for( u = 0; u < graph -> total - 1; u ++ ) */
+
+    orderFirst = 0;
+    orderCount = 0;
+    verticesCount = 0;
+    lengthArr[ s ] = 0;
+
+    /* add vertex s to order */
+    order[ orderCount ] = s;
+    orderCount ++;
+
+    while( orderCount != orderFirst )
+    {
+        /* getting u from order */
+        u = order[ orderFirst ];
+        orderFirst ++;
+
+        /* adding u to vertex array */
+        vertices[ verticesCount ] = u;
+        verticesCount ++;
+
+        int ofs;
+        CvGraphVtx* graphVtx = cvGetGraphVtx( graph, u );
+
+        /* processing all vertices outgoing from vertex u */
+        CvGraphEdge* graphEdge = graphVtx -> first;
+        while( graphEdge )
+        {
+            int tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[1] );
+            ofs = tempVtxIdx == u;
+            if( !ofs )
+            {
+                v = tempVtxIdx;
+
+                CvGraphEdge* tempGraphEdge = cvFindGraphEdge( graph, u, v );
+                if( ( lengthArr[ u ] < lengthArr[ v ] )
+                    && ( lengthArr[ v ] <= lengthArr[ t ] )
+                    && ( ( ( Edge* )tempGraphEdge ) -> flow <
+                        ( ( Edge* )tempGraphEdge ) -> weight ) )
+                {
+                    if( lengthArr[ v ] == INT_INFINITY )
+                    {
+                        /* adding vertex v to order */
+                        order[ orderCount ] = v;
+                        orderCount ++;
+
+                        lengthArr[ v ] = lengthArr[ u ] + 1;
+                        CvGraphEdge* tempGraphEdge2;
+
+                        cvGraphAddEdge( hlpGraph, u, v, NULL, &tempGraphEdge2 );
+                        ( ( Edge* )tempGraphEdge2 ) -> flow = 0;
+
+                        ( ( Edge* )tempGraphEdge2 ) -> weight =
+                            ( ( Edge* )tempGraphEdge ) -> weight -
+                            ( ( Edge* )tempGraphEdge ) -> flow;
+
+                    } /* if( length[ v ] == INT_INFINITY ) */
+
+                } /* if( ( lengthArr[ u ] < lengthArr[ v ] ) ... */
+
+            } /* if( !ofs ) */
+
+            graphEdge = graphEdge -> next[ ofs ];
+
+        } /* while( graphEdge ) */
+
+        /* processing all vertices incoming to vertex u */
+        graphEdge = graphVtx -> first;
+        while( graphEdge )
+        {
+            int tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[1] );
+            ofs = tempVtxIdx == u;
+            if( ofs )
+            {
+                tempVtxIdx = cvGraphVtxIdx( graph, graphEdge -> vtx[0] );
+                v = tempVtxIdx;
+
+                CvGraphEdge* tempGraphEdge = cvFindGraphEdge( graph, v, u );
+                if( ( lengthArr[ u ] < lengthArr[ v ] )
+                    && ( lengthArr[ v ] <= lengthArr[ t ] )
+                    && ( ( ( Edge* )tempGraphEdge ) -> flow > 0 ) )
+                {
+                    if( lengthArr[ v ] == INT_INFINITY )
+                    {
+                        /* adding vertex v to order */
+                        order[ orderCount ] = v;
+                        orderCount ++;
+
+                        lengthArr[ v ] = lengthArr[ u ] + 1;
+                        CvGraphEdge* tempGraphEdge3 = cvFindGraphEdge( hlpGraph, u, v );
+
+                        if( tempGraphEdge3 == NULL ||
+                            ( ( Edge* )tempGraphEdge3 ) -> weight == 0 )
+                        {
+                            CvGraphEdge* tempGraphEdge2;
+                            cvGraphAddEdge( hlpGraph, u, v, NULL,
+                                &tempGraphEdge2 );
+                            ( ( Edge* )tempGraphEdge2 ) -> flow = 0;
+                            ( ( Edge* )tempGraphEdge2 ) -> weight = 0;
+                        } /* if( tempGraphEdge3 == NULL || ... */
+
+                        ( ( Edge* )tempGraphEdge3 ) -> weight +=
+                            ( ( Edge* )tempGraphEdge ) -> flow;
+
+                    } /* if( length[ v ] == INT_INFINITY ) */
+
+                } /* if( ( lengthArr[ u ] < lengthArr[ v ] ) ... */
+
+            } /* if( ofs ) */
+
+            graphEdge = graphEdge -> next[ ofs ];
+
+        } /* while( graphEdge ) */
+  
+    } /* while( orderCount != orderFirst ) */
+
+    int i;
+    for( i = 0; i < hlpGraph -> total - 2; i ++ )
+    {
+        CvGraphVtx* hlpGraphVtxTemp = cvGetGraphVtx( hlpGraph, i );
+        if( hlpGraphVtxTemp ) {
+            if( !hlpGraphVtxTemp -> first ) {
+                cvGraphRemoveVtxByPtr( hlpGraph, hlpGraphVtxTemp );
+            }
+        }
+    } /* for( i = 0; i < hlpGraph -> total - 2; i ++ ) */
+
+    return lengthArr[ t ];
+
+} /* makeHelpGraph */
+
+// function makePseudoMaxFlow increases flow in graph by using hlpGraph
+//      graph           - pointer to initial graph
+//      hlpGraph        - pointer to help graph
+//      vertices        - pointer to vertices array
+//      verticesCount   - number of vertices in vertices array
+//      mem             - pointer to memory allocated by allocTempMem function
+//      width           - width of image line in pixels
+void makePseudoMaxFlow( CvGraph* graph,
+                        CvGraph* hlpGraph,
+                        int* vertices,
+                        int verticesCount,
+                        int* mem,
+                        int width )
+{
+    int stekCount;
+    int orderFirst;
+    int orderCount;
+    int i;
+    int v, u;
+    int* stek = mem;
+    int* order = stek + width + 2;
+    int* incomFlow = order + width + 2;
+    int* outgoFlow = incomFlow + width + 2;
+    int* flow = outgoFlow + width + 2;
+    int* cargo = flow+ width + 2;
+    int s = graph -> total - 2; /* source vertex */
+    int t = graph -> total - 1; /* terminate vertex */
+    int realVerticesCount = verticesCount;
+
+    stekCount = 0;
+
+    for( i = 0; i < verticesCount; i ++ )
+    {
+        v = vertices[ i ];
+
+        incomFlow[ v ] = outgoFlow[ v ] = 0;
+
+        if( v == s ) {
+            incomFlow[ v ] = INT_INFINITY;
+        } /* if( v == s ) */
+        else {
+            CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
+            CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
+            int ofs;
+
+            while( hlpGraphEdge )
+            {
+                int vtxIdx = cvGraphVtxIdx( hlpGraph,
+                    hlpGraphEdge -> vtx[1] );
+                ofs = vtxIdx == v;
+
+                if( ofs )
+                {
+                    incomFlow[ v ] += ( ( Edge* )hlpGraphEdge ) -> weight;
+                } /* if( ofs ) */
+
+                hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
+            } /* while( hlpGraphEdge ) */
+
+        } /* if( v == s ) else */
+
+        if( v == t ) {
+            outgoFlow[ v ] = INT_INFINITY;
+        } /* if( v == t ) */
+        else {
+            CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
+            CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
+            int ofs;
+
+            while( hlpGraphEdge )
+            {
+                int vtxIdx = cvGraphVtxIdx( hlpGraph,
+                    hlpGraphEdge -> vtx[1] );
+                ofs = vtxIdx == v;
+
+                if( !ofs )
+                {
+                    outgoFlow[ v ] += ( ( Edge* )hlpGraphEdge ) -> weight;
+                } /* if( ofs ) */
+
+                hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
+            } /* while( hlpGraphEdge ) */
+
+        } /* if( v == t ) else */
+
+        flow[ v ] = CV_MIN2( incomFlow[ v ], outgoFlow[ v ] );
+
+        if( !flow[ v ] ) {
+            stek[ stekCount ] = v;
+            stekCount ++;
+        } /* if( !flow[ v ] ) */
+
+    } /* for( i = 0; i < verticesCount; i ++ ) */
+
+    for( i = 0; i < verticesCount; i ++ )
+    {
+        v = vertices[ i ];
+        cargo[ v ] = 0;
+    } /* for( i = 0; i < verticesCount; i ++ ) */
+
+    while( realVerticesCount > 2 )
+    {
+        /* deleting all vertices included in stek */
+        while( stekCount )
+        {
+            v = stek[ stekCount - 1 ];
+            stekCount --;
+
+            /* deleting edges incoming to v and outgoing from v */
+            int ofs;
+            CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
+            CvGraphEdge* hlpGraphEdge;
+            if( hlpGraphVtx ) {
+                hlpGraphEdge = hlpGraphVtx -> first;
+            }
+            else {
+                hlpGraphEdge = NULL;
+            }
+            while( hlpGraphEdge )
+            {
+                CvGraphVtx* hlpGraphVtx2 = hlpGraphEdge -> vtx[ 1 ];
+                int hlpGraphVtxIdx2 = cvGraphVtxIdx( hlpGraph,
+                    hlpGraphVtx2 );
+                ofs = hlpGraphVtxIdx2 == v;
+
+                if( ofs )
+                {
+                    /* hlpGraphEdge is incoming edge */
+                    CvGraphVtx* hlpGraphVtx3 = hlpGraphEdge -> vtx[0];
+                    u = cvGraphVtxIdx( hlpGraph,
+                                       hlpGraphVtx3 );
+                    outgoFlow[ u ] -= ( ( Edge* )hlpGraphEdge ) -> weight
+                        - ( ( Edge* )hlpGraphEdge ) -> flow;
+                    cvGraphRemoveEdgeByPtr( hlpGraph,
+                                            hlpGraphVtx3,
+                                            hlpGraphVtx2 );
+                    if( flow[ u ] != 0 ) {
+                        flow[ u ] = CV_MIN2( incomFlow[u], outgoFlow[u] );
+                        if( flow[ u ] == 0 ) {
+                            stek[ stekCount ] = u;
+                            stekCount ++;
+                        }
+                    }
+                } /* if( ofs ) */
+                else
+                {
+                    /* hlpGraphEdge is outgoing edge */
+                    CvGraphVtx* hlpGraphVtx3 = hlpGraphEdge -> vtx[1];
+                    int u = cvGraphVtxIdx( hlpGraph,
+                                              hlpGraphVtx3 );
+                    incomFlow[ u ] -= ( ( Edge* )hlpGraphEdge ) -> weight
+                        - ( ( Edge* )hlpGraphEdge ) -> flow;
+                    cvGraphRemoveEdgeByPtr( hlpGraph,
+                                            hlpGraphVtx2,
+                                            hlpGraphVtx3 );
+                    if( flow[ u ] != 0 ) {
+                        flow[ u ] = CV_MIN2( incomFlow[u], outgoFlow[u] );
+                        if( flow[ u ] == 0 ) {
+                            stek[ stekCount ] = u;
+                            stekCount ++;
+                        }
+                    }
+                } /* if( ofs ) else */
+
+                hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
+
+            } /* while( hlpGraphEdge ) */
+
+            /* deleting vertex v */
+            cvGraphRemoveVtx( hlpGraph, v );
+            realVerticesCount --;
+
+        } /* while( stekCount ) */
+
+        if( realVerticesCount > 2 ) /* the flow is not max still */
+        {
+            int p = INT_INFINITY;
+            int r = -1;
+            CvGraphVtx* graphVtx;
+
+            if( realVerticesCount == 3 ) {
+                r = r;
+            }
+            for( i = 0; i < hlpGraph -> total - 2; i ++ )
+            {
+                graphVtx = cvGetGraphVtx( hlpGraph, i );
+                if( graphVtx ) {
+                    v = cvGraphVtxIdx( hlpGraph, graphVtx );
+                    if( flow[ v ] < p ) {
+                        r = v;
+                        p = flow[ v ];
+                    }
+                }
+
+            } /* for( i = 0; i < hlpGraph -> total - 2; i ++ ) */
+
+            /* building of size p flow from r to t */
+            orderCount = orderFirst = 0;
+            order[ orderCount ] = r;
+            orderCount ++;
+
+            v = order[ orderFirst ];
+            orderFirst ++;
+
+            cargo[ r ] = p;
+            do /* while( v != t ) */
+            {
+                incomFlow[ v ] -= cargo[ v ];
+                outgoFlow[ v ] -= cargo[ v ];
+                flow[ v ] -= cargo[ v ];
+
+                if( flow[ v ] == 0 ) {
+                    stek[ stekCount ] = v;
+                    stekCount ++;
+                }
+
+                if( v == t ) {
+                    cargo[ v ] = p;
+                }
+                else
+                {
+                    int ofs;
+                    CvGraphVtx* hlpGraphVtx2;
+                    CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
+                    CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
+                    CvGraphEdge* hlpGraphEdge2 = NULL;
+
+                    while( hlpGraphEdge && cargo[ v ] > 0 )
+                    {
+                        hlpGraphVtx2 = hlpGraphEdge -> vtx[ 1 ];
+                        u = cvGraphVtxIdx( hlpGraph, hlpGraphVtx2 );
+                        ofs = u == v;
+
+                        if( !ofs )
+                        {
+                            if( cargo[ u ] == 0 ) {
+                                order[ orderCount ] = u;
+                                orderCount ++;
+                            }
+                            int delta = ( ( Edge* )hlpGraphEdge ) -> weight
+                                - ( ( Edge* )hlpGraphEdge ) -> flow;
+                            delta = CV_MIN2( cargo[ v ], delta );
+                            ( ( Edge* )hlpGraphEdge ) -> flow += delta;
+                            cargo[ v ] -= delta;
+                            cargo[ u ] += delta;
+                            if( ( ( Edge* )hlpGraphEdge ) -> weight ==
+                                ( ( Edge* )hlpGraphEdge ) -> flow )
+                            {
+                                /* deleting hlpGraphEdge */
+                                hlpGraphEdge2 = hlpGraphEdge -> next[ ofs ];
+                                CvGraphEdge* graphEdge =
+                                    cvFindGraphEdge( graph, v, u );
+                                ( ( Edge* )graphEdge ) -> flow +=
+                                    ( ( Edge* )hlpGraphEdge ) -> flow;
+                                cvGraphRemoveEdgeByPtr( hlpGraph,
+                                    hlpGraphEdge -> vtx[0],
+                                    hlpGraphEdge -> vtx[1] );
+                            }
+                        } /* if( !ofs ) */
+
+                        if( hlpGraphEdge2 ) {
+                            hlpGraphEdge = hlpGraphEdge2;
+                            hlpGraphEdge2 = NULL;
+                        }
+                        else {
+                            hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
+                        }
+                    } /* while( hlpGraphEdge && cargo[ v ] > 0 ) */
+
+                } /* if( v == t ) else */
+
+                v = order[ orderFirst ];
+                orderFirst ++;
+
+            } while( v != t ); /* do */
+
+            /* building of size p flow from s to r */
+            orderCount = orderFirst = 0;
+            order[ orderCount ] = r;
+            orderCount ++;
+
+            v = order[ orderFirst ];
+            orderFirst ++;
+
+            cargo[ r ] = p;
+            do /* while( v != s ) */
+            {
+                if( v != r )
+                {
+                    incomFlow[ v ] -= cargo[ v ];
+                    outgoFlow[ v ] -= cargo[ v ];
+                    flow[ v ] -= cargo[ v ];
+                    if( flow[ v ] == 0 ) {
+                        stek[ stekCount ] = v;
+                        stekCount ++;
+                    }
+                } /* if( v != r ) */
+
+                if( v == s ) {
+                    cargo[ v ] = 0;
+                } /* if( v == s ) */
+                else
+                {
+                    int ofs;
+
+                    CvGraphVtx* hlpGraphVtx = cvGetGraphVtx( hlpGraph, v );
+                    CvGraphEdge* hlpGraphEdge = hlpGraphVtx -> first;
+                    CvGraphEdge* hlpGraphEdge2 = NULL;
+                    while( hlpGraphEdge && cargo[ v ] > 0 )
+                    {
+                        u = cvGraphVtxIdx( hlpGraph,
+                                hlpGraphEdge -> vtx[ 1 ] );
+                        ofs = u == v;
+
+                        if( ofs )
+                        {
+                            u = cvGraphVtxIdx( hlpGraph,
+                                    hlpGraphEdge -> vtx[ 0 ] );
+
+                            if( cargo[ u ] == 0 ) {
+                                order[ orderCount ] = u;
+                                orderCount ++;
+                            }
+
+                            int delta = ( ( Edge* )hlpGraphEdge ) -> weight
+                                - ( ( Edge* )hlpGraphEdge ) -> flow;
+
+                            delta = CV_MIN2( cargo[ v ], delta );
+                            
+                            (( ( Edge* )hlpGraphEdge ) -> flow) += delta;
+
+                            cargo[ v ] -= delta;
+                            cargo[ u ] += delta;
+
+                            if( ( ( Edge* )hlpGraphEdge ) -> weight ==
+                                ( ( Edge* )hlpGraphEdge ) -> flow )
+                            {
+                                hlpGraphEdge2 = hlpGraphEdge -> next[ ofs ];
+                                CvGraphEdge* graphEdge =
+                                    cvFindGraphEdge( graph, u, v );
+                                ( ( Edge* )graphEdge ) -> flow +=
+                                    ( ( Edge* )hlpGraphEdge ) -> flow;
+                                cvGraphRemoveEdgeByPtr( hlpGraph,
+                                    hlpGraphEdge -> vtx[0],
+                                    hlpGraphEdge -> vtx[1] );
+                            }
+                        } /* if( ofs ) */
+
+                        if( hlpGraphEdge2 ) {
+                            hlpGraphEdge = hlpGraphEdge2;
+                            hlpGraphEdge2 = NULL;
+                        }
+                        else {
+                            hlpGraphEdge = hlpGraphEdge -> next[ ofs ];
+                        }
+                    } /* while( hlpGraphEdge && cargo[ v ] > 0 ) */
+
+                } /* if( v == s ) else */
+
+                v = order[ orderFirst ]; //added
+                orderFirst ++; //added
+
+            } while( v != s ); /* do */
+
+        } /* if( hlpGraph -> total > 2 ) */
+
+    } /* while( hlpGraph -> total > 2 ) */
+
+} /* makePseudoMaxFlow */
+
+
+// function oneStep produces one alpha-beta exchange for one line of images
+//      leftLine        - pointer to the left image line
+//      rightLine       - pointer to the right image line
+//      alpha           - label number one
+//      beta            - label number two
+//      corr            - pointer to correspondence array for this line
+//      width           - width of image line in pixels
+//      mem             - pointer to memory allocated by allocTempMem function
+//      vertices        - pointer to vertices array allocated by allocTempMem
+//                        function
+//      storage         - pointer to CvMemStorage structure
+bool oneStep( unsigned char* leftLine,
+              unsigned char* rightLine,
+              int alpha,
+              int beta,
+              int* corr,
+              int width,
+              int* mem,
+              int* vertices,
+              CvMemStorage* storage )
+{
+    CvGraph* graph = NULL;
+    CvGraph* hlpGraph = NULL;
+    CvMemStoragePos storagePos;
+    int i;
+    bool change = false;
+    cvSaveMemStoragePos( storage, &storagePos );
+
+    int verticesCount;
+
+    makeGraph( &graph, leftLine, rightLine, alpha, beta, corr, width, storage );
+
+    int s = graph -> total - 2; /* source vertex - alpha vertex */
+    //int t = graph -> total - 1; /* terminate vertex - beta vertex */
+
+    int length = makeHelpGraph( graph,
+                                &hlpGraph,
+                                storage,
+                                mem,
+                                vertices,
+                                &verticesCount,
+                                width );
+    while( length != INT_INFINITY )
+    {
+        change = true;
+        makePseudoMaxFlow( graph,
+                           hlpGraph,
+                           vertices,
+                           verticesCount,
+                           mem,
+                           width );
+        cvClearGraph( hlpGraph );
+        length = makeHelpGraph( graph,
+                                &hlpGraph,
+                                storage,
+                                mem,
+                                vertices,
+                                &verticesCount,
+                                width );
+    } /* while( length != INT_INFINITY ) */
+
+    int coord;
+    CvGraphVtx* graphVtx;
+    for( i = 0; i < s; i ++ )
+    {
+        CvGraphEdge* graphEdge = cvFindGraphEdge( graph, s, i );
+
+        if( ( ( Edge* )graphEdge ) -> weight ==
+            ( ( Edge* )graphEdge ) -> flow )
+        { /* this vertex must have alpha label */
+            graphVtx = cvGetGraphVtx( graph, i );
+            coord = ( ( Vertex* )graphVtx )-> coord;
+            if( corr[ coord ] != alpha ) {
+                corr[ coord ] = alpha; //added
+                change = true;
+            }
+            else {
+                corr[ coord ] = alpha;
+            }
+        } /* if( ( ( Edge* )graphEdge ) -> weight == ... */
+        else
+        { /* this vertex must have beta label */
+            graphVtx = cvGetGraphVtx( graph, i );
+            coord = ( ( Vertex* )graphVtx )-> coord;
+            if( corr[ coord ] != beta ) {
+                corr[ coord ] = beta; //added
+                change = true;
+            }
+            else {
+                corr[ coord ] = beta;
+            }
+        } /* if( ( ( Edge* )graphEdge ) -> weight == ... else */
+
+    } /* for( i = 0; i < s; i ++ ) */
+
+    cvClearGraph( hlpGraph );
+    cvClearGraph( graph );
+
+    cvRestoreMemStoragePos( storage, &storagePos );
+
+    return change;
+
+} /* oneStep */
+
+// function initCorr fills correspondence array with initial values
+//      corr                - pointer to correspondence array for this line
+//      width               -  width of image line in pixels
+//      maxPixelDifference  - maximum value of difference between the same
+//                            point painted on two images
+void initCorr( int* corr, int width, int maxPixelDifference )
+{
+    int i;
+    int pixelDifferenceRange = maxPixelDifference * 2 + 1;
+
+    for( i = 0; i < width; i ++ )
+    {
+        corr[ i ] = i % pixelDifferenceRange - maxPixelDifference;
+    }
+} /* initCorr */
+
+// function oneLineCorr fully computes one line of images
+//      leftLine                - pointer to the left image line
+//      rightLine               - pointer to the right image line
+//      corr                    - pointer to the correspondence array for one
+//                                line
+//      mem                     - pointer to memory allocated by allocTempMem
+//                                function
+//      vertices                - pointer to memory allocated by allocTempMem
+//                                function
+//      width                   - width of image line in pixels
+//      maxPixelDifference      - maximum value of pixel differences in pixels
+//      storage                 - pointer to CvMemStorage struct which
+//                                contains memory storage
+void oneLineCorr( unsigned char* leftLine,
+                  unsigned char* rightLine,
+                  int* corr,
+                  int* mem,
+                  int* vertices,
+                  int width,
+                  int maxPixelDifference,
+                  CvMemStorage* storage )
+{
+    int result = 1;
+    int count = 0;
+    int i, j;
+
+    initCorr( corr, width, maxPixelDifference );
+    while( result )
+    {
+        result = 0;
+
+        for( i = - maxPixelDifference; i < maxPixelDifference; i ++ )
+        for( j = i + 1; j <= maxPixelDifference; j ++ )
+        {
+            result += (int)oneStep( leftLine,
+                               rightLine,
+                               i,
+                               j,
+                               corr,
+                               width,
+                               mem,
+                               vertices,
+                               storage );
+        } /* for( j = i + 1; j < width; j ++ ) */
+
+        count ++;
+        if( count > /*0*//*1*/2 ) {
+            break;
+        }
+
+    } /* while( result ) */
+
+} /* oneLineCorr */
+
+// function allLinesCorr computes all lines on the images
+//      leftImage           - pointer to the left image
+//      leftLineStep        - size of line on the left image in bytes
+//      rightImage          - pointer to the right image
+//      rightLineStep       - size of line on the right image in bytes
+//      width               - width of line in pixels
+//      height              - height of image in pixels
+//      corr                - pointer to correspondence array for all lines
+//      maxPixelDifference  - maximum value of difference between the same
+//                            point painted on two images
+//      storage             - pointer to CvMemStorage which contains memory
+//                            storage
+void allLinesCorr( unsigned char* leftImage,
+                   int leftLineStep,
+                   unsigned char* rightImage,
+                   int rightLineStep,
+                   int width,
+                   int height,
+                   int* corr,
+                   int maxPixelDifference,
+                   CvMemStorage* storage )
+{
+    int i;
+    unsigned char* leftLine = leftImage;
+    unsigned char* rightLine = rightImage;
+    int* mem;
+    int* vertices;
+
+    allocTempMem( &mem,
+                  &vertices,
+                  width );
+
+    for( i = 0; i < height; i ++ )
+    {
+        oneLineCorr( leftLine,
+                     rightLine,
+                     corr + i * width,
+                     mem,
+                     vertices,
+                     width,
+                     maxPixelDifference,
+                     storage );
+        leftLine += leftLineStep;
+        rightLine += rightLineStep;
+    } /* for( i = 0; i < height; i ++ ) */
+
+    freeTempMem( &mem,
+                 &vertices );
+
+} /* allLinesCorr */
+
+// This function produces morphing of two images into one image, which includes morphed
+// image or depth map
+//      _leftImage              - pointer to left image
+//      _leftLineStep           - size of line on left image in bytes
+//      _rightImage             - pointer to right image
+//      _rightLineStep          - size of line on right image in bytes
+//      _resultImage            - pointer to result morphed image
+//      _resultLineStep         - size of line on result image in bytes
+//      _corrArray              - pointer to array with correspondences
+//      _numCorrArray           - pointer to array with numbers correspondeces on each line
+//      width                   - width of images
+//      height                  - height of images
+//      alpha                   - position of virtual camera ( 0 corresponds to left image, 1 - to right one )
+//      imageNeed               - defines your wishes. if you want to see normal morphed image you have to set
+//                                this parameter to morphNormalImage ( this is default value ), else if you want
+//                                to see depth map you have to set this parameter to morphDepthMap and set the
+//                                next parameter ( maxPixelDifference ) to real value
+//      maxPixelDifference      - maximum value of pixel difference on two images
+void CCvGraphCutMorpher::Morph( unsigned char* _leftImage,
+            int _leftLineStep,
+            unsigned char* _rightImage,
+            int _rightLineStep,
+            unsigned char* _resultImage,
+            int _resultLineStep,
+            int* _corrArray,
+            int width,
+            int height,
+            float alpha,
+            morphImageType imageNeed,
+            int maxDifference
+          )
+{
+    unsigned char* leftArray    = _leftImage;
+    unsigned char* middleArray  = _resultImage;
+    unsigned char* rightArray   = _rightImage;
+    int leftLineSize            = _leftLineStep;
+    int middleLineSize          = _resultLineStep;
+    int rightLineSize           = _rightLineStep;
+
+    int lineNumber;
+    unsigned char* leftTemp;
+    unsigned char* middleTemp;
+    unsigned char* rightTemp;
+    int leftPixel;
+    int prevLeftPixel;
+    int middlePixel;
+    int prevMiddlePixel;
+    int rightPixel;
+    int prevRightPixel;
+    int leftPixel3;
+    int middlePixel3;
+    int rightPixel3;
+    int i;
+    int j;
+    int tempIndex;
+    int* result;
+    int number;
+    float alpha1        = 1.0f - alpha;
+    
+    for( lineNumber = 0; lineNumber < height; lineNumber ++ )
+    {
+        leftTemp    = leftArray + leftLineSize * lineNumber;
+        middleTemp  = middleArray + middleLineSize * lineNumber;
+        rightTemp   = rightArray + rightLineSize * lineNumber;
+        memset( ( void* )middleTemp, 0, middleLineSize );
+
+        result = _corrArray + width * lineNumber;
+        number = width;
+        
+        prevLeftPixel   = 0;
+        prevRightPixel  = prevLeftPixel + result[ 0 ];
+        if( prevRightPixel >= width ) {
+            prevRightPixel = width - 1;
+        }
+        else if ( prevRightPixel < 0 ) {
+            prevRightPixel = 0;
+        }
+        prevMiddlePixel =
+            (int)( prevLeftPixel * alpha1 + prevRightPixel * alpha );
+        for( i = 0; i < number - 1; i ++ )
+        {
+            leftPixel       = i;
+            rightPixel      = i + result[ i ];
+            if( rightPixel >= width ) {
+                rightPixel = width - 1;
+            }
+            else if( rightPixel < 0 ) {
+                rightPixel = 0;
+            }
+            middlePixel     =
+                (int)( leftPixel * alpha1 + rightPixel * alpha );
+            leftPixel3      = leftPixel * 3;
+            middlePixel3    = middlePixel * 3;
+            rightPixel3     = rightPixel * 3;
+            
+            if( imageNeed == morphDepthMap ) {
+                int t   = leftPixel - rightPixel + maxDifference;
+                t       = t < 0 ? -t : t;
+                t       = t * 255 / maxDifference / 2;
+                middleTemp[ middlePixel3 ]      = ( unsigned char )t;
+                middleTemp[ middlePixel3 + 1 ]  = ( unsigned char )t;
+                middleTemp[ middlePixel3 + 2 ]  = ( unsigned char )t;
+            } // if( imageNeed == morphDepthMap )
+            else
+            {
+                middleTemp[ middlePixel3 ] =
+                    (unsigned char)( leftTemp[ leftPixel3 ] * alpha1
+                    + rightTemp[ rightPixel3 ] * alpha );
+                middleTemp[ middlePixel3 + 1 ] =
+                    (unsigned char)( leftTemp[ leftPixel3 + 1 ] * alpha1
+                    + rightTemp[ rightPixel3 + 1 ] * alpha );
+                middleTemp[ middlePixel3 + 2 ] =
+                    (unsigned char)( leftTemp[ leftPixel3 + 2 ] * alpha1
+                    + rightTemp[ rightPixel3 + 2 ] * alpha );
+
+                if( middlePixel - prevMiddlePixel > 1 ) // occlusion
+                {
+                    if( leftPixel - prevLeftPixel > 1 )
+                    {
+                        int LenSrc  = leftPixel - prevLeftPixel - 2;
+                        int LenDest = middlePixel - prevMiddlePixel - 1;
+                        for( j = prevMiddlePixel + 1; j < middlePixel; j ++ )
+                        {
+                            tempIndex   = prevLeftPixel + 1 + LenSrc *
+                                ( j - prevMiddlePixel - 1 ) / LenDest;
+                            middleTemp[ j * 3 ]     =
+                                leftTemp[ tempIndex * 3 ];
+                            middleTemp[ j * 3 + 1 ] =
+                                leftTemp[ tempIndex * 3 + 1 ];
+                            middleTemp[ j * 3 + 2 ] =
+                                leftTemp[ tempIndex * 3 + 2 ];
+                        }
+                    } // if( leftPixel - prevLeftPixel > 1 )
+                    else
+                    {
+                        int LenSrc  = rightPixel - prevRightPixel - 2;
+                        int LenDest = middlePixel - prevMiddlePixel - 1;
+                        for( j = prevMiddlePixel + 1; j < middlePixel; j ++ )
+                        {
+                            tempIndex   = prevRightPixel + 1 + LenSrc *
+                                ( j - prevMiddlePixel - 1 ) / LenDest;
+                            middleTemp[ j * 3 ]     =
+                                rightTemp[ tempIndex * 3 ];
+                            middleTemp[ j * 3 + 1 ] =
+                                rightTemp[ tempIndex * 3 + 1 ];
+                            middleTemp[ j * 3 + 2 ] =
+                                rightTemp[ tempIndex * 3 + 2 ];
+                        }
+                    } // if( leftPixel - prevLeftPixel > 1 ) else
+                    
+                } // if( middlePixel - prevMiddlePixel > 1 )
+
+            } // if( imageNeed == morphDepthMap ) else
+
+            if( middlePixel > prevMiddlePixel ) {
+                if( leftPixel > prevLeftPixel )
+                    prevLeftPixel   = leftPixel;
+                if( rightPixel > prevRightPixel )
+                    prevRightPixel  = rightPixel;
+                prevMiddlePixel = middlePixel;
+            }
+        } // for( i = number - 1; i >= 0; i -- )
+        
+    } // for( lineNumber = 0; lineNumber < LeftImage -> m_Raster -> GetHeight() )
+
+} // Morph
+
+bool  CCvGraphCutMorpher::OnCalculateStereo()
+{
+    CvSize imageSizeLeft = GetImageSize( m_left_img ),
+           imageSizeRight = GetImageSize( m_right_img );
+
+    if( ( imageSizeLeft.width != imageSizeRight.width )
+        || ( imageSizeLeft.height != imageSizeRight.height ) )
+    {
+        return false;
+    }
+
+    if( m_corr ) {
+        free( m_corr );
+        m_corr = NULL;
+    }
+    m_corr = ( int* ) malloc( m_left_img -> width
+        * m_left_img -> height
+        * sizeof( int ) );
+
+    if( !m_storage ) {
+        m_storage = cvCreateMemStorage( 0 );
+        m_isStorageAllocated = true;
+    }
+    // Find correspondence for full image and store it to corr array
+    allLinesCorr( ( unsigned char* )m_left_img -> imageData,
+                  m_left_img -> widthStep,
+                  ( unsigned char* )m_right_img -> imageData,
+                  m_right_img -> widthStep,
+                  m_left_img -> width,
+                  m_left_img -> height,
+                  m_corr,
+                  m_maxPixelDifference,
+                  m_storage );
+
+    m_isStereoReady = true;
+
+    return true;
+}
+
+bool  CCvGraphCutMorpher::OnCalculateVirtualImage()
+{
+    // Output image to ResultImage window
+    Morph( ( unsigned char* )m_left_img -> imageData,
+           m_left_img ->widthStep,
+           ( unsigned char* )m_right_img -> imageData,
+           m_right_img -> widthStep,
+           ( unsigned char* )m_virtual_img -> imageData,
+           m_virtual_img -> widthStep,
+           m_corr,
+           m_left_img -> width,
+           m_left_img -> height,
+           m_pan );
+
+    m_isVirtualImageReady = true;
+
+    return true;
+}
+
+bool  CCvGraphCutMorpher::OnCalculateDisparity()
+{
+    Morph( ( unsigned char* )m_left_img -> imageData,
+           m_left_img ->widthStep,
+           ( unsigned char* )m_right_img -> imageData,
+           m_right_img -> widthStep,
+           ( unsigned char* )m_disparity_img -> imageData,
+           m_disparity_img -> widthStep,
+           m_corr,
+           m_left_img -> width,
+           m_left_img -> height,
+           m_pan,
+           morphDepthMap,
+           m_maxPixelDifference );
+
+    return true;
+}
+
+bool  CCvGraphCutMorpher::OnCalculateDisparityImage()
+{
+    Morph( ( unsigned char* )m_left_img -> imageData,
+           m_left_img ->widthStep,
+           ( unsigned char* )m_right_img -> imageData,
+           m_right_img -> widthStep,
+           ( unsigned char* )m_disparity_img -> imageData,
+           m_disparity_img -> widthStep,
+           m_corr,
+           m_left_img -> width,
+           m_left_img -> height,
+           m_pan,
+           morphDepthMap,
+           m_maxPixelDifference );
+
+    return true;
+}
+
+CCvGraphCutMorpher::CCvGraphCutMorpher()
+{
+    m_maxPixelDifference = MAX_DIFFERENCE;
+    m_corr = 0;
+    m_isStereoReady = false;
+    m_isVirtualImageReady = false;
+    m_isDisparityReady = false;
+    m_storage = NULL;
+    m_isStorageAllocated = false;
+}
+
+#endif
+
+/* End of file */