📄 kdtree.c
字号:
for( i = 0; i < n; i++ ) tmp[i] = features[i].descr[ki]; kv = median_select( tmp, n ); free( tmp ); kd_node->ki = ki; kd_node->kv = kv;}/* Finds the median value of an array. The array's elements are re-ordered by this function. @param array an array; the order of its elelemts is reordered @param n number of elements in array @return Returns the median value of array.*/double median_select( double* array, int n ){ return rank_select( array, n, (n - 1) / 2 );}/* Finds the element of a specified rank in an array using the linear time median-of-medians algorithm by Blum, Floyd, Pratt, Rivest, and Tarjan. The elements of the array are re-ordered by this function. @param array an array; the order of its elelemts is reordered @param n number of elements in array @param r the zero-based rank of the element to be selected @return Returns the element from array with zero-based rank r.*/double rank_select( double* array, int n, int r ){ double* tmp, med; int gr_5, gr_tot, rem_elts, i, j; /* base case */ if( n == 1 ) return array[0]; /* divide array into groups of 5 and sort them */ gr_5 = n / 5; gr_tot = cvCeil( n / 5.0 ); rem_elts = n % 5; tmp = array; for( i = 0; i < gr_5; i++ ) { insertion_sort( tmp, 5 ); tmp += 5; } insertion_sort( tmp, rem_elts ); /* recursively find the median of the medians of the groups of 5 */ tmp = calloc( gr_tot, sizeof( double ) ); for( i = 0, j = 2; i < gr_5; i++, j += 5 ) tmp[i] = array[j]; if( rem_elts ) tmp[i++] = array[n - 1 - rem_elts/2]; med = rank_select( tmp, i, ( i - 1 ) / 2 ); free( tmp ); /* partition around median of medians and recursively select if necessary */ j = partition_array( array, n, med ); if( r == j ) return med; else if( r < j ) return rank_select( array, j, r ); else { array += j+1; return rank_select( array, ( n - j - 1 ), ( r - j - 1 ) ); }}/* Sorts an array in place into increasing order using insertion sort. @param array an array @param n number of elements*/void insertion_sort( double* array, int n ){ double k; int i, j; for( i = 1; i < n; i++ ) { k = array[i]; j = i-1; while( j >= 0 && array[j] > k ) { array[j+1] = array[j]; j -= 1; } array[j+1] = k; }}/* Partitions an array around a specified value. @param array an array @param n number of elements @param pivot value around which to partition @return Returns index of the pivot after partitioning*/int partition_array( double* array, int n, double pivot ){ double tmp; int p, i, j; i = -1; for( j = 0; j < n; j++ ) if( array[j] <= pivot ) { tmp = array[++i]; array[i] = array[j]; array[j] = tmp; if( array[i] == pivot ) p = i; } array[p] = array[i]; array[i] = pivot; return i;}/* Partitions the features at a specified kd tree node to create its two children. @param kd_node a kd tree node whose partition key is set*/void partition_features( struct kd_node* kd_node ){ struct feature* features, tmp; double kv; int n, ki, p, i, j = -1; features = kd_node->features; n = kd_node->n; ki = kd_node->ki; kv = kd_node->kv; for( i = 0; i < n; i++ ) if( features[i].descr[ki] <= kv ) { tmp = features[++j]; features[j] = features[i]; features[i] = tmp; if( features[j].descr[ki] == kv ) p = j; } tmp = features[p]; features[p] = features[j]; features[j] = tmp; /* if all records fall on same side of partition, make node a leaf */ if( j == n - 1 ) { kd_node->leaf = 1; return; } kd_node->kd_left = kd_node_init( features, j + 1 ); kd_node->kd_right = kd_node_init( features + ( j + 1 ), ( n - j - 1 ) );}/* Explores a kd tree from a given node to a leaf. Branching decisions are made at each node based on the descriptor of a given feature. Each node examined but not explored is put into a priority queue to be explored later, keyed based on the distance from its partition key value to the given feature's desctiptor. @param kd_node root of the subtree to be explored @param feat feature upon which branching decisions are based @param min_pq a minimizing priority queue into which tree nodes are placed as described above @return Returns a pointer to the leaf node at which exploration ends or NULL on error.*/struct kd_node* explore_to_leaf( struct kd_node* kd_node, struct feature* feat, struct min_pq* min_pq ){ struct kd_node* unexpl, * expl = kd_node; double kv; int ki; while( expl && ! expl->leaf ) { ki = expl->ki; kv = expl->kv; if( ki >= feat->d ) { fprintf( stderr, "Warning: comparing imcompatible descriptors, %s" \ " line %d\n", __FILE__, __LINE__ ); return NULL; } if( feat->descr[ki] <= kv ) { unexpl = expl->kd_right; expl = expl->kd_left; } else { unexpl = expl->kd_left; expl = expl->kd_right; } if( minpq_insert( min_pq, unexpl, ABS( kv - feat->descr[ki] ) ) ) { fprintf( stderr, "Warning: unable to insert into PQ, %s, line %d\n", __FILE__, __LINE__ ); return NULL; } } return expl;}/* Inserts a feature into the nearest-neighbor array so that the array remains in order of increasing descriptor distance from the search feature. @param feat feature to be inderted into the array; it's feature_data field should be a pointer to a bbf_data with d equal to the squared descriptor distance between feat and the search feature @param nbrs array of nearest neighbors neighbors @param n number of elements already in nbrs and @param k maximum number of elements in nbrs @return If feat was successfully inserted into nbrs, returns 1; otherwise returns 0.*/int insert_into_nbr_array( struct feature* feat, struct feature** nbrs, int n, int k ){ struct bbf_data* fdata, * ndata; double dn, df; int i, ret = 0; if( n == 0 ) { nbrs[0] = feat; return 1; } /* check at end of array */ fdata = (struct bbf_data*)feat->feature_data; df = fdata->d; ndata = (struct bbf_data*)nbrs[n-1]->feature_data; dn = ndata->d; if( df >= dn ) { if( n == k ) { feat->feature_data = fdata->old_data; free( fdata ); return 0; } nbrs[n] = feat; return 1; } /* find the right place in the array */ if( n < k ) { nbrs[n] = nbrs[n-1]; ret = 1; } else { nbrs[n-1]->feature_data = ndata->old_data; free( ndata ); } i = n-2; while( i >= 0 ) { ndata = (struct bbf_data*)nbrs[i]->feature_data; dn = ndata->d; if( dn <= df ) break; nbrs[i+1] = nbrs[i]; i--; } i++; nbrs[i] = feat; return ret;}/* Determines whether a given point lies within a specified rectangular region @param pt point @param rect rectangular region @return Returns 1 if pt is inside rect or 0 otherwise*/int within_rect( CvPoint2D64f pt, CvRect rect ){ if( pt.x < rect.x || pt.y < rect.y ) return 0; if( pt.x > rect.x + rect.width || pt.y > rect.y + rect.height ) return 0; return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -