Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/features2d/src/fast_score.cpp
16337 views
1
/* This is FAST corner detector, contributed to OpenCV by the author, Edward Rosten.
2
Below is the original copyright and the references */
3
4
/*
5
Copyright (c) 2006, 2008 Edward Rosten
6
All rights reserved.
7
8
Redistribution and use in source and binary forms, with or without
9
modification, are permitted provided that the following conditions
10
are met:
11
12
*Redistributions of source code must retain the above copyright
13
notice, this list of conditions and the following disclaimer.
14
15
*Redistributions in binary form must reproduce the above copyright
16
notice, this list of conditions and the following disclaimer in the
17
documentation and/or other materials provided with the distribution.
18
19
*Neither the name of the University of Cambridge nor the names of
20
its contributors may be used to endorse or promote products derived
21
from this software without specific prior written permission.
22
23
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
*/
35
36
/*
37
The references are:
38
* Machine learning for high-speed corner detection,
39
E. Rosten and T. Drummond, ECCV 2006
40
* Faster and better: A machine learning approach to corner detection
41
E. Rosten, R. Porter and T. Drummond, PAMI, 2009
42
*/
43
44
#include "fast_score.hpp"
45
#include "opencv2/core/hal/intrin.hpp"
46
#define VERIFY_CORNERS 0
47
48
namespace cv {
49
50
void makeOffsets(int pixel[25], int rowStride, int patternSize)
51
{
52
static const int offsets16[][2] =
53
{
54
{0, 3}, { 1, 3}, { 2, 2}, { 3, 1}, { 3, 0}, { 3, -1}, { 2, -2}, { 1, -3},
55
{0, -3}, {-1, -3}, {-2, -2}, {-3, -1}, {-3, 0}, {-3, 1}, {-2, 2}, {-1, 3}
56
};
57
58
static const int offsets12[][2] =
59
{
60
{0, 2}, { 1, 2}, { 2, 1}, { 2, 0}, { 2, -1}, { 1, -2},
61
{0, -2}, {-1, -2}, {-2, -1}, {-2, 0}, {-2, 1}, {-1, 2}
62
};
63
64
static const int offsets8[][2] =
65
{
66
{0, 1}, { 1, 1}, { 1, 0}, { 1, -1},
67
{0, -1}, {-1, -1}, {-1, 0}, {-1, 1}
68
};
69
70
const int (*offsets)[2] = patternSize == 16 ? offsets16 :
71
patternSize == 12 ? offsets12 :
72
patternSize == 8 ? offsets8 : 0;
73
74
CV_Assert(pixel && offsets);
75
76
int k = 0;
77
for( ; k < patternSize; k++ )
78
pixel[k] = offsets[k][0] + offsets[k][1] * rowStride;
79
for( ; k < 25; k++ )
80
pixel[k] = pixel[k - patternSize];
81
}
82
83
#if VERIFY_CORNERS
84
static void testCorner(const uchar* ptr, const int pixel[], int K, int N, int threshold) {
85
// check that with the computed "threshold" the pixel is still a corner
86
// and that with the increased-by-1 "threshold" the pixel is not a corner anymore
87
for( int delta = 0; delta <= 1; delta++ )
88
{
89
int v0 = std::min(ptr[0] + threshold + delta, 255);
90
int v1 = std::max(ptr[0] - threshold - delta, 0);
91
int c0 = 0, c1 = 0;
92
93
for( int k = 0; k < N; k++ )
94
{
95
int x = ptr[pixel[k]];
96
if(x > v0)
97
{
98
if( ++c0 > K )
99
break;
100
c1 = 0;
101
}
102
else if( x < v1 )
103
{
104
if( ++c1 > K )
105
break;
106
c0 = 0;
107
}
108
else
109
{
110
c0 = c1 = 0;
111
}
112
}
113
CV_Assert( (delta == 0 && std::max(c0, c1) > K) ||
114
(delta == 1 && std::max(c0, c1) <= K) );
115
}
116
}
117
#endif
118
119
template<>
120
int cornerScore<16>(const uchar* ptr, const int pixel[], int threshold)
121
{
122
const int K = 8, N = K*3 + 1;
123
int k, v = ptr[0];
124
short d[N];
125
for( k = 0; k < N; k++ )
126
d[k] = (short)(v - ptr[pixel[k]]);
127
128
#if CV_SIMD128
129
if (hasSIMD128())
130
{
131
v_int16x8 q0 = v_setall_s16(-1000), q1 = v_setall_s16(1000);
132
for (k = 0; k < 16; k += 8)
133
{
134
v_int16x8 v0 = v_load(d + k + 1);
135
v_int16x8 v1 = v_load(d + k + 2);
136
v_int16x8 a = v_min(v0, v1);
137
v_int16x8 b = v_max(v0, v1);
138
v0 = v_load(d + k + 3);
139
a = v_min(a, v0);
140
b = v_max(b, v0);
141
v0 = v_load(d + k + 4);
142
a = v_min(a, v0);
143
b = v_max(b, v0);
144
v0 = v_load(d + k + 5);
145
a = v_min(a, v0);
146
b = v_max(b, v0);
147
v0 = v_load(d + k + 6);
148
a = v_min(a, v0);
149
b = v_max(b, v0);
150
v0 = v_load(d + k + 7);
151
a = v_min(a, v0);
152
b = v_max(b, v0);
153
v0 = v_load(d + k + 8);
154
a = v_min(a, v0);
155
b = v_max(b, v0);
156
v0 = v_load(d + k);
157
q0 = v_max(q0, v_min(a, v0));
158
q1 = v_min(q1, v_max(b, v0));
159
v0 = v_load(d + k + 9);
160
q0 = v_max(q0, v_min(a, v0));
161
q1 = v_min(q1, v_max(b, v0));
162
}
163
q0 = v_max(q0, v_setzero_s16() - q1);
164
threshold = v_reduce_max(q0) - 1;
165
}
166
else
167
#endif
168
{
169
170
int a0 = threshold;
171
for( k = 0; k < 16; k += 2 )
172
{
173
int a = std::min((int)d[k+1], (int)d[k+2]);
174
a = std::min(a, (int)d[k+3]);
175
if( a <= a0 )
176
continue;
177
a = std::min(a, (int)d[k+4]);
178
a = std::min(a, (int)d[k+5]);
179
a = std::min(a, (int)d[k+6]);
180
a = std::min(a, (int)d[k+7]);
181
a = std::min(a, (int)d[k+8]);
182
a0 = std::max(a0, std::min(a, (int)d[k]));
183
a0 = std::max(a0, std::min(a, (int)d[k+9]));
184
}
185
186
int b0 = -a0;
187
for( k = 0; k < 16; k += 2 )
188
{
189
int b = std::max((int)d[k+1], (int)d[k+2]);
190
b = std::max(b, (int)d[k+3]);
191
b = std::max(b, (int)d[k+4]);
192
b = std::max(b, (int)d[k+5]);
193
if( b >= b0 )
194
continue;
195
b = std::max(b, (int)d[k+6]);
196
b = std::max(b, (int)d[k+7]);
197
b = std::max(b, (int)d[k+8]);
198
199
b0 = std::min(b0, std::max(b, (int)d[k]));
200
b0 = std::min(b0, std::max(b, (int)d[k+9]));
201
}
202
203
threshold = -b0 - 1;
204
}
205
206
#if VERIFY_CORNERS
207
testCorner(ptr, pixel, K, N, threshold);
208
#endif
209
return threshold;
210
}
211
212
template<>
213
int cornerScore<12>(const uchar* ptr, const int pixel[], int threshold)
214
{
215
const int K = 6, N = K*3 + 1;
216
int k, v = ptr[0];
217
short d[N + 4];
218
for( k = 0; k < N; k++ )
219
d[k] = (short)(v - ptr[pixel[k]]);
220
#if CV_SIMD128
221
for( k = 0; k < 4; k++ )
222
d[N+k] = d[k];
223
#endif
224
225
#if CV_SIMD128
226
if (hasSIMD128())
227
{
228
v_int16x8 q0 = v_setall_s16(-1000), q1 = v_setall_s16(1000);
229
for (k = 0; k < 16; k += 8)
230
{
231
v_int16x8 v0 = v_load(d + k + 1);
232
v_int16x8 v1 = v_load(d + k + 2);
233
v_int16x8 a = v_min(v0, v1);
234
v_int16x8 b = v_max(v0, v1);
235
v0 = v_load(d + k + 3);
236
a = v_min(a, v0);
237
b = v_max(b, v0);
238
v0 = v_load(d + k + 4);
239
a = v_min(a, v0);
240
b = v_max(b, v0);
241
v0 = v_load(d + k + 5);
242
a = v_min(a, v0);
243
b = v_max(b, v0);
244
v0 = v_load(d + k + 6);
245
a = v_min(a, v0);
246
b = v_max(b, v0);
247
v0 = v_load(d + k);
248
q0 = v_max(q0, v_min(a, v0));
249
q1 = v_min(q1, v_max(b, v0));
250
v0 = v_load(d + k + 7);
251
q0 = v_max(q0, v_min(a, v0));
252
q1 = v_min(q1, v_max(b, v0));
253
}
254
q0 = v_max(q0, v_setzero_s16() - q1);
255
threshold = v_reduce_max(q0) - 1;
256
}
257
else
258
#endif
259
{
260
int a0 = threshold;
261
for( k = 0; k < 12; k += 2 )
262
{
263
int a = std::min((int)d[k+1], (int)d[k+2]);
264
if( a <= a0 )
265
continue;
266
a = std::min(a, (int)d[k+3]);
267
a = std::min(a, (int)d[k+4]);
268
a = std::min(a, (int)d[k+5]);
269
a = std::min(a, (int)d[k+6]);
270
a0 = std::max(a0, std::min(a, (int)d[k]));
271
a0 = std::max(a0, std::min(a, (int)d[k+7]));
272
}
273
274
int b0 = -a0;
275
for( k = 0; k < 12; k += 2 )
276
{
277
int b = std::max((int)d[k+1], (int)d[k+2]);
278
b = std::max(b, (int)d[k+3]);
279
b = std::max(b, (int)d[k+4]);
280
if( b >= b0 )
281
continue;
282
b = std::max(b, (int)d[k+5]);
283
b = std::max(b, (int)d[k+6]);
284
285
b0 = std::min(b0, std::max(b, (int)d[k]));
286
b0 = std::min(b0, std::max(b, (int)d[k+7]));
287
}
288
289
threshold = -b0-1;
290
}
291
#if VERIFY_CORNERS
292
testCorner(ptr, pixel, K, N, threshold);
293
#endif
294
return threshold;
295
}
296
297
template<>
298
int cornerScore<8>(const uchar* ptr, const int pixel[], int threshold)
299
{
300
const int K = 4, N = K * 3 + 1;
301
int k, v = ptr[0];
302
short d[N];
303
for (k = 0; k < N; k++)
304
d[k] = (short)(v - ptr[pixel[k]]);
305
306
#if CV_SIMD128
307
if (hasSIMD128())
308
{
309
v_int16x8 v0 = v_load(d + 1);
310
v_int16x8 v1 = v_load(d + 2);
311
v_int16x8 a = v_min(v0, v1);
312
v_int16x8 b = v_max(v0, v1);
313
v0 = v_load(d + 3);
314
a = v_min(a, v0);
315
b = v_max(b, v0);
316
v0 = v_load(d + 4);
317
a = v_min(a, v0);
318
b = v_max(b, v0);
319
v0 = v_load(d);
320
v_int16x8 q0 = v_min(a, v0);
321
v_int16x8 q1 = v_max(b, v0);
322
v0 = v_load(d + 5);
323
q0 = v_max(q0, v_min(a, v0));
324
q1 = v_min(q1, v_max(b, v0));
325
q0 = v_max(q0, v_setzero_s16() - q1);
326
threshold = v_reduce_max(q0) - 1;
327
}
328
else
329
#endif
330
{
331
int a0 = threshold;
332
for( k = 0; k < 8; k += 2 )
333
{
334
int a = std::min((int)d[k+1], (int)d[k+2]);
335
if( a <= a0 )
336
continue;
337
a = std::min(a, (int)d[k+3]);
338
a = std::min(a, (int)d[k+4]);
339
a0 = std::max(a0, std::min(a, (int)d[k]));
340
a0 = std::max(a0, std::min(a, (int)d[k+5]));
341
}
342
343
int b0 = -a0;
344
for( k = 0; k < 8; k += 2 )
345
{
346
int b = std::max((int)d[k+1], (int)d[k+2]);
347
b = std::max(b, (int)d[k+3]);
348
if( b >= b0 )
349
continue;
350
b = std::max(b, (int)d[k+4]);
351
352
b0 = std::min(b0, std::max(b, (int)d[k]));
353
b0 = std::min(b0, std::max(b, (int)d[k+5]));
354
}
355
356
threshold = -b0-1;
357
}
358
359
#if VERIFY_CORNERS
360
testCorner(ptr, pixel, K, N, threshold);
361
#endif
362
return threshold;
363
}
364
365
} // namespace cv
366
367