Main MRPT website > C++ reference for MRPT 1.9.9
faster_corner_12.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 // ---------------------------------------------------------------------------
11 // LICENSING: This file is a slightly-modified version of part of libcvd,
12 // released under LGPL 2.1 by Edward Rosten
13 // ---------------------------------------------------------------------------
14 
15 #include <mrpt/utils/utils_defs.h>
16 #include <mrpt/system/memory.h>
18 
19 #include <mrpt/utils/SSE_types.h>
21 #include "corner_12.h"
22 
23 using namespace std;
24 using namespace mrpt;
25 using namespace mrpt::utils;
26 
27 template <int I, int N>
28 struct BitCheck
29 {
30  template <class C>
31  static inline void eval(
32  unsigned int three, const uint8_t* p, const int w, const int barrier,
33  C& corners)
34  {
35  const int BIT = 1 << I;
36  if (three & BIT)
37  {
38  if (three & (BIT << 16))
39  {
40  if (is_corner_12<Greater>(p, w, barrier)) corners.push_back(p);
41  }
42  else
43  {
44  if (is_corner_12<Less>(p, w, barrier)) corners.push_back(p);
45  }
46  }
47  BitCheck<I + 1, N>::eval(three, p + 1, w, barrier, corners);
48  }
49 };
50 
51 template <int N>
52 struct BitCheck<N, N>
53 {
54  template <class C>
55  static inline void eval(
56  unsigned int, const uint8_t*, const int, const int, C&)
57  {
58  }
59 };
60 
61 template <int CHUNKS, class C>
62 inline void process_16(
63  unsigned int three, const uint8_t* p, const int w, const int barrier,
64  C& corners)
65 {
66  three |= (three >> 16);
67  const int BITS = 16 / CHUNKS;
68  const int mask = ((1 << BITS) - 1);
69  for (int i = 0; i < CHUNKS; ++i)
70  {
71  if (three & mask)
72  BitCheck<0, BITS>::eval(three, p, w, barrier, corners);
73  p += BITS;
74  three >>= BITS;
75  }
76 }
77 
78 #if MRPT_HAS_SSE2 && MRPT_HAS_OPENCV
79 
80 template <bool Aligned>
82  const IplImage* I, mrpt::vision::TSimpleFeatureList& corners, int barrier,
83  uint8_t octave, std::vector<size_t>* out_feats_index_by_row)
84 {
85  corners.reserve(corners.size() + 500);
86  // corners.mark_kdtree_as_outdated();
87 
88  size_t *ptr_feat_index_by_row, *ptr_feat_index_end;
89  if (out_feats_index_by_row)
90  {
91  out_feats_index_by_row->resize(I->height);
92  ptr_feat_index_by_row = &(*out_feats_index_by_row)[0];
93  ptr_feat_index_end =
94  ptr_feat_index_by_row + out_feats_index_by_row->size();
95  }
96  else
97  {
98  ptr_feat_index_by_row = nullptr;
99  ptr_feat_index_end = nullptr;
100  }
101 
102  const int w = I->width;
103  const int stride = 3 * I->widthStep; // 3*w;
104  typedef std::list<const uint8_t*> Passed;
105  Passed passed;
106 
107  // The compiler refuses to reserve a register for this,
108  // even though xmm6 and xmm7 go unused.
109  // It loads it from memory each time. I am stymied.
110  const __m128i barriers = _mm_set1_epi8((uint8_t)barrier);
111 
112  for (int i = 3; i < I->height - 3; ++i)
113  {
114  const uint8_t* p =
115  (const uint8_t*)I->imageData + I->widthStep * i; // I[i];
116  for (int j = 0; j < w / 16; ++j, p += 16)
117  {
118  __m128i lo, hi;
119  {
120  const __m128i here = load_si128<Aligned>((const __m128i*)(p));
121  lo = _mm_subs_epu8(here, barriers);
122  hi = _mm_adds_epu8(barriers, here);
123  }
124  const __m128i above =
125  load_si128<Aligned>((const __m128i*)(p - stride));
126  const __m128i below =
127  load_si128<Aligned>((const __m128i*)(p + stride));
128  unsigned int up_flags, down_flags;
129  CHECK_BARRIER(lo, hi, above, up_flags);
130  CHECK_BARRIER(lo, hi, below, down_flags);
131  const unsigned int either_ud = up_flags | down_flags;
132  if (either_ud)
133  {
134  unsigned int left_flags;
135  {
136  const __m128i other =
137  _mm_loadu_si128((const __m128i*)(p - 3));
138  CHECK_BARRIER(lo, hi, other, left_flags);
139  }
140  const unsigned int both_ud = up_flags & down_flags;
141  if (both_ud | (either_ud & left_flags))
142  {
143  unsigned int right_flags;
144  {
145  const __m128i other =
146  _mm_loadu_si128((const __m128i*)(p + 3));
147  CHECK_BARRIER(lo, hi, other, right_flags);
148  }
149  const unsigned int at_least_three =
150  (either_ud & (left_flags & right_flags)) |
151  (both_ud & (left_flags | right_flags));
152  if (at_least_three)
153  {
154  process_16<4>(at_least_three, p, w, barrier, passed);
155  }
156  }
157  }
158  }
159 
160  // Do the edge of the row, using the old-fasioned 4 point test
161  for (int j = (w / 16) * 16; j < w - 3; j++, p++)
162  {
163  int cb = *p + barrier;
164  int c_b = *p - barrier;
165  int num_above = (p[stride] > cb) + (p[-stride] > cb);
166  int num_below = (p[stride] < c_b) + (p[-stride] < c_b);
167 
168  if (!num_above && !num_below) continue;
169 
170  // Look left
171  num_above += p[-3] > cb;
172  num_below += p[-3] < c_b;
173 
174  if (num_above & 2) // num_above is 2 or 3
175  {
176  if (!(num_above & 1)) // num_above is 2
177  num_above += p[3] > cb;
178 
179  // Only do a complete check if num_above is 3
180  if ((num_above & 1) && is_corner_12<Greater>(p, w, barrier))
181  passed.push_back(p);
182  }
183  else if (num_below & 2)
184  {
185  if (!(num_below & 1)) num_below += p[3] < c_b;
186 
187  if ((num_below & 1) && is_corner_12<Less>(p, w, barrier))
188  passed.push_back(p);
189  }
190  }
191 
192  passed.push_back(0);
193  }
194 
195  // 3 first rows have no features:
196  if (ptr_feat_index_by_row)
197  {
198  *ptr_feat_index_by_row++ = corners.size();
199  *ptr_feat_index_by_row++ = corners.size();
200  *ptr_feat_index_by_row++ = corners.size();
201  }
202 
203  int row = 3;
204 
205  const uint8_t* row_start = (const uint8_t*)I->imageData + I->widthStep * 3;
206  for (Passed::iterator it = passed.begin(); it != passed.end(); ++it)
207  {
208  if (*it == 0)
209  {
210  // next row:
211  if (ptr_feat_index_by_row) // save index by row:
212  *ptr_feat_index_by_row++ = corners.size();
213 
214  row_start = (const uint8_t*)I->imageData +
215  I->widthStep * (++row); // I[++row];
216  continue;
217  }
218  int x = *it - row_start;
219  if (x > 2 && x < w - 3)
220  corners.push_back_fast(x << octave, row << octave);
221  }
222 
223  // 3 last rows have no features:
224  if (ptr_feat_index_by_row)
225  {
226  *ptr_feat_index_by_row++ = corners.size();
227  *ptr_feat_index_by_row++ = corners.size();
228  *ptr_feat_index_by_row++ = corners.size();
229  ASSERT_(ptr_feat_index_by_row == ptr_feat_index_end)
230  }
231 }
232 
233 #endif // MRPT_HAS_SSE2 && MRPT_HAS_OPENCV
234 
235 #if MRPT_HAS_OPENCV
236 
238  const IplImage* I, mrpt::vision::TSimpleFeatureList& corners, int barrier,
239  uint8_t octave, std::vector<size_t>* out_feats_index_by_row)
240 {
241  if (I->width < 22)
242  {
244  I, corners, barrier, octave, out_feats_index_by_row);
245  return;
246  }
247  else if (I->width < 22 || I->height < 7)
248  return;
249 
250 #if MRPT_HAS_SSE2
251  if (mrpt::system::is_aligned<16>(I->imageData) &&
252  mrpt::system::is_aligned<16>(I->imageData + I->widthStep))
253  faster_corner_detect_12<true>(
254  I, corners, barrier, octave, out_feats_index_by_row);
255  else
256  faster_corner_detect_12<false>(
257  I, corners, barrier, octave, out_feats_index_by_row);
258 #else
260  I, corners, barrier, octave, out_feats_index_by_row);
261 #endif
262 }
263 #endif
bool is_aligned< 16 >(const void *ptr)
Definition: memory.h:126
GLenum GLint GLuint mask
Definition: glext.h:4050
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
void fast_corner_detect_12(const IplImage *I, mrpt::vision::TSimpleFeatureList &corners, int barrier, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
void fast_corner_detect_plain_12(const IplImage *i, TSimpleFeatureList &corners, int b, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
Scalar * iterator
Definition: eigen_plugins.h:26
static void eval(unsigned int three, const uint8_t *p, const int w, const int barrier, C &corners)
for(ctr=DCTSIZE;ctr > 0;ctr--)
Definition: jidctflt.cpp:56
STL namespace.
#define CHECK_BARRIER(lo, hi, other, flags)
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:4178
unsigned char uint8_t
Definition: rptypes.h:41
GLsizei stride
Definition: glext.h:3825
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
static void eval(unsigned int, const uint8_t *, const int, const int, C &)
GLenum GLenum GLvoid * row
Definition: glext.h:3576
void faster_corner_detect_12(const IplImage *I, mrpt::vision::TSimpleFeatureList &corners, int barrier, uint8_t octave, std::vector< size_t > *out_feats_index_by_row)
#define ASSERT_(f)
GLenum GLint x
Definition: glext.h:3538
GLfloat GLfloat p
Definition: glext.h:6305
void process_16(unsigned int three, const uint8_t *p, const int w, const int barrier, C &corners)



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019