Index: surf.cpp =================================================================== --- surf.cpp (révision 5377) +++ surf.cpp (copie de travail) @@ -114,6 +114,7 @@ CvSURFParams params; params.hessianThreshold = threshold; params.extended = extended; + params.upright = 0; params.nOctaves = 4; params.nOctaveLayers = 2; return params; @@ -575,7 +576,6 @@ DW[i*PATCH_SZ+j] = G_desc.at(i,0) * G_desc.at(j,0); } } - void operator()(const BlockedRange& range) const { /* X and Y gradient wavelet data */ @@ -630,58 +630,67 @@ kp->size = -1; continue; } - icvResizeHaarPattern( dx_s, dx_t, NX, 4, grad_wav_size, sum->cols ); - icvResizeHaarPattern( dy_s, dy_t, NY, 4, grad_wav_size, sum->cols ); - for( kk = 0, nangle = 0; kk < nOriSamples; kk++ ) - { - const int* ptr; - float vx, vy; - x = cvRound( center.x + apt[kk].x*s - (float)(grad_wav_size-1)/2 ); - y = cvRound( center.y + apt[kk].y*s - (float)(grad_wav_size-1)/2 ); - if( (unsigned)y >= (unsigned)(sum->rows - grad_wav_size) || - (unsigned)x >= (unsigned)(sum->cols - grad_wav_size) ) + + float descriptor_dir; + if (params->upright == 0) { + + icvResizeHaarPattern( dx_s, dx_t, NX, 4, grad_wav_size, sum->cols ); + icvResizeHaarPattern( dy_s, dy_t, NY, 4, grad_wav_size, sum->cols ); + for( kk = 0, nangle = 0; kk < nOriSamples; kk++ ) + { + const int* ptr; + float vx, vy; + x = cvRound( center.x + apt[kk].x*s - (float)(grad_wav_size-1)/2 ); + y = cvRound( center.y + apt[kk].y*s - (float)(grad_wav_size-1)/2 ); + if( (unsigned)y >= (unsigned)(sum->rows - grad_wav_size) || + (unsigned)x >= (unsigned)(sum->cols - grad_wav_size) ) + continue; + ptr = sum_ptr + x + y*sum_cols; + vx = icvCalcHaarPattern( ptr, dx_t, 2 ); + vy = icvCalcHaarPattern( ptr, dy_t, 2 ); + X[nangle] = vx*aptw[kk]; Y[nangle] = vy*aptw[kk]; + nangle++; + } + if ( nangle == 0 ) + { + /* No gradient could be sampled because the keypoint is too + * near too one or more of the sides of the image. As we + * therefore cannot find a dominant direction, we skip this + * keypoint and mark it for later deletion from the sequence. */ + kp->size = -1; continue; - ptr = sum_ptr + x + y*sum_cols; - vx = icvCalcHaarPattern( ptr, dx_t, 2 ); - vy = icvCalcHaarPattern( ptr, dy_t, 2 ); - X[nangle] = vx*aptw[kk]; Y[nangle] = vy*aptw[kk]; - nangle++; - } - if ( nangle == 0 ) - { - /* No gradient could be sampled because the keypoint is too - * near too one or more of the sides of the image. As we - * therefore cannot find a dominant direction, we skip this - * keypoint and mark it for later deletion from the sequence. */ - kp->size = -1; - continue; - } - matX.cols = matY.cols = _angle.cols = nangle; - cvCartToPolar( &matX, &matY, 0, &_angle, 1 ); + } + matX.cols = matY.cols = _angle.cols = nangle; + cvCartToPolar( &matX, &matY, 0, &_angle, 1 ); - float bestx = 0, besty = 0, descriptor_mod = 0; - for( i = 0; i < 360; i += ORI_SEARCH_INC ) - { - float sumx = 0, sumy = 0, temp_mod; - for( j = 0; j < nangle; j++ ) + float bestx = 0, besty = 0, descriptor_mod = 0; + for( i = 0; i < 360; i += ORI_SEARCH_INC ) { - int d = std::abs(cvRound(angle[j]) - i); - if( d < ORI_WIN/2 || d > 360-ORI_WIN/2 ) + float sumx = 0, sumy = 0, temp_mod; + for( j = 0; j < nangle; j++ ) { - sumx += X[j]; - sumy += Y[j]; + int d = std::abs(cvRound(angle[j]) - i); + if( d < ORI_WIN/2 || d > 360-ORI_WIN/2 ) + { + sumx += X[j]; + sumy += Y[j]; + } } + temp_mod = sumx*sumx + sumy*sumy; + if( temp_mod > descriptor_mod ) + { + descriptor_mod = temp_mod; + bestx = sumx; + besty = sumy; + } } - temp_mod = sumx*sumx + sumy*sumy; - if( temp_mod > descriptor_mod ) - { - descriptor_mod = temp_mod; - bestx = sumx; - besty = sumy; - } + + descriptor_dir = cvFastArctan( besty, bestx ); + kp->dir = descriptor_dir; + } else { + descriptor_dir = 0; + kp->dir = 0; } - float descriptor_dir = cvFastArctan( besty, bestx ); - kp->dir = descriptor_dir; if( !descriptors ) continue; descriptor_dir *= (float)(CV_PI/180); @@ -689,35 +698,59 @@ int win_size = (int)((PATCH_SZ+1)*s); CV_Assert( winbuf->cols >= win_size*win_size ); CvMat win = cvMat(win_size, win_size, CV_8U, winbuf->data.ptr); - float sin_dir = sin(descriptor_dir); - float cos_dir = cos(descriptor_dir) ; - /* Subpixel interpolation version (slower). Subpixel not required since - the pixels will all get averaged when we scale down to 20 pixels */ - /* - float w[] = { cos_dir, sin_dir, center.x, - -sin_dir, cos_dir , center.y }; - CvMat W = cvMat(2, 3, CV_32F, w); - cvGetQuadrangleSubPix( img, &win, &W ); - */ + if (params->upright == 0) { - /* Nearest neighbour version (faster) */ - float win_offset = -(float)(win_size-1)/2; - float start_x = center.x + win_offset*cos_dir + win_offset*sin_dir; - float start_y = center.y - win_offset*sin_dir + win_offset*cos_dir; - uchar* WIN = win.data.ptr; - for( i = 0; i < win_size; i++, start_x += sin_dir, start_y += cos_dir ) - { - float pixel_x = start_x; - float pixel_y = start_y; - for( j = 0; j < win_size; j++, pixel_x += cos_dir, pixel_y -= sin_dir ) + float sin_dir = sin(descriptor_dir); + float cos_dir = cos(descriptor_dir) ; + + /* Subpixel interpolation version (slower). Subpixel not required since + the pixels will all get averaged when we scale down to 20 pixels */ + /* + float w[] = { cos_dir, sin_dir, center.x, + -sin_dir, cos_dir , center.y }; + CvMat W = cvMat(2, 3, CV_32F, w); + cvGetQuadrangleSubPix( img, &win, &W ); + */ + + /* Nearest neighbour version (faster) */ + float win_offset = -(float)(win_size-1)/2; + float start_x = center.x + win_offset*cos_dir + win_offset*sin_dir; + float start_y = center.y - win_offset*sin_dir + win_offset*cos_dir; + uchar* WIN = win.data.ptr; + for( i = 0; i < win_size; i++, start_x += sin_dir, start_y += cos_dir ) { - int x = std::min(std::max(cvRound(pixel_x), 0), img->cols-1); - int y = std::min(std::max(cvRound(pixel_y), 0), img->rows-1); - WIN[i*win_size + j] = img->data.ptr[y*img->step + x]; + float pixel_x = start_x; + float pixel_y = start_y; + for( j = 0; j < win_size; j++, pixel_x += cos_dir, pixel_y -= sin_dir ) + { + int x = std::min(std::max(cvRound(pixel_x), 0), img->cols-1); + int y = std::min(std::max(cvRound(pixel_y), 0), img->rows-1); + WIN[i*win_size + j] = img->data.ptr[y*img->step + x]; + } } + } else { + /* extract rect - slightly optimized version of the code above + TODO: find faster code, as this is simply an extract rect operation, + e.g. by using cvGetSubRect, problem is the border processing */ + + float win_offset = -(float)(win_size-1)/2; + int start_x = cvRound(center.x + win_offset); + int start_y = cvRound(center.y + win_offset); + uchar* WIN = win.data.ptr; + for( i=0; icols-1 ); + y = MIN( y, img->rows-1 ); + WIN[i*win_size + j] = img->data.ptr[y*img->step+x]; + } + } } - /* Scale the window to size PATCH_SZ so each pixel's size is s. This makes calculating the gradients with wavelets of size 2s easy */ cvResize( &win, &_patch, CV_INTER_AREA ); @@ -886,8 +919,8 @@ cv::parallel_for(cv::BlockedRange(0, N), cv::SURFInvoker(¶ms, keypoints, descriptors, img, sum) ); #else - cv::SURFInvoker invoker(¶ms, keypoints, descriptors, img, sum); - invoker(cv::BlockedRange(0, N)); + cv::SURFInvoker invoker(¶ms, keypoints, descriptors, img, sum); + invoker(cv::BlockedRange(0, N)); #endif } @@ -924,14 +957,16 @@ { hessianThreshold = 100; extended = 1; + upright = 0; nOctaves = 4; nOctaveLayers = 2; } -SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended) +SURF::SURF(double _threshold, int _nOctaves, int _nOctaveLayers, bool _extended, bool _upright) { hessianThreshold = _threshold; extended = _extended; + upright = _upright; nOctaves = _nOctaves; nOctaveLayers = _nOctaveLayers; }