Commit 2388fa22 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

patched spilltree for better compatibility with multi-threaded apps (thanks to Kevin Keraudren)

parent e12b63dd
...@@ -57,10 +57,9 @@ struct CvSpillTreeNode ...@@ -57,10 +57,9 @@ struct CvSpillTreeNode
}; };
struct CvSpillTree struct CvSpillTree
{ {
CvSpillTreeNode* root; CvSpillTreeNode* root;
CvMat** refmat; // leaf ref matrix CvMat** refmat; // leaf ref matrix
bool* cache; // visited or not
int total; // total leaves int total; // total leaves
int naive; // under this value, we perform naive search int naive; // under this value, we perform naive search
int type; // mat type int type; // mat type
...@@ -68,6 +67,12 @@ struct CvSpillTree ...@@ -68,6 +67,12 @@ struct CvSpillTree
double tau; // the overlapping buffer ratio double tau; // the overlapping buffer ratio
}; };
struct CvResult
{
int index;
double distance;
};
// find the farthest node in the "list" from "node" // find the farthest node in the "list" from "node"
static inline CvSpillTreeNode* static inline CvSpillTreeNode*
icvFarthestNode( CvSpillTreeNode* node, icvFarthestNode( CvSpillTreeNode* node,
...@@ -88,7 +93,7 @@ icvFarthestNode( CvSpillTreeNode* node, ...@@ -88,7 +93,7 @@ icvFarthestNode( CvSpillTreeNode* node,
} }
return result; return result;
} }
// clone a new tree node // clone a new tree node
static inline CvSpillTreeNode* static inline CvSpillTreeNode*
icvCloneSpillTreeNode( CvSpillTreeNode* node ) icvCloneSpillTreeNode( CvSpillTreeNode* node )
...@@ -261,7 +266,6 @@ icvCreateSpillTree( const CvMat* raw_data, ...@@ -261,7 +266,6 @@ icvCreateSpillTree( const CvMat* raw_data,
tr->root = (CvSpillTreeNode*)cvAlloc( sizeof(CvSpillTreeNode) ); tr->root = (CvSpillTreeNode*)cvAlloc( sizeof(CvSpillTreeNode) );
memset(tr->root, 0, sizeof(CvSpillTreeNode)); memset(tr->root, 0, sizeof(CvSpillTreeNode));
tr->refmat = (CvMat**)cvAlloc( sizeof(CvMat*)*n ); tr->refmat = (CvMat**)cvAlloc( sizeof(CvMat*)*n );
tr->cache = (bool*)cvAlloc( sizeof(bool)*n );
tr->total = n; tr->total = n;
tr->naive = naive; tr->naive = naive;
tr->rho = rho; tr->rho = rho;
...@@ -299,26 +303,26 @@ icvCreateSpillTree( const CvMat* raw_data, ...@@ -299,26 +303,26 @@ icvCreateSpillTree( const CvMat* raw_data,
} }
static void static void
icvSpillTreeNodeHeapify( CvSpillTreeNode** heap, icvSpillTreeNodeHeapify( CvResult * heap,
int i, int i,
const int k ) const int k )
{ {
if ( heap[i] == NULL ) if ( heap[i].index == -1 )
return; return;
int l, r, largest = i; int l, r, largest = i;
CvSpillTreeNode* inp; CvResult inp;
do { do {
i = largest; i = largest;
r = (i+1)<<1; r = (i+1)<<1;
l = r-1; l = r-1;
if (( l < k )&&( heap[l] == NULL )) if (( l < k )&&( heap[l].index == -1 ))
largest = l; largest = l;
else if (( r < k )&&( heap[r] == NULL )) else if (( r < k )&&( heap[r].index == -1 ))
largest = r; largest = r;
else { else {
if (( l < k )&&( heap[l]->mp > heap[i]->mp )) if (( l < k )&&( heap[l].distance > heap[i].distance ))
largest = l; largest = l;
if (( r < k )&&( heap[r]->mp > heap[largest]->mp )) if (( r < k )&&( heap[r].distance > heap[largest].distance ))
largest = r; largest = r;
} }
if ( largest != i ) if ( largest != i )
...@@ -329,15 +333,17 @@ icvSpillTreeNodeHeapify( CvSpillTreeNode** heap, ...@@ -329,15 +333,17 @@ icvSpillTreeNodeHeapify( CvSpillTreeNode** heap,
static void static void
icvSpillTreeDFSearch( CvSpillTree* tr, icvSpillTreeDFSearch( CvSpillTree* tr,
CvSpillTreeNode* node, CvSpillTreeNode* node,
CvSpillTreeNode** heap, CvResult* heap,
int* es, int* es,
const CvMat* desc, const CvMat* desc,
const int k, const int k,
const int emax ) const int emax,
bool * cache)
{ {
if ((emax > 0)&&( *es >= emax )) if ((emax > 0)&&( *es >= emax ))
return; return;
double dist, p=0; double dist, p=0;
double distance;
while ( node->spill ) while ( node->spill )
{ {
// defeatist search // defeatist search
...@@ -358,13 +364,16 @@ icvSpillTreeDFSearch( CvSpillTree* tr, ...@@ -358,13 +364,16 @@ icvSpillTreeDFSearch( CvSpillTree* tr,
CvSpillTreeNode* it = node->lc; CvSpillTreeNode* it = node->lc;
for ( int i = 0; i < node->cc; i++ ) for ( int i = 0; i < node->cc; i++ )
{ {
if ( !tr->cache[it->i] ) if ( !cache[it->i] )
{ {
it->mp = cvNorm( it->center, desc ); distance = cvNorm( it->center, desc );
tr->cache[it->i] = true; cache[it->i] = true;
if (( heap[0] == NULL)||( it->mp < heap[0]->mp )) if (( heap[0].index == -1)||( distance < heap[0].distance ))
{ {
heap[0] = it; CvResult current_result;
current_result.index = it->i;
current_result.distance = distance;
heap[0] = current_result;
icvSpillTreeNodeHeapify( heap, 0, k ); icvSpillTreeNodeHeapify( heap, 0, k );
(*es)++; (*es)++;
} }
...@@ -375,17 +384,17 @@ icvSpillTreeDFSearch( CvSpillTree* tr, ...@@ -375,17 +384,17 @@ icvSpillTreeDFSearch( CvSpillTree* tr,
} }
dist = cvNorm( node->center, desc ); dist = cvNorm( node->center, desc );
// impossible case, skip // impossible case, skip
if (( heap[0] != NULL )&&( dist-node->r > heap[0]->mp )) if (( heap[0].index != -1 )&&( dist-node->r > heap[0].distance ))
return; return;
p = cvDotProduct( node->u, desc ); p = cvDotProduct( node->u, desc );
// guided dfs // guided dfs
if ( p < node->mp ) if ( p < node->mp )
{ {
icvSpillTreeDFSearch( tr, node->lc, heap, es, desc, k, emax ); icvSpillTreeDFSearch( tr, node->lc, heap, es, desc, k, emax, cache );
icvSpillTreeDFSearch( tr, node->rc, heap, es, desc, k, emax ); icvSpillTreeDFSearch( tr, node->rc, heap, es, desc, k, emax, cache );
} else { } else {
icvSpillTreeDFSearch( tr, node->rc, heap, es, desc, k, emax ); icvSpillTreeDFSearch( tr, node->rc, heap, es, desc, k, emax, cache );
icvSpillTreeDFSearch( tr, node->lc, heap, es, desc, k, emax ); icvSpillTreeDFSearch( tr, node->lc, heap, es, desc, k, emax, cache );
} }
} }
...@@ -398,16 +407,21 @@ icvFindSpillTreeFeatures( CvSpillTree* tr, ...@@ -398,16 +407,21 @@ icvFindSpillTreeFeatures( CvSpillTree* tr,
const int emax ) const int emax )
{ {
assert( desc->type == tr->type ); assert( desc->type == tr->type );
CvSpillTreeNode** heap = (CvSpillTreeNode**)cvAlloc( k*sizeof(heap[0]) ); CvResult* heap = (CvResult*)cvAlloc( k*sizeof(heap[0]) );
bool* cache = (bool*)cvAlloc( sizeof(bool)*tr->total );
for ( int j = 0; j < desc->rows; j++ ) for ( int j = 0; j < desc->rows; j++ )
{ {
CvMat _desc = cvMat( 1, desc->cols, desc->type, _dispatch_mat_ptr(desc, j*desc->cols) ); CvMat _desc = cvMat( 1, desc->cols, desc->type, _dispatch_mat_ptr(desc, j*desc->cols) );
for ( int i = 0; i < k; i++ ) for ( int i = 0; i < k; i++ ) {
heap[i] = NULL; CvResult current;
memset( tr->cache, 0, sizeof(bool)*tr->total ); current.index=-1;
current.distance=-1;
heap[i] = current;
}
memset( cache, 0, sizeof(bool)*tr->total );
int es = 0; int es = 0;
icvSpillTreeDFSearch( tr, tr->root, heap, &es, &_desc, k, emax ); icvSpillTreeDFSearch( tr, tr->root, heap, &es, &_desc, k, emax, cache );
CvSpillTreeNode* inp; CvResult inp;
for ( int i = k-1; i > 0; i-- ) for ( int i = k-1; i > 0; i-- )
{ {
CV_SWAP( heap[i], heap[0], inp ); CV_SWAP( heap[i], heap[0], inp );
...@@ -416,14 +430,15 @@ icvFindSpillTreeFeatures( CvSpillTree* tr, ...@@ -416,14 +430,15 @@ icvFindSpillTreeFeatures( CvSpillTree* tr,
int* rs = results->data.i+j*results->cols; int* rs = results->data.i+j*results->cols;
double* dt = dist->data.db+j*dist->cols; double* dt = dist->data.db+j*dist->cols;
for ( int i = 0; i < k; i++, rs++, dt++ ) for ( int i = 0; i < k; i++, rs++, dt++ )
if ( heap[i] != NULL ) if ( heap[i].index != -1 )
{ {
*rs = heap[i]->i; *rs = heap[i].index;
*dt = heap[i]->mp; *dt = heap[i].distance;
} else } else
*rs = -1; *rs = -1;
} }
cvFree( &heap ); cvFree( &heap );
cvFree( &cache );
} }
static void static void
...@@ -453,7 +468,6 @@ icvReleaseSpillTree( CvSpillTree** tr ) ...@@ -453,7 +468,6 @@ icvReleaseSpillTree( CvSpillTree** tr )
for ( int i = 0; i < (*tr)->total; i++ ) for ( int i = 0; i < (*tr)->total; i++ )
cvReleaseMat( &((*tr)->refmat[i]) ); cvReleaseMat( &((*tr)->refmat[i]) );
cvFree( &((*tr)->refmat) ); cvFree( &((*tr)->refmat) );
cvFree( &((*tr)->cache) );
icvDFSReleaseSpillTreeNode( (*tr)->root ); icvDFSReleaseSpillTreeNode( (*tr)->root );
cvFree( tr ); cvFree( tr );
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment