bug-2325-surf.diff
b/modules/nonfree/include/opencv2/nonfree/features2d.hpp | ||
---|---|---|
52 | 52 | |
53 | 53 |
/*! |
54 | 54 |
SIFT implementation. |
55 |
|
|
55 | ||
56 | 56 |
The class implements SIFT algorithm by D. Lowe. |
57 | 57 |
*/ |
58 | 58 |
class CV_EXPORTS_W SIFT : public Feature2D |
... | ... | |
64 | 64 | |
65 | 65 |
//! returns the descriptor size in floats (128) |
66 | 66 |
CV_WRAP int descriptorSize() const; |
67 |
|
|
67 | ||
68 | 68 |
//! returns the descriptor type |
69 | 69 |
CV_WRAP int descriptorType() const; |
70 |
|
|
70 | ||
71 | 71 |
//! finds the keypoints using SIFT algorithm |
72 | 72 |
void operator()(InputArray img, InputArray mask, |
73 | 73 |
vector<KeyPoint>& keypoints) const; |
... | ... | |
77 | 77 |
vector<KeyPoint>& keypoints, |
78 | 78 |
OutputArray descriptors, |
79 | 79 |
bool useProvidedKeypoints=false) const; |
80 |
|
|
80 | ||
81 | 81 |
AlgorithmInfo* info() const; |
82 |
|
|
82 | ||
83 | 83 |
void buildGaussianPyramid( const Mat& base, vector<Mat>& pyr, int nOctaves ) const; |
84 | 84 |
void buildDoGPyramid( const vector<Mat>& pyr, vector<Mat>& dogpyr ) const; |
85 | 85 |
void findScaleSpaceExtrema( const vector<Mat>& gauss_pyr, const vector<Mat>& dog_pyr, |
... | ... | |
88 | 88 |
protected: |
89 | 89 |
void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const; |
90 | 90 |
void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const; |
91 |
|
|
91 | ||
92 | 92 |
CV_PROP_RW int nfeatures; |
93 | 93 |
CV_PROP_RW int nOctaveLayers; |
94 | 94 |
CV_PROP_RW double contrastThreshold; |
... | ... | |
98 | 98 | |
99 | 99 |
typedef SIFT SiftFeatureDetector; |
100 | 100 |
typedef SIFT SiftDescriptorExtractor; |
101 |
|
|
101 | ||
102 | 102 |
/*! |
103 | 103 |
SURF implementation. |
104 |
|
|
104 | ||
105 | 105 |
The class implements SURF algorithm by H. Bay et al. |
106 | 106 |
*/ |
107 |
class CV_EXPORTS_W SURF : public Feature2D |
|
107 | ||
108 |
class CV_EXPORTS_W SurfFeatureDetector : public FeatureDetector |
|
108 | 109 |
{ |
109 | 110 |
public: |
110 | 111 |
//! the default constructor |
111 |
CV_WRAP SURF(); |
|
112 |
CV_WRAP SurfFeatureDetector(); |
|
113 | ||
112 | 114 |
//! the full constructor taking all the necessary parameters |
113 |
explicit CV_WRAP SURF(double hessianThreshold, |
|
114 |
int nOctaves=4, int nOctaveLayers=2, |
|
115 |
bool extended=true, bool upright=false); |
|
115 |
explicit CV_WRAP SurfFeatureDetector(double hessianThreshold, |
|
116 |
int nOctaves=4, int nOctaveLayers=2); |
|
116 | 117 | |
117 |
//! returns the descriptor size in float's (64 or 128) |
|
118 |
CV_WRAP int descriptorSize() const; |
|
119 |
|
|
120 |
//! returns the descriptor type |
|
121 |
CV_WRAP int descriptorType() const; |
|
122 |
|
|
123 | 118 |
//! finds the keypoints using fast hessian detector used in SURF |
124 | 119 |
void operator()(InputArray img, InputArray mask, |
125 |
CV_OUT vector<KeyPoint>& keypoints) const; |
|
126 |
//! finds the keypoints and computes their descriptors. Optionally it can compute descriptors for the user-provided keypoints |
|
127 |
void operator()(InputArray img, InputArray mask, |
|
128 |
CV_OUT vector<KeyPoint>& keypoints, |
|
129 |
OutputArray descriptors, |
|
130 |
bool useProvidedKeypoints=false) const; |
|
131 |
|
|
120 |
CV_OUT vector<KeyPoint>& keypoints) const; |
|
121 | ||
132 | 122 |
AlgorithmInfo* info() const; |
133 |
|
|
123 | ||
134 | 124 |
CV_PROP_RW double hessianThreshold; |
135 | 125 |
CV_PROP_RW int nOctaves; |
136 | 126 |
CV_PROP_RW int nOctaveLayers; |
127 | ||
128 |
protected: |
|
129 |
void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat()) const; |
|
130 |
void detectImplCached( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask, Mat& integralImage) const; |
|
131 | ||
132 |
}; |
|
133 | ||
134 | ||
135 |
class CV_EXPORTS_W SurfDescriptorExtractor : public DescriptorExtractor |
|
136 |
{ |
|
137 |
public: |
|
138 |
//! the default constructor |
|
139 |
CV_WRAP SurfDescriptorExtractor(); |
|
140 | ||
141 |
//! the full constructor taking all the necessary parameters |
|
142 |
explicit CV_WRAP SurfDescriptorExtractor(bool extended, bool upright=false); |
|
143 | ||
144 |
//! returns the descriptor size in float's (64 or 128) |
|
145 |
CV_WRAP int descriptorSize() const; |
|
146 | ||
147 |
//! returns the descriptor type |
|
148 |
CV_WRAP int descriptorType() const; |
|
149 | ||
150 |
AlgorithmInfo* info() const; |
|
151 | ||
137 | 152 |
CV_PROP_RW bool extended; |
138 | 153 |
CV_PROP_RW bool upright; |
139 |
|
|
154 | ||
140 | 155 |
protected: |
141 |
|
|
142 |
void detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const; |
|
143 | 156 |
void computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const; |
157 |
void computeImplCached( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors, Mat& integralImage) const; |
|
158 |
}; |
|
159 | ||
160 |
class CV_EXPORTS_W SURF : public SurfDescriptorExtractor, SurfFeatureDetector |
|
161 |
{ |
|
162 |
public: |
|
163 |
//! the default constructor |
|
164 |
CV_WRAP SURF(); |
|
165 |
//! the full constructor taking all the necessary parameters |
|
166 |
explicit CV_WRAP SURF(double hessianThreshold, |
|
167 |
int nOctaves=4, int nOctaveLayers=2, |
|
168 |
bool extended=true, bool upright=false); |
|
169 | ||
170 |
//! finds the keypoints and computes their descriptors. Optionally it can compute descriptors for the user-provided keypoints |
|
171 |
void operator()(InputArray img, InputArray mask, |
|
172 |
CV_OUT vector<KeyPoint>& keypoints, |
|
173 |
OutputArray descriptors, |
|
174 |
bool useProvidedKeypoints=false) const; |
|
175 | ||
176 |
//! finds the keypoints using fast hessian detector used in SURF |
|
177 |
void operator()(InputArray img, InputArray mask, |
|
178 |
CV_OUT vector<KeyPoint>& keypoints) const; |
|
179 | ||
180 |
AlgorithmInfo* info() const; |
|
181 | ||
144 | 182 |
}; |
145 |
|
|
146 |
typedef SURF SurfFeatureDetector; |
|
147 |
typedef SURF SurfDescriptorExtractor; |
|
148 | 183 | |
149 | 184 |
} /* namespace cv */ |
150 | 185 |
b/modules/nonfree/src/nonfree_init.cpp | ||
---|---|---|
54 | 54 |
obj.info()->addParam(obj, "extended", obj.extended); |
55 | 55 |
obj.info()->addParam(obj, "upright", obj.upright)); |
56 | 56 | |
57 |
CV_INIT_ALGORITHM(SurfFeatureDetector, "Feature2D.SurfDetector", |
|
58 |
obj.info()->addParam(obj, "hessianThreshold", obj.hessianThreshold); |
|
59 |
obj.info()->addParam(obj, "nOctaves", obj.nOctaves); |
|
60 |
obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers)); |
|
61 | ||
62 |
CV_INIT_ALGORITHM(SurfDescriptorExtractor, "Feature2D.SurfExtractor", |
|
63 |
obj.info()->addParam(obj, "extended", obj.extended); |
|
64 |
obj.info()->addParam(obj, "upright", obj.upright)); |
|
65 | ||
57 | 66 |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
58 | 67 | |
59 |
CV_INIT_ALGORITHM(SIFT, "Feature2D.SIFT",
|
|
68 |
CV_INIT_ALGORITHM(SIFT, "Feature2D.SIFT", |
|
60 | 69 |
obj.info()->addParam(obj, "nFeatures", obj.nfeatures); |
61 | 70 |
obj.info()->addParam(obj, "nOctaveLayers", obj.nOctaveLayers); |
62 | 71 |
obj.info()->addParam(obj, "contrastThreshold", obj.contrastThreshold); |
63 | 72 |
obj.info()->addParam(obj, "edgeThreshold", obj.edgeThreshold); |
64 | 73 |
obj.info()->addParam(obj, "sigma", obj.sigma)); |
65 | 74 | |
66 |
///////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
67 |
|
|
75 |
/////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|
76 | ||
68 | 77 |
bool initModule_nonfree(void) |
69 | 78 |
{ |
70 |
Ptr<Algorithm> sift = createSIFT(), surf = createSURF(); |
|
71 |
return sift->info() != 0 && surf->info() != 0; |
|
79 |
Ptr<Algorithm> |
|
80 |
sift = createSIFT(), |
|
81 |
surf = createSURF(), |
|
82 |
surfDetector = createSurfFeatureDetector(), |
|
83 |
surfExtractor = createSurfFeatureDetector(); |
|
84 |
return sift->info() != 0 |
|
85 |
&& surf->info() != 0 |
|
86 |
&& surfDetector->info() != 0 |
|
87 |
&& surfExtractor->info() != 0 |
|
88 |
; |
|
72 | 89 |
} |
73 | 90 | |
74 | 91 |
} |
75 |
|
b/modules/nonfree/src/surf.cpp | ||
---|---|---|
854 | 854 |
nOctaveLayers = _nOctaveLayers; |
855 | 855 |
} |
856 | 856 | |
857 |
int SURF::descriptorSize() const { return extended ? 128 : 64; }
|
|
858 |
int SURF::descriptorType() const { return CV_32F; }
|
|
857 |
int SurfDescriptorExtractor::descriptorSize() const { return extended ? 128 : 64; }
|
|
858 |
int SurfDescriptorExtractor::descriptorType() const { return CV_32F; }
|
|
859 | 859 | |
860 | 860 |
void SURF::operator()(InputArray imgarg, InputArray maskarg, |
861 | 861 |
CV_OUT vector<KeyPoint>& keypoints) const |
... | ... | |
868 | 868 |
OutputArray _descriptors, |
869 | 869 |
bool useProvidedKeypoints) const |
870 | 870 |
{ |
871 |
Mat img = _img.getMat(), mask = _mask.getMat(), mask1, sum, msum; |
|
872 |
bool doDescriptors = _descriptors.needed(); |
|
871 |
Mat integralImage; |
|
872 |
Mat img = _img.getMat(); |
|
873 | ||
874 |
// Compute keypoints only if we are not asked for evaluating the descriptors are some given locations: |
|
875 |
if( !useProvidedKeypoints ) |
|
876 |
{ |
|
877 |
this->detectImplCached(img, keypoints, _mask.getMat(), integralImage); |
|
878 |
} |
|
879 | ||
880 |
this->computeImplCached(img, keypoints, _descriptors.getMatRef(), integralImage); |
|
881 | ||
882 | ||
883 |
} |
|
884 | ||
885 |
SurfFeatureDetector::SurfFeatureDetector() |
|
886 |
{ |
|
887 |
hessianThreshold = 100; |
|
888 |
nOctaves = 4; |
|
889 |
nOctaveLayers = 2; |
|
890 |
} |
|
891 | ||
892 |
SurfFeatureDetector::SurfFeatureDetector(double _threshold, int _nOctaves, int _nOctaveLayers) |
|
893 |
{ |
|
894 |
hessianThreshold = _threshold; |
|
895 |
nOctaves = _nOctaves; |
|
896 |
nOctaveLayers = _nOctaveLayers; |
|
897 |
} |
|
898 | ||
899 |
void SurfFeatureDetector::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const |
|
900 |
{ |
|
901 |
Mat m; |
|
902 |
this->detectImplCached(image, keypoints, mask, m); |
|
903 |
} |
|
904 | ||
905 |
void SurfFeatureDetector::detectImplCached( const Mat& img, vector<KeyPoint>& keypoints, const Mat& mask, Mat& integralImg) const |
|
906 |
{ |
|
907 |
Mat mask1, msum; |
|
908 | ||
873 | 909 | |
874 | 910 |
CV_Assert(!img.empty() && img.depth() == CV_8U); |
875 | 911 |
if( img.channels() > 1 ) |
... | ... | |
880 | 916 |
CV_Assert(nOctaves > 0); |
881 | 917 |
CV_Assert(nOctaveLayers > 0); |
882 | 918 | |
883 |
integral(img, sum, CV_32S);
|
|
919 |
integral(img, integralImg, CV_32S);
|
|
884 | 920 | |
885 |
// Compute keypoints only if we are not asked for evaluating the descriptors are some given locations: |
|
886 |
if( !useProvidedKeypoints )
|
|
921 | ||
922 |
if( !mask.empty() )
|
|
887 | 923 |
{ |
888 |
if( !mask.empty() ) |
|
889 |
{ |
|
890 |
cv::min(mask, 1, mask1); |
|
891 |
integral(mask1, msum, CV_32S); |
|
892 |
} |
|
893 |
fastHessianDetector( sum, msum, keypoints, nOctaves, nOctaveLayers, (float)hessianThreshold ); |
|
924 |
cv::min(mask, 1, mask1); |
|
925 |
integral(mask1, msum, CV_32S); |
|
894 | 926 |
} |
927 |
fastHessianDetector( integralImg, msum, keypoints, nOctaves, nOctaveLayers, (float)hessianThreshold ); |
|
928 |
} |
|
929 | ||
930 | ||
931 |
SurfDescriptorExtractor::SurfDescriptorExtractor() |
|
932 |
{ |
|
933 |
extended = true; |
|
934 |
upright = false; |
|
935 |
} |
|
936 | ||
937 |
SurfDescriptorExtractor::SurfDescriptorExtractor(bool _extended, bool _upright) |
|
938 |
{ |
|
939 |
extended = _extended; |
|
940 |
upright = _upright; |
|
941 |
} |
|
942 | ||
943 |
void SurfDescriptorExtractor::computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors ) const |
|
944 |
{ |
|
945 |
Mat m; |
|
946 |
this->computeImplCached(image, keypoints, descriptors, m); |
|
947 |
} |
|
948 | ||
949 |
void SurfDescriptorExtractor::computeImplCached( const Mat& img, vector<KeyPoint>& keypoints, Mat& descriptors, Mat& integralImg) const |
|
950 |
{ |
|
951 |
CV_Assert(!img.empty() && img.depth() == CV_8U); |
|
952 |
if( img.channels() > 1 ) |
|
953 |
cvtColor(img, img, COLOR_BGR2GRAY); |
|
954 | ||
955 |
if (integralImg.empty()) |
|
956 |
integral(img, integralImg, CV_32S); |
|
895 | 957 | |
896 | 958 |
int i, j, N = (int)keypoints.size(); |
897 | 959 |
if( N > 0 ) |
898 | 960 |
{ |
899 |
Mat descriptors; |
|
900 |
bool _1d = false; |
|
901 | 961 |
int dcols = extended ? 128 : 64; |
902 | 962 |
size_t dsize = dcols*sizeof(float); |
903 | 963 | |
904 |
if( doDescriptors ) |
|
905 |
{ |
|
906 |
_1d = _descriptors.kind() == _InputArray::STD_VECTOR && _descriptors.type() == CV_32F; |
|
907 |
if( _1d ) |
|
908 |
{ |
|
909 |
_descriptors.create(N*dcols, 1, CV_32F); |
|
910 |
descriptors = _descriptors.getMat().reshape(1, N); |
|
911 |
} |
|
912 |
else |
|
913 |
{ |
|
914 |
_descriptors.create(N, dcols, CV_32F); |
|
915 |
descriptors = _descriptors.getMat(); |
|
916 |
} |
|
917 |
} |
|
964 |
descriptors.create(N, dcols, CV_32F); |
|
918 | 965 | |
919 | 966 |
// we call SURFInvoker in any case, even if we do not need descriptors, |
920 | 967 |
// since it computes orientation of each feature. |
921 |
parallel_for(BlockedRange(0, N), SURFInvoker(img, sum, keypoints, descriptors, extended, upright) );
|
|
968 |
parallel_for(BlockedRange(0, N), SURFInvoker(img, integralImg, keypoints, descriptors, extended, upright) );
|
|
922 | 969 | |
923 | 970 |
// remove keypoints that were marked for deletion |
924 | 971 |
for( i = j = 0; i < N; i++ ) |
... | ... | |
928 | 975 |
if( i > j ) |
929 | 976 |
{ |
930 | 977 |
keypoints[j] = keypoints[i]; |
931 |
if( doDescriptors ) |
|
932 |
memcpy( descriptors.ptr(j), descriptors.ptr(i), dsize); |
|
978 |
memcpy( descriptors.ptr(j), descriptors.ptr(i), dsize); |
|
933 | 979 |
} |
934 | 980 |
j++; |
935 | 981 |
} |
936 | 982 |
} |
937 |
if( N > j ) |
|
938 |
{ |
|
939 |
N = j; |
|
940 |
keypoints.resize(N); |
|
941 |
if( doDescriptors ) |
|
942 |
{ |
|
943 |
Mat d = descriptors.rowRange(0, N); |
|
944 |
if( _1d ) |
|
945 |
d = d.reshape(1, N*dcols); |
|
946 |
d.copyTo(_descriptors); |
|
947 |
} |
|
948 |
} |
|
949 | 983 |
} |
950 | 984 |
} |
951 | 985 | |
952 | ||
953 |
void SURF::detectImpl( const Mat& image, vector<KeyPoint>& keypoints, const Mat& mask) const |
|
954 |
{ |
|
955 |
(*this)(image, mask, keypoints, noArray(), false); |
|
956 |
} |
|
957 | ||
958 |
void SURF::computeImpl( const Mat& image, vector<KeyPoint>& keypoints, Mat& descriptors) const |
|
959 |
{ |
|
960 |
(*this)(image, Mat(), keypoints, descriptors, true); |
|
961 |
} |
|
962 | ||
963 | 986 |
} |
964 |
- |