diff options
Diffstat (limited to 'cvaux/src/enmin.cpp')
-rw-r--r-- | cvaux/src/enmin.cpp | 1381 |
1 files changed, 1381 insertions, 0 deletions
diff --git a/cvaux/src/enmin.cpp b/cvaux/src/enmin.cpp new file mode 100644 index 0000000..e083380 --- /dev/null +++ b/cvaux/src/enmin.cpp @@ -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 */ |