@@ -569,92 +569,160 @@ static bool adjustLocalExtrema( const std::vector<Mat>& dog_pyr, KeyPoint& kpt,
569
569
}
570
570
571
571
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
577
573
{
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 ;
583
609
584
- keypoints.clear ();
610
+ static const int n = SIFT_ORI_HIST_BINS;
611
+ float hist[n];
585
612
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++)
588
619
{
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);
595
623
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 ++)
597
625
{
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 ])))
603
648
{
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++ )
626
662
{
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 ;
643
665
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 ;
645
673
{
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);
651
675
keypoints.push_back (kpt);
652
676
}
653
677
}
654
678
}
655
679
}
656
680
}
657
681
}
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
+ }
658
726
}
659
727
660
728
@@ -1081,7 +1149,7 @@ void SIFT_Impl::detectAndCompute(InputArray _image, InputArray _mask,
1081
1149
{
1082
1150
// t = (double)getTickCount();
1083
1151
findScaleSpaceExtrema (gpyr, dogpyr, keypoints);
1084
- KeyPointsFilter::removeDuplicated ( keypoints );
1152
+ KeyPointsFilter::removeDuplicatedSorted ( keypoints );
1085
1153
1086
1154
if ( nfeatures > 0 )
1087
1155
KeyPointsFilter::retainBest (keypoints, nfeatures);
0 commit comments