void ComputeMSURFDescriptor( const ImageT & Lx , const ImageT & Ly , const int id_octave , const SIOPointFeature & ipt , Descriptor< Real , 64 > & desc ) { Real dx = 0, dy = 0, mdx = 0, mdy = 0, gauss_s1 = 0, gauss_s2 = 0; Real rx = 0, ry = 0, rrx = 0, rry = 0, ys = 0, xs = 0; Real sample_x = 0, sample_y = 0; int kx = 0, ky = 0, i = 0, j = 0, dcount = 0; // Subregion centers for the 4x4 gaussian weighting Real cx = - static_cast<Real>( 0.5 ) , cy = static_cast<Real>( 0.5 ) ; // Set the descriptor size and the sample and pattern sizes const int sample_step = 5; const int pattern_size = 12; // Get the information from the keypoint const Real ratio = static_cast<Real>( 1 << id_octave ); const int scale = MathTrait<float>::round( ipt.scale() / ratio ); const Real angle = ipt.orientation() ; const Real yf = ipt.y() / ratio; const Real xf = ipt.x() / ratio; const Real co = MathTrait<Real>::cos( angle ); const Real si = MathTrait<Real>::sin( angle ); i = -8; const image::Sampler2d<image::SamplerLinear> sampler; // Calculate descriptor for this interest point // Area of size 24 s x 24 s while ( i < pattern_size ) { j = -8; i = i - 4; cx += 1.0; cy = -0.5; while ( j < pattern_size ) { dx = dy = mdx = mdy = 0.0; cy += 1.0; j = j - 4; ky = i + sample_step; kx = j + sample_step; xs = xf + ( -kx * scale * si + ky * scale * co ); ys = yf + ( kx * scale * co + ky * scale * si ); for ( int k = i; k < i + 9; ++k ) { for ( int l = j; l < j + 9; ++l ) { // Get coords of sample point on the rotated axis sample_y = yf + ( l * scale * co + k * scale * si ); sample_x = xf + ( -l * scale * si + k * scale * co ); // Get the gaussian weighted x and y responses gauss_s1 = gaussian( xs - sample_x, ys - sample_y, static_cast<Real>( 2.5 ) * static_cast<Real>( scale ) ); rx = sampler( Lx, sample_y, sample_x ); ry = sampler( Ly, sample_y, sample_x ); // Get the x and y derivatives on the rotated axis rry = gauss_s1 * ( rx * co + ry * si ); rrx = gauss_s1 * ( -rx * si + ry * co ); // Sum the derivatives to the cumulative descriptor dx += rrx; dy += rry; mdx += MathTrait<Real>::abs( rrx ); mdy += MathTrait<Real>::abs( rry ); } } // Add the values to the descriptor vector gauss_s2 = gaussian( cx - static_cast<Real>( 2.0 ) , cy - static_cast<Real>( 2.0 ) , static_cast<Real>( 1.5 ) ) ; desc[dcount++] = dx * gauss_s2; desc[dcount++] = dy * gauss_s2; desc[dcount++] = mdx * gauss_s2; desc[dcount++] = mdy * gauss_s2; j += 9; } i += 9; } // convert to unit vector (L2 norm) desc.normalize(); }
static bool SIFTDetector(const Image<unsigned char>& I, std::vector<SIOPointFeature>& feats, std::vector<Descriptor<type,128> >& descs, bool bDezoom = false, bool bRootSift = false, float dPeakThreshold = 0.04f) { // First Octave Index. int firstOctave = (bDezoom == true) ? -1 : 0; // Number of octaves. int numOctaves = 6; // Number of scales per octave. int numScales = 3; // Max ratio of Hessian eigenvalues. float edgeThresh = 10.0f; // Min contrast. float peakThresh = dPeakThreshold; int w=I.Width(), h=I.Height(); //Convert to float Image<float> If( I.GetMat().cast<float>() ); vl_constructor(); VlSiftFilt *filt = vl_sift_new(w,h,numOctaves,numScales,firstOctave); if (edgeThresh >= 0) vl_sift_set_edge_thresh(filt, edgeThresh); if (peakThresh >= 0) vl_sift_set_peak_thresh(filt, 255*peakThresh/numScales); vl_sift_process_first_octave(filt, If.data()); vl_sift_pix descr[128]; Descriptor<type, 128> descriptor; while (true) { vl_sift_detect(filt); VlSiftKeypoint const *keys = vl_sift_get_keypoints(filt); int nkeys = vl_sift_get_nkeypoints(filt); for (int i=0;i<nkeys;++i) { double angles [4]; int nangles=vl_sift_calc_keypoint_orientations(filt,angles,keys+i); for (int q=0 ; q < nangles ; ++q) { vl_sift_calc_keypoint_descriptor(filt,descr, keys+i, angles [q]); SIOPointFeature fp; fp.x() = keys[i].x; fp.y() = keys[i].y; fp.scale() = keys[i].sigma; fp.orientation() = static_cast<float>(angles[q]); siftDescToFloat(descr, descriptor, bRootSift); descs.push_back(descriptor); feats.push_back(fp); } } if (vl_sift_process_next_octave(filt)) break; // Last octave } vl_sift_delete(filt); vl_destructor(); return true; }