Skip to content

Commit 4bc49c0

Browse files
committed
Merge pull request #1195 from woodychow:multithread_sift_findScaleSpaceExtrema
2 parents b954189 + ab43a3b commit 4bc49c0

File tree

1 file changed

+143
-71
lines changed

1 file changed

+143
-71
lines changed

modules/xfeatures2d/src/sift.cpp

Lines changed: 143 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -569,92 +569,164 @@ 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+
TLSData<std::vector<KeyPoint> > &_tls_kpts_struct)
589+
590+
: o(_o),
591+
i(_i),
592+
threshold(_threshold),
593+
idx(_idx),
594+
step(_step),
595+
cols(_cols),
596+
nOctaveLayers(_nOctaveLayers),
597+
contrastThreshold(_contrastThreshold),
598+
edgeThreshold(_edgeThreshold),
599+
sigma(_sigma),
600+
gauss_pyr(_gauss_pyr),
601+
dog_pyr(_dog_pyr),
602+
tls_kpts_struct(_tls_kpts_struct) { }
603+
void operator()( const cv::Range& range ) const
604+
{
605+
const int begin = range.start;
606+
const int end = range.end;
583607

584-
keypoints.clear();
608+
static const int n = SIFT_ORI_HIST_BINS;
609+
float hist[n];
585610

586-
for( int o = 0; o < nOctaves; o++ )
587-
for( int i = 1; i <= nOctaveLayers; i++ )
611+
const Mat& img = dog_pyr[idx];
612+
const Mat& prev = dog_pyr[idx-1];
613+
const Mat& next = dog_pyr[idx+1];
614+
615+
std::vector<KeyPoint> *tls_kpts = tls_kpts_struct.get();
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;
651-
keypoints.push_back(kpt);
674+
tls_kpts->push_back(kpt);
652675
}
653676
}
654677
}
655678
}
656679
}
657680
}
681+
}
682+
private:
683+
int o, i;
684+
int threshold;
685+
int idx, step, cols;
686+
int nOctaveLayers;
687+
double contrastThreshold;
688+
double edgeThreshold;
689+
double sigma;
690+
const std::vector<Mat>& gauss_pyr;
691+
const std::vector<Mat>& dog_pyr;
692+
TLSData<std::vector<KeyPoint> > &tls_kpts_struct;
693+
};
694+
695+
//
696+
// Detects features at extrema in DoG scale space. Bad features are discarded
697+
// based on contrast and ratio of principal curvatures.
698+
void SIFT_Impl::findScaleSpaceExtrema( const std::vector<Mat>& gauss_pyr, const std::vector<Mat>& dog_pyr,
699+
std::vector<KeyPoint>& keypoints ) const
700+
{
701+
const int nOctaves = (int)gauss_pyr.size()/(nOctaveLayers + 3);
702+
const int threshold = cvFloor(0.5 * contrastThreshold / nOctaveLayers * 255 * SIFT_FIXPT_SCALE);
703+
704+
keypoints.clear();
705+
TLSData<std::vector<KeyPoint> > tls_kpts_struct;
706+
707+
for( int o = 0; o < nOctaves; o++ )
708+
for( int i = 1; i <= nOctaveLayers; i++ )
709+
{
710+
const int idx = o*(nOctaveLayers+2)+i;
711+
const Mat& img = dog_pyr[idx];
712+
const int step = (int)img.step1();
713+
const int rows = img.rows, cols = img.cols;
714+
715+
parallel_for_(Range(SIFT_IMG_BORDER, rows-SIFT_IMG_BORDER),
716+
findScaleSpaceExtremaComputer(
717+
o, i, threshold, idx, step, cols,
718+
nOctaveLayers,
719+
contrastThreshold,
720+
edgeThreshold,
721+
sigma,
722+
gauss_pyr, dog_pyr, tls_kpts_struct));
723+
}
724+
725+
std::vector<std::vector<KeyPoint>*> kpt_vecs;
726+
tls_kpts_struct.gather(kpt_vecs);
727+
for (size_t i = 0; i < kpt_vecs.size(); ++i) {
728+
keypoints.insert(keypoints.end(), kpt_vecs[i]->begin(), kpt_vecs[i]->end());
729+
}
658730
}
659731

660732

@@ -1081,7 +1153,7 @@ void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
10811153
{
10821154
//t = (double)getTickCount();
10831155
findScaleSpaceExtrema(gpyr, dogpyr, keypoints);
1084-
KeyPointsFilter::removeDuplicated( keypoints );
1156+
KeyPointsFilter::removeDuplicatedSorted( keypoints );
10851157

10861158
if( nfeatures > 0 )
10871159
KeyPointsFilter::retainBest(keypoints, nfeatures);

0 commit comments

Comments
 (0)