|
|
|
/*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 "precomp.hpp"
|
|
|
|
|
|
|
|
#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 */
|