Skip to content

Commit 6be2945

Browse files
author
Woody Chow
committed
Multithreading findScaleSpaceExtremaComputer. Sort the keypoints afterwards to make the output stable
1 parent 27f6d4e commit 6be2945

File tree

1 file changed

+138
-70
lines changed

1 file changed

+138
-70
lines changed

modules/xfeatures2d/src/sift.cpp

Lines changed: 138 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -569,92 +569,160 @@ static bool adjustLocalExtrema( const std::vector<Mat>& dog_pyr, KeyPoint& kpt,
569569
}
570570

571571

572-
//
573-
// Detects features at extrema in DoG scale space. Bad features are discarded
574-
// based on contrast and ratio of principal curvatures.
575-
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
576-
std::vector<KeyPoint>& keypoints ) const
572+
class findScaleSpaceExtremaComputer : public ParallelLoopBody
577573
{
578-
int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
579-
int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE);
580-
const int n = SIFT_ORI_HIST_BINS;
581-
float hist[n];
582-
KeyPoint kpt;
574+
public:
575+
findScaleSpaceExtremaComputer(
576+
int _o,
577+
int _i,
578+
int _threshold,
579+
int _idx,
580+
int _step,
581+
int _cols,
582+
int _nOctaveLayers,
583+
double _contrastThreshold,
584+
double _edgeThreshold,
585+
double _sigma,
586+
const std::vector<Mat>& _gauss_pyr,
587+
const std::vector<Mat>& _dog_pyr,
588+
std::vector<KeyPoint>& _keypoints,
589+
Mutex &_mutex)
590+
591+
: o(_o),
592+
i(_i),
593+
threshold(_threshold),
594+
idx(_idx),
595+
step(_step),
596+
cols(_cols),
597+
nOctaveLayers(_nOctaveLayers),
598+
contrastThreshold(_contrastThreshold),
599+
edgeThreshold(_edgeThreshold),
600+
sigma(_sigma),
601+
gauss_pyr(_gauss_pyr),
602+
dog_pyr(_dog_pyr),
603+
keypoints(_keypoints),
604+
mutex(_mutex) { }
605+
void operator()( const cv::Range& range ) const
606+
{
607+
const int begin = range.start;
608+
const int end = range.end;
583609

584-
keypoints.clear();
610+
static const int n = SIFT_ORI_HIST_BINS;
611+
float hist[n];
585612

586-
for( int o = 0; o < nOctaves; o++ )
587-
for( int i = 1; i <= nOctaveLayers; i++ )
613+
const Mat& img = dog_pyr[idx];
614+
const Mat& prev = dog_pyr[idx-1];
615+
const Mat& next = dog_pyr[idx+1];
616+
617+
KeyPoint kpt;
618+
for( int r = begin; r < end; r++)
588619
{
589-
int idx = o*(nOctaveLayers+2)+i;
590-
const Mat& img = dog_pyr[idx];
591-
const Mat& prev = dog_pyr[idx-1];
592-
const Mat& next = dog_pyr[idx+1];
593-
int step = (int)img.step1();
594-
int rows = img.rows, cols = img.cols;
620+
const sift_wt* currptr = img.ptr<sift_wt>(r);
621+
const sift_wt* prevptr = prev.ptr<sift_wt>(r);
622+
const sift_wt* nextptr = next.ptr<sift_wt>(r);
595623

596-
for( int r = SIFT_IMG_BORDER; r < rows-SIFT_IMG_BORDER; r++)
624+
for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)
597625
{
598-
const sift_wt* currptr = img.ptr<sift_wt>(r);
599-
const sift_wt* prevptr = prev.ptr<sift_wt>(r);
600-
const sift_wt* nextptr = next.ptr<sift_wt>(r);
601-
602-
for( int c = SIFT_IMG_BORDER; c < cols-SIFT_IMG_BORDER; c++)
626+
sift_wt val = currptr[c];
627+
628+
// find local extrema with pixel accuracy
629+
if( std::abs(val) > threshold &&
630+
((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&
631+
val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
632+
val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
633+
val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
634+
val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
635+
val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
636+
val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
637+
val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
638+
val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
639+
(val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
640+
val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
641+
val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
642+
val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
643+
val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
644+
val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
645+
val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
646+
val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
647+
val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
603648
{
604-
sift_wt val = currptr[c];
605-
606-
// find local extrema with pixel accuracy
607-
if( std::abs(val) > threshold &&
608-
((val > 0 && val >= currptr[c-1] && val >= currptr[c+1] &&
609-
val >= currptr[c-step-1] && val >= currptr[c-step] && val >= currptr[c-step+1] &&
610-
val >= currptr[c+step-1] && val >= currptr[c+step] && val >= currptr[c+step+1] &&
611-
val >= nextptr[c] && val >= nextptr[c-1] && val >= nextptr[c+1] &&
612-
val >= nextptr[c-step-1] && val >= nextptr[c-step] && val >= nextptr[c-step+1] &&
613-
val >= nextptr[c+step-1] && val >= nextptr[c+step] && val >= nextptr[c+step+1] &&
614-
val >= prevptr[c] && val >= prevptr[c-1] && val >= prevptr[c+1] &&
615-
val >= prevptr[c-step-1] && val >= prevptr[c-step] && val >= prevptr[c-step+1] &&
616-
val >= prevptr[c+step-1] && val >= prevptr[c+step] && val >= prevptr[c+step+1]) ||
617-
(val < 0 && val <= currptr[c-1] && val <= currptr[c+1] &&
618-
val <= currptr[c-step-1] && val <= currptr[c-step] && val <= currptr[c-step+1] &&
619-
val <= currptr[c+step-1] && val <= currptr[c+step] && val <= currptr[c+step+1] &&
620-
val <= nextptr[c] && val <= nextptr[c-1] && val <= nextptr[c+1] &&
621-
val <= nextptr[c-step-1] && val <= nextptr[c-step] && val <= nextptr[c-step+1] &&
622-
val <= nextptr[c+step-1] && val <= nextptr[c+step] && val <= nextptr[c+step+1] &&
623-
val <= prevptr[c] && val <= prevptr[c-1] && val <= prevptr[c+1] &&
624-
val <= prevptr[c-step-1] && val <= prevptr[c-step] && val <= prevptr[c-step+1] &&
625-
val <= prevptr[c+step-1] && val <= prevptr[c+step] && val <= prevptr[c+step+1])))
649+
int r1 = r, c1 = c, layer = i;
650+
if( !adjustLocalExtrema(dog_pyr, kpt, o, layer, r1, c1,
651+
nOctaveLayers, (float)contrastThreshold,
652+
(float)edgeThreshold, (float)sigma) )
653+
continue;
654+
float scl_octv = kpt.size*0.5f/(1 << o);
655+
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+3) + layer],
656+
Point(c1, r1),
657+
cvRound(SIFT_ORI_RADIUS * scl_octv),
658+
SIFT_ORI_SIG_FCTR * scl_octv,
659+
hist, n);
660+
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
661+
for( int j = 0; j < n; j++ )
626662
{
627-
int r1 = r, c1 = c, layer = i;
628-
if( !adjustLocalExtrema(dog_pyr, kpt, o, layer, r1, c1,
629-
nOctaveLayers, (float)contrastThreshold,
630-
(float)edgeThreshold, (float)sigma) )
631-
continue;
632-
float scl_octv = kpt.size*0.5f/(1 << o);
633-
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+3) + layer],
634-
Point(c1, r1),
635-
cvRound(SIFT_ORI_RADIUS * scl_octv),
636-
SIFT_ORI_SIG_FCTR * scl_octv,
637-
hist, n);
638-
float mag_thr = (float)(omax * SIFT_ORI_PEAK_RATIO);
639-
for( int j = 0; j < n; j++ )
640-
{
641-
int l = j > 0 ? j - 1 : n - 1;
642-
int r2 = j < n-1 ? j + 1 : 0;
663+
int l = j > 0 ? j - 1 : n - 1;
664+
int r2 = j < n-1 ? j + 1 : 0;
643665

644-
if( hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr )
666+
if( hist[j] > hist[l] && hist[j] > hist[r2] && hist[j] >= mag_thr )
667+
{
668+
float bin = j + 0.5f * (hist[l]-hist[r2]) / (hist[l] - 2*hist[j] + hist[r2]);
669+
bin = bin < 0 ? n + bin : bin >= n ? bin - n : bin;
670+
kpt.angle = 360.f - (float)((360.f/n) * bin);
671+
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
672+
kpt.angle = 0.f;
645673
{
646-
float bin = j + 0.5f * (hist[l]-hist[r2]) / (hist[l] - 2*hist[j] + hist[r2]);
647-
bin = bin < 0 ? n + bin : bin >= n ? bin - n : bin;
648-
kpt.angle = 360.f - (float)((360.f/n) * bin);
649-
if(std::abs(kpt.angle - 360.f) < FLT_EPSILON)
650-
kpt.angle = 0.f;
674+
AutoLock autoLock(mutex);
651675
keypoints.push_back(kpt);
652676
}
653677
}
654678
}
655679
}
656680
}
657681
}
682+
}
683+
private:
684+
int o, i;
685+
int threshold;
686+
int idx, step, cols;
687+
int nOctaveLayers;
688+
double contrastThreshold;
689+
double edgeThreshold;
690+
double sigma;
691+
const std::vector<Mat>& gauss_pyr;
692+
const std::vector<Mat>& dog_pyr;
693+
std::vector<KeyPoint>& keypoints;
694+
Mutex &mutex;
695+
};
696+
697+
//
698+
// Detects features at extrema in DoG scale space. Bad features are discarded
699+
// based on contrast and ratio of principal curvatures.
700+
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
701+
std::vector<KeyPoint>& keypoints ) const
702+
{
703+
const int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
704+
const int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE);
705+
706+
keypoints.clear();
707+
Mutex mutex;
708+
709+
for( int o = 0; o < nOctaves; o++ )
710+
for( int i = 1; i <= nOctaveLayers; i++ )
711+
{
712+
const int idx = o*(nOctaveLayers+2)+i;
713+
const Mat& img = dog_pyr[idx];
714+
const int step = (int)img.step1();
715+
const int rows = img.rows, cols = img.cols;
716+
717+
parallel_for_(Range(SIFT_IMG_BORDER, rows-SIFT_IMG_BORDER),
718+
findScaleSpaceExtremaComputer(
719+
o, i, threshold, idx, step, cols,
720+
nOctaveLayers,
721+
contrastThreshold,
722+
edgeThreshold,
723+
sigma,
724+
gauss_pyr, dog_pyr, keypoints, mutex));
725+
}
658726
}
659727

660728

@@ -1081,7 +1149,7 @@ void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
10811149
{
10821150
//t = (double)getTickCount();
10831151
findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
1084-
KeyPointsFilter::removeDuplicated( keypoints );
1152+
KeyPointsFilter::removeDuplicatedSorted( keypoints );
10851153

10861154
if( nfeatures > 0 )
10871155
KeyPointsFilter::retainBest(keypoints, nfeatures);

0 commit comments

Comments
 (0)