1. 程式人生 > >k-d tree的優化查詢演算法BBF

k-d tree的優化查詢演算法BBF

/*
Finds an image feature's approximate k nearest neighbors in a kd tree using
Best Bin First search.

@param kd_root root of an image feature kd tree
@param feat image feature for whose neighbors to search
@param k number of neighbors to find
@param nbrs pointer to an array in which to store pointers to neighbors
in order of increasing descriptor distance
@param max_nn_chks search is cut off after examining this many tree entries

@return Returns the number of neighbors found and stored in nbrs, or
-1 on error.
*/
//引數和返回值參看以上註釋
//基於k-d tree + bbf的k近鄰查詢函式
int kdtree_bbf_knn( struct kd_node* kd_root, struct feature* feat, int k,
struct feature*** nbrs, int max_nn_chks )
{
struct kd_node* expl;      //expl是特徵k-d tree中的一個節點
struct min_pq* min_pq; //min_pq是優先順序佇列
struct feature* tree_feat, ** _nbrs;//tree_feat是一個SIFT特徵,_nbrs中存放著查找出來的近鄰特徵節點
struct bbf_data* bbf_data;   //bbf_data是一個用來存放臨時特徵資料和特徵間距離的快取結構
int i, t = 0, n = 0;       //t是執行時限,n是查找出來的近鄰個數
if( ! nbrs || ! feat || ! kd_root )
{
fprintf( stderr, "Warning: NULL pointer error, %s, line %d\n",
__FILE__, __LINE__ );
return -1;
}

_nbrs = calloc( k, sizeof
( struct feature* ) );  //給查詢結果分配相應大小的記憶體
min_pq = minpq_init();                 //min_pq佇列初始化
minpq_insert( min_pq, kd_root, 0 );         //將根節點先插入到min_pq優先順序佇列中
while( min_pq->n > 0 && t < max_nn_chks ) //min_pq佇列沒有回溯完且未達到時限
{
expl = (struct kd_node*)minpq_extract_min( min_pq );//從min_pq中提取優先順序最高的節點(並移除)
if( ! expl )
{
fprintf( stderr, "Warning: PQ unexpectedly empty, %s line %d\n",
__FILE__, __LINE__ );
goto fail;
}

expl = explore_to_leaf( expl, feat, min_pq );    //從expl節點開始查詢到葉子節點(下詳) 
if( ! expl )
{
fprintf( stderr, "Warning: PQ unexpectedly empty, %s line %d\n",
__FILE__, __LINE__ );
goto fail;
}

for( i = 0; i < expl->n; i++ )  //開始比較查詢最近鄰
{
tree_feat = &expl->features[i];
bbf_data = malloc( sizeof( struct bbf_data ) );
if( ! bbf_data )
{
fprintf( stderr, "Warning: unable to allocate memory,"
" %s line %d\n", __FILE__, __LINE__ );
goto fail;
}
bbf_data->old_data = tree_feat->feature_data;
bbf_data->d = descr_dist_sq(feat, tree_feat);  //計算葉子節點特徵和目標特徵的距離
tree_feat->feature_data = bbf_data;
n += insert_into_nbr_array( tree_feat, _nbrs, n, k );//判斷並插入符合條件的近鄰到_nbrs中
}
t++;
}
   //釋放記憶體並返回結果
minpq_release( &min_pq );
for( i = 0; i < n; i++ )
{
bbf_data = _nbrs[i]->feature_data;
_nbrs[i]->feature_data = bbf_data->old_data;
free( bbf_data );
}
*nbrs = _nbrs;
return n;

fail:
minpq_release( &min_pq );
for( i = 0; i < n; i++ )
{
bbf_data = _nbrs[i]->feature_data;
_nbrs[i]->feature_data = bbf_data->old_data;
free( bbf_data );
}
free( _nbrs );
*nbrs = NULL;
return -1;
}