iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RangeOpsImpl.H
Go to the documentation of this file.
1 /*! @file
2  @author Randolph Voorhies
3  @copyright GNU Public License (GPL v3)
4  @section License
5  @verbatim
6  // ////////////////////////////////////////////////////////////////////////
7  // The iLab Neuromorphic Robotics Toolkit (NRT) //
8  // Copyright 2010-2012 by the University of Southern California (USC) //
9  // and the iLab at USC. //
10  // //
11  // iLab - University of Southern California //
12  // Hedco Neurociences Building, Room HNB-10 //
13  // Los Angeles, Ca 90089-2520 - USA //
14  // //
15  // See http://ilab.usc.edu for information about this project. //
16  // ////////////////////////////////////////////////////////////////////////
17  // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18  // //
19  // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20  // redistribute it and/or modify it under the terms of the GNU General //
21  // Public License as published by the Free Software Foundation, either //
22  // version 3 of the License, or (at your option) any later version. //
23  // //
24  // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25  // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26  // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27  // PURPOSE. See the GNU General Public License for more details. //
28  // //
29  // You should have received a copy of the GNU General Public License //
30  // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31  // <http://www.gnu.org/licenses/>. //
32  // ////////////////////////////////////////////////////////////////////////
33  @endverbatim */
34 
35 
37 
38 template <class PixType>
40 {
41  assert(a.size() > 0);
42 
43  nrt::Dims<int> dims = a.dims();
44 
45  if (size * 2 > dims.width()) size = dims.width() / 2;
46  if (size * 2 > dims.height()) size = dims.height() / 2;
47  if (size < 1) return; // forget it
48 
49  float increment = 1.0 / (float)(size + 1);
50  // top lines:
51  float coeff = increment;
52  typename nrt::Image<PixType>::iterator aptr = a.begin();
53  for (int y = 0; y < size; ++ y)
54  {
55  for (int x = 0; x < dims.width(); ++ x)
56  {
57  *aptr = (PixType)( (*aptr) * coeff );
58  ++aptr;
59  }
60  coeff += increment;
61  }
62  // normal lines: start again from beginning to attenuate corners twice:
63  aptr = a.begin();
64  for (int y = 0; y < dims.height(); ++ y)
65  {
66  coeff = increment;
67  for (int x = 0; x < size; ++ x)
68  {
69  *(aptr + dims.width() - 1 - x * 2) =
70  (PixType)(*(aptr + dims.width() - 1 - x * 2) * coeff);
71 
72  *aptr = (PixType)( (*aptr) * coeff );
73  ++aptr;
74  coeff += increment;
75  }
76  aptr += dims.width() - size;
77  }
78  // bottom lines
79  aptr = a.begin() + (dims.height() - size) * dims.width();
80  coeff = increment * (float)size;
81  for (int y = dims.height() - size; y < dims.height(); ++ y)
82  {
83  for (int x = 0; x < dims.width(); ++ x)
84  {
85  *aptr = (PixType)( (*aptr) * coeff );
86  ++aptr;
87  }
88  coeff -= increment;
89  }
90 }
91 
92 // ######################################################################
93 template <class PixType>
95 {
96  PixType zero = PixType(0);
97  for (PixType & pix : dst) if (pix < zero) pix = zero;
98 }
99 
100 // ######################################################################
101 // ######################################################################
102 template <class PixType>
103 void nrt::inplaceNormalize(nrt::Image<PixType> & dst, PixType const & mi, PixType const & ma)
104 {
105  PixType oldmin, oldmax;
106  inplaceNormalize(dst, mi, ma, oldmin, oldmax);
107 }
108 
109 // ######################################################################
110 template <class PixType>
111 void nrt::inplaceNormalize(nrt::Image<PixType> & dst, PixType const & mi, PixType const & ma,
112  PixType & oldmi, PixType & oldma)
113 {
114  if (dst.size() == 0) return;
115 
116  typedef typename nrt::promote<PixType, float>::type TF;
117  nrt::Range<PixType> oldr = dst.range(); oldmi = oldr.min(); oldma = oldr.max();
118 
119  // check if the original range is empty; NOTE: don't try to check (oldma-oldmi)==0.0 here, because that will fail if
120  // oldmin=inf and oldmax=inf, since inf-inf=nan, whereas a test of inf==inf will still yield true
121  if (oldma == oldmi) {
122  // OK, the input image was uniform, so let's just change it to be uniform at the min of the desired new scale.
123 
124  // NOTE: Another sensible approach in this case might be to set the new image to the midpoint of the new range,
125  // but this causes backward-compatibility problems, particularly in cases where we expect input images containing
126  // all 0's to stay at 0 rather than shifting to a higher non-zero value after rescaling.
127  dst.clear(mi);
128  return;
129  }
130 
131  TF const scale = (TF(ma) - TF(mi)) / (TF(oldma) - TF(oldmi));
132  TF const oldminf = TF(oldmi);
133 
134  for (PixType & pix : dst) pix = PixType( mi + (TF(pix) - oldminf) * scale );
135 }
136 
137 // ######################################################################
138 template <NRT_PROMOTE_PIX_NO_DEFAULT>
139 nrt::Image<DestType> const nrt::normalize(nrt::Image<PixType> const src, DestType const & mi, DestType const & ma)
140 {
141  PixType oldmi, oldma;
142  return normalize<promo>(src, mi, ma, oldmi, oldma);
143 }
144 
145 // ######################################################################
146 template <NRT_PROMOTE_PIX_NO_DEFAULT>
147 nrt::Image<DestType> nrt::normalize(nrt::Image<PixType> const src, DestType const & mi, DestType const & ma,
148  PixType & oldmi, PixType & oldma)
149 {
150  if (src.size() == 0) return nrt::Image<DestType>();
151 
152  // Even though we get a promoted DestType here, we need at least float capability to internally do our divisions, so
153  // we will promote possibly even higher internally and then convert back to DestType when we store a pixel's result:
154  typedef typename nrt::promote<DestType, float>::type TF;
155 
156  nrt::Range<PixType> oldr = src.range(); oldmi = oldr.min(); oldma = oldr.max();
157 
158  // check if the original range is empty; NOTE: don't try to check (oldma-oldmi)==0.0 here, because that will fail if
159  // oldmin=inf and oldmax=inf, since inf-inf=nan, whereas a test of inf==inf will still yield true
160  if (oldma == oldmi) {
161  // OK, the input image was uniform, so let's just change it to be uniform at the min of the desired new scale.
162 
163  // NOTE: Another sensible approach in this case might be to set the new image to the midpoint of the new range,
164  // but this causes backward-compatibility problems, particularly in cases where we expect input images containing
165  // all 0's to stay at 0 rather than shifting to a higher non-zero value after rescaling.
166  return nrt::Image<DestType>(src.dims(), DestType(mi));
167  }
168 
169  TF const scale = (TF(ma) - TF(mi)) / (TF(oldma) - TF(oldmi));
170  TF const oldminf = TF(oldmi), mif = TF(mi);
171 
173 
174  std::transform(src.begin(), src.end(), dest.begin(),
175  [&mif,&scale,&oldminf](PixType const & pix) { return DestType(mif + (TF(pix) - oldminf) * scale); } );
176  return dest;
177 }
178 
179 // ######################################################################
180 namespace
181 {
182  template <typename promo>
183  struct NormalizeVisitor : public boost::static_visitor<nrt::GenericImage const>
184  {
185  inline NormalizeVisitor(double const & mi_, double const & ma_) : mi(mi_), ma(ma_) { }
186 
187  template <class PixType> inline
188  nrt::GenericImage const operator()(nrt::Image<PixType> const im) const
189  {
190  typedef typename nrt::promote<PixType, promo>::type DestType;
191  return nrt::GenericImage(nrt::normalize<promo>(im, DestType(mi), DestType(ma)));
192  }
193 
194  private:
195  double const mi, ma;
196  };
197 }
198 
199 template <typename promo>
200 nrt::GenericImage const nrt::normalize(nrt::GenericImage const src, double const & mi, double const & ma)
201 { return src.apply_visitor(NormalizeVisitor<promo>(mi, ma)); }
202 
203 // ######################################################################
204 template <NRT_PROMOTE_PIX_NO_DEFAULT>
206 {
208  DestType const zero(0);
209 
210  DestType const m = DestType(nrt::mean(ret)); // or clamped_convert??
211  if (m != zero) ret -= m;
212 
213  DestType const v = DestType(nrt::variance(ret));
214  if (v!= zero) ret /= v;
215 
216  return ret;
217 }
218 
219 // ######################################################################
220 template <class PixType>
222 {
223  PixType const zero(0);
224 
225  PixType const m = PixType(nrt::mean(src));
226  if (m != zero) src -= m;
227 
228  PixType const v = PixType(nrt::variance(src));
229  if (v != zero) src /= v;
230 }
231