-
Notifications
You must be signed in to change notification settings - Fork 103
/
nonmax_suppression.cxx
161 lines (127 loc) · 4.38 KB
/
nonmax_suppression.cxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <cvd/image_ref.h>
#include <cvd/nonmax_suppression.h>
#include <vector>
using namespace std;
namespace CVD
{
//This function has been moved from fast_corner.cxx. Look there
//for the old ChangeLog.
// fast_nonmax_t is templated so you can have either of:
// 1: A vector of ImageRefs of the nonmax corners
// 2: A vector of <ImageRef, int> pairs of the corners and their scores.
// And
// 1: Non-strict (neighbours of the same score allowed)
// 2: Strict (must be larger than the neighbours)
// It's internal, the user-visible functions instantiate it below..
template<class Score, class ReturnType, class Collector, class Test>
inline void nonmax_suppression_t(const vector<ImageRef>& corners, const vector<Score>& scores, vector<ReturnType>& nonmax_corners)
{
nonmax_corners.clear();
nonmax_corners.reserve(corners.size());
if(corners.size() < 1)
return;
// Find where each row begins
// (the corners are output in raster scan order). A beginning of -1 signifies
// that there are no corners on that row.
int last_row = corners.back().y;
vector<int> row_start(last_row + 1, -1);
int prev_row = -1;
for(unsigned int i=0; i< corners.size(); i++)
if(corners[i].y != prev_row)
{
row_start[corners[i].y] = i;
prev_row = corners[i].y;
}
//Point above points (roughly) to the pixel above the one of interest, if there
//is a feature there.
int point_above = 0;
int point_below = 0;
const int sz = (int)corners.size();
for(int i=0; i < sz; i++)
{
Score score = scores[i];
ImageRef pos = corners[i];
//Check left
if(i > 0)
if(corners[i-1] == pos-ImageRef(1,0) && Test::Compare(scores[i-1], score))
continue;
//Check right
if(i < (sz - 1))
if(corners[i+1] == pos+ImageRef(1,0) && Test::Compare(scores[i+1], score))
continue;
//Check above (if there is a valid row above)
if(pos.y != 0 && row_start[pos.y - 1] != -1)
{
//Make sure that current point_above is one
//row above.
if(corners[point_above].y < pos.y - 1)
point_above = row_start[pos.y-1];
//Make point_above point to the first of the pixels above the current point,
//if it exists.
for(; corners[point_above].y < pos.y && corners[point_above].x < pos.x - 1; point_above++)
{}
for(int i=point_above; corners[i].y < pos.y && corners[i].x <= pos.x + 1; i++)
{
int x = corners[i].x;
if( (x == pos.x - 1 || x ==pos.x || x == pos.x+1) && Test::Compare(scores[i], score))
goto cont;
}
}
//Check below (if there is anything below)
if(pos.y != last_row && row_start[pos.y + 1] != -1 && point_below < sz) //Nothing below
{
if(corners[point_below].y < pos.y + 1)
point_below = row_start[pos.y+1];
// Make point below point to one of the pixels belowthe current point, if it
// exists.
for(; point_below < sz && corners[point_below].y == pos.y+1 && corners[point_below].x < pos.x - 1; point_below++)
{}
for(int i=point_below; i < sz && corners[i].y == pos.y+1 && corners[i].x <= pos.x + 1; i++)
{
int x = corners[i].x;
if( (x == pos.x - 1 || x ==pos.x || x == pos.x+1) && Test::Compare(scores[i],score))
goto cont;
}
}
nonmax_corners.push_back(Collector::collect(corners[i],scores[i]));
cont:
;
}
}
struct Greater
{
static bool Compare(int a, int b)
{
return a > b;
}
};
struct GreaterEqual
{
static bool Compare(int a, int b)
{
return a >= b;
}
};
// The two collectors which either return just the ImageRef or the <ImageRef,int> pair
struct collect_pos
{
static inline ImageRef collect(const ImageRef& pos, int ){return pos;}
};
struct collect_score
{
static inline pair<ImageRef, int> collect(const ImageRef& pos, int score){return make_pair(pos,score);}
};
// The callable functions
void nonmax_suppression_strict(const vector<ImageRef>& corners, const vector<int>& scores, vector<ImageRef>& nonmax_corners)
{
nonmax_suppression_t<int, ImageRef, collect_pos, GreaterEqual>(corners, scores, nonmax_corners);
}
void nonmax_suppression(const vector<ImageRef>& corners, const vector<int>& scores, vector<ImageRef>& nonmax_corners)
{
nonmax_suppression_t<int, ImageRef, collect_pos, Greater>(corners, scores, nonmax_corners);
}
void nonmax_suppression_with_scores(const vector<ImageRef>& corners, const vector<int>& scores, vector<pair<ImageRef,int> >& nonmax_corners)
{
nonmax_suppression_t<int, pair<ImageRef,int> , collect_score, Greater>(corners, scores, nonmax_corners);
}
}