auxiliary
 All Classes Namespaces Files Functions Typedefs Enumerations Enumerator Macros
pyramid.hpp
Go to the documentation of this file.
1 
38 #pragma once
39 
40 #include <armadillo>
41 
42 namespace auxiliary
43 {
45 #ifdef USE_CXX11
46  enum border_type : arma::uword
47 #else
49 #endif
50  {
54  warp,
57  };
58 
65  inline arma::uword borderInterpolate(int p, int n, border_type type = reflect101)
66  {
67  //return (p < 0) ? -p : ((p < n) ? p : (n + n - p - 1));
68  if ((unsigned)p < (unsigned)n) return p;
69 
70  switch (type) {
71  case reflect:
72  case reflect101:
73  {
74  int delta = (type == reflect101);
75 
76  if (n == 1) p = 0;
77 
78  do {
79  if (p < 0)
80  p = -p - 1 + delta;
81  else
82  p = n - 1 - (p - n) - delta;
83  } while ((unsigned)p >= (unsigned)n);
84  }
85  break;
86  case replicate:
87  p = (p < 0) ? 0 : n - 1;
88  break;
89  case warp:
90  if (p < 0)
91  p -= ((p - n + 1) / n) * n;
92  if (p > n)
93  p %= n;
94  break;
95  case constant:
96  p = -1;
97  break;
98  default:
99  break;
100  };
101 
102  return p;
103  }
104 
105 #define castOp(x) ((x + 128) >> 8)
106 
127  template <typename T1, typename T2>
128  void pyrDown(const T1& in, T2& out)
129  {
130  const uword KERNEL_SIZE = 5;
131 
132  //uword width = std::min((src.n_cols - SZ / 2 - 1) / 2;
133 
134  circular_buffer<arma::ivec> cols(KERNEL_SIZE);
135 
136 #ifdef __VXWORKS__
137  ivec dummy(out.n_rows); dummy.zeros();
138 #endif
139  for (arma::uword i = 0 ; i < KERNEL_SIZE ; i++)
140 #ifdef __VXWORKS__
141  cols.push_back(dummy);
142 #else
143  cols.push_back(zeros<ivec>(out.n_rows));
144 #endif
145 
146  int sx0 = -(int)KERNEL_SIZE / 2, sx = sx0;
147 
148  arma::umat tab(KERNEL_SIZE + 2, 2);
149  uword* lptr = tab.colptr(0),
150  * rptr = tab.colptr(1);
151  for (uword y = 0 ; y <= KERNEL_SIZE + 1 ; y++) {
152  lptr[y] = borderInterpolate((int)y + sx0, (int)in.n_rows);
153  rptr[y] = borderInterpolate((int)(y + (out.n_rows - 1) * 2) + sx0, (int)in.n_rows);
154  }
155 
156  // gaussian convolution with
157  for (arma::uword x = 0 ; x < out.n_cols ; x++) {
158  typename T2::elem_type* dst = out.colptr(x);
159 
160  // vertical convolution and decimation
161  for ( ; sx <= (int)x * 2 + 2 ; sx++) {
162  ivec& col = cols.next();
163  int* colptr = col.memptr();
164 
165  // interpolate border
166  const typename T2::elem_type* src = in.colptr(borderInterpolate(sx, (int)in.n_cols));
167 
168  colptr[0] = src[lptr[2]] * 6 + (src[lptr[1]] + src[lptr[3]]) * 4 + (src[lptr[0]] + src[lptr[4]]);
169 
170  for (arma::uword y = 1 ; y < out.n_rows - 1; y++)
171  //concurrency::parallel_for(uword(1), out.n_rows - 1, [&](uword y) {
172  colptr[y] = src[y * 2] * 6 +
173  (src[y * 2 - 1] + src[y * 2 + 1]) * 4 +
174  (src[y * 2 - 2] + src[y * 2 + 2]);
175  //});
176 
177  colptr[out.n_rows - 1] = src[rptr[2]] * 6 +
178  (src[rptr[1]] + src[rptr[3]]) * 4 +
179  (src[rptr[0]] + src[rptr[4]]);
180  }
181 
182  const int* col0 = cols[0].memptr();
183  const int* col1 = cols[1].memptr();
184  const int* col2 = cols[2].memptr();
185  const int* col3 = cols[3].memptr();
186  const int* col4 = cols[4].memptr();
187 
188  // horizontal convolution and decimation
189 #if ENABLE_SSE2
190  //__m128i d = _mm_set1_epi16(128);
191  //uword y = 0;
192  //for ( ; y <= out.n_rows - 16 ; y += 16) {
193  // __m128i c0, c1, c2, c3, c4, t0, t1;
194  // c0 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(col0 + y)),
195  // _mm_load_si128((const __m128i*)(col0 + y + 4)));
196  // c1 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(col1 + y)),
197  // _mm_load_si128((const __m128i*)(col1 + y + 4)));
198  // c2 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(col2 + y)),
199  // _mm_load_si128((const __m128i*)(col2 + y + 4)));
200  // c3 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(col3 + y)),
201  // _mm_load_si128((const __m128i*)(col3 + y + 4)));
202  // c4 = _mm_packs_epi32(_mm_load_si128((const __m128i*)(col4 + y)),
203  // _mm_load_si128((const __m128i*)(col4 + y + 4)));
204 
205  // c0 = _mm_add_epi16(r0, r4);
206  // c1 = _mm_add_epi16(_mm_add_epi16(c1, c3), c2);
207  //}
208 #else
209  for (arma::uword y = 0 ; y < out.n_rows ; y++)
210  //concurrency::parallel_for(uword(0), out.n_rows, [&](uword y) {
211  dst[y] = (typename T2::elem_type)castOp(col2[y] * 6 + (col1[y] + col3[y]) * 4 + col0[y] + col4[y]);
212  //});
213 #endif
214  }
215  }
216 }
arma::uword borderInterpolate(int p, int n, border_type type=reflect101)
Computes the location of an extrapolated pixel.
Definition: pyramid.hpp:65
void pyrDown(const T1 &in, T2 &out)
Blurs an image and downsamples it. This function performs the downsampling step of the Gaussian pyra...
Definition: pyramid.hpp:128
dcb | abcde | dcb
Definition: pyramid.hpp:55
#define castOp(x)
Definition: pyramid.hpp:105
cde | abcde | abc
Definition: pyramid.hpp:54
border_type
Various border types, image boundaries are denoted with &#39;|&#39;.
Definition: pyramid.hpp:48
A minimal implementation of circular buffer class.
Definition: circular_buffer.hpp:45
iii | abcde | iii with some specified &#39;i&#39;
Definition: pyramid.hpp:51
reference next()
Get next element in the circular buffer.
Definition: circular_buffer.hpp:55
aaa | abcde | eee
Definition: pyramid.hpp:53
not specified
Definition: pyramid.hpp:56
cba | abcde | edc
Definition: pyramid.hpp:52
void push_back(const value_type &item)
Add new last element.
Definition: circular_buffer.hpp:64