void matching(struct sift_keypoints *k1, struct sift_keypoints *k2, struct sift_keypoints *out_k1, struct sift_keypoints *out_k2A, struct sift_keypoints *out_k2B, float thresh, int flag) { int n1 = k1->size; int n2 = k2->size; float* dist = xmalloc<float>(n1*n2); float* distA = xmalloc<float>(n1); float* distB = xmalloc<float>(n1); int* indexA = xmalloc<int>(n1); int* indexB = xmalloc<int>(n1); compute_keypoints_distance(dist, k1, k2); find_the_two_nearest_keys(dist, n1, n2, indexA, indexB, distA, distB); int j = 0; for(int i = 0; i < n1; i++){ float val; val = (flag == 1 ? distA[i]/distB[i] : distA[i]); if (val < thresh){ int iA = indexA[i]; int iB = indexB[i]; struct keypoint* k; k = sift_malloc_keypoint_from_model_and_copy(k1->list[i]); sift_add_keypoint_to_list(k, out_k1); k = sift_malloc_keypoint_from_model_and_copy(k2->list[iA]); sift_add_keypoint_to_list(k, out_k2A); k = sift_malloc_keypoint_from_model_and_copy(k2->list[iB]); sift_add_keypoint_to_list(k, out_k2B); j++; } } free(dist); free(indexA); free(indexB); free(distA); free(distB); }
/** @brief Dissize keys with edge response * * in @param keysIn : list of keypoints, the edge response is stored * * out @param keysAccepted : passing * out @param keysRejected : failing * * @param threshold on (hXX + hYY)*(hXX + hYY)/(hXX*hYY - hXY*hXY) * on the ratio of principal curvatures. * * */ static void keypoints_discard_on_edge(struct sift_keypoints *keysIn, struct sift_keypoints *keysAccept, float thresh) { for( int k = 0; k < keysIn->size; k++){ struct keypoint *key = keysIn->list[k]; bool isAccepted = ( ABS(key->edgeResp) <= thresh); if (isAccepted == true){ struct keypoint *copy = sift_malloc_keypoint_from_model_and_copy(key); sift_add_keypoint_to_list(copy, keysAccept); } } }
/** @brief Attribute a reference orientation to each keypoint of a list * * * in @param dx_scalespace, x component (up-bottom) * in @param dy_scalespace, y component (left-right) * * in @param keysIn list of keypoints (pointer) * * out @param keysOut list of oriented keypoints * * size(keysIn) <= size(keysOut) * * @param t : threshold over a local maxima to constitute a reference orientation * * @param lambda_ori : size parameter for the Gaussian window * * * */ static void keypoints_attribute_orientations(const struct sift_scalespace *sx, const struct sift_scalespace *sy, const struct sift_keypoints *keysIn, struct sift_keypoints *keysOut, int n_bins, float lambda_ori, float t) { for(int k=0;k<keysIn->size;k++){ // load keypoint coordinates struct keypoint* key = keysIn->list[k]; float x = key->x; float y = key->y; float sigma = key->sigma; int o = key->o; int s = key->s; // load scalespace gradient int w = sx->octaves[o]->w; int h = sx->octaves[o]->h; float delta = sx->octaves[o]->delta; const float* dx = &(sx->octaves[o]->imStack[s*w*h]); const float* dy = &(sy->octaves[o]->imStack[s*w*h]); //conversion to the octave's coordinates x /= delta; y /= delta; sigma /= delta; /** Accumulate gradient orientation histogram */ sift_accumulate_orientation_histogram(x, y, sigma, dx, dy, w, h, n_bins, lambda_ori, key->orihist); /** Extract principal orientation */ float* principal_orientations = xmalloc(n_bins*sizeof(float)); int n_prOri; n_prOri = sift_extract_principal_orientations(key->orihist, n_bins, t, principal_orientations); /*t = 0.8 threhsold for secondary orientation */ /** Updating keypoints and save in new list */ for(int n = 0; n < n_prOri; n++){ struct keypoint* copy = sift_malloc_keypoint_from_model_and_copy(key); copy->theta = principal_orientations[n]; sift_add_keypoint_to_list(copy, keysOut); } free(principal_orientations); } }
static void keypoints_discard_near_the_border(struct sift_keypoints *keysIn, struct sift_keypoints *keysAccept, int w, int h, float lambda) { for( int k = 0; k < keysIn->size; k++){ struct keypoint *key = keysIn->list[k]; float x = key->x; float y = key->y; float sigma = key->sigma; bool isAccepted = (x-lambda*sigma > 0.0 )&&( x + lambda*sigma < (float)h) && (y-lambda*sigma > 0.0 )&&( y + lambda*sigma < (float)w); if (isAccepted == true){ struct keypoint *copy = sift_malloc_keypoint_from_model_and_copy(key); sift_add_keypoint_to_list(copy, keysAccept); } } }
/** @brief Refine the position of candidate keypoints * * in @param dog : difference of Gaussian * in @param keys : list candidate keypoints (3d discrete extrema) * * out @param keysInterpol : list of interpolated keypoints. * out @param keysReject : list of removed keypoints. * * The interpolation model consists in a local 3d quadratic model of the DoG space. * * An interpolation is successful if the interpolated extremum lays inside the pixel area * * Iterative process * * */ static void keypoints_interpolate_position(struct sift_scalespace *d, struct sift_keypoints *keys, struct sift_keypoints *keysInterpol, int itermax) { int nMaxIntrp = itermax; /* Maximum number of consecutive unsuccessful interpolation */ float ofstMax = 0.6; // Ratio between two consecutive scales in the scalespace // assuming the ratio is constant over all scales and over all octaves float sigmaratio = d->octaves[0]->sigmas[1]/d->octaves[0]->sigmas[0]; for(int k = 0; k<keys->size; k++){ /* Loading keypoint and associated octave */ struct keypoint* key = keys->list[k]; int o = key->o; int s = key->s; int i = key->i; int j = key->j; struct octa* octave = d->octaves[o]; int w = octave->w; int h = octave->h; int ns = octave->nSca; // WARNING this includes the auxiliary scales. float delta = octave->delta; float* imStck = octave->imStack; float val = key->val; int ic=i; /* current value of i coordinate - at each interpolation */ int jc=j; int sc=s; int nIntrp = 0; bool isConv = false; float ofstX =0.; float ofstY =0.; float ofstS =0.; while( nIntrp < nMaxIntrp ){ /** Extrema interpolation via a quadratic function */ /* only if the detection is not too close to the border (so the discrete 3D Hessian is well defined) */ if((0 < ic)&&( ic < (h-1))&&(0 < jc)&&(jc < (w-1))){ inverse_3D_Taylor_second_order_expansion(imStck, w, h, ic, jc, sc, &ofstX, &ofstY, &ofstS, &val); }else{ isConv = false; ofstX = 5.0; ofstY = 5.0; ofstS = 5.0; } /** Test if the quadratic model is consistent */ if( (ABS(ofstX) < ofstMax) && (ABS(ofstY) < ofstMax) && (ABS(ofstS) < ofstMax) ){ isConv = true; break; }else{ // move to another point // space... if((ofstX > +ofstMax) && ((ic+1) < (h-1))) {ic +=1;} if((ofstX < -ofstMax) && ((ic-1) > 0 )) {ic -=1;} if((ofstY > +ofstMax) && ((jc+1) < (w-1))) {jc +=1;} if((ofstY < -ofstMax) && ((jc-1) > 0 )) {jc -=1;} // ... and scale. if((ofstS > +ofstMax) && ((sc+1) < (ns-1))) {sc +=1;} if((ofstS < -ofstMax) && ((sc-1) > 0 )) {sc -=1;} } nIntrp += 1; } if(isConv == true){ /** Create key and save in corresponding keypoint structure */ struct keypoint* keycp = sift_malloc_keypoint_from_model_and_copy(key); keycp->x = (ic+ofstX)*delta; keycp->y = (jc+ofstY)*delta; keycp->i = ic; keycp->j = jc; keycp->s = sc; keycp->sigma = octave->sigmas[sc]*pow(sigmaratio,ofstS); /* logarithmic scale */ keycp->val = val; sift_add_keypoint_to_list(keycp,keysInterpol); } } }