DGtal  0.6.devel
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ReverseDistanceTransformation.ih
1 
30 
31 #include <cstdlib>
32 #include <boost/lexical_cast.hpp>
34 
36 // IMPLEMENTATION of inline methods.
38 
40 // ----------------------- Standard services ------------------------------
41 
45 template <typename I, DGtal::uint32_t p, typename IntShort>
46 inline
48  const IntShort defaultBackground):
49  myForegroundValue(defaultForeground),
50  myBackgroundValue(defaultBackground)
51 {
52 }
53 
58 template <typename I, DGtal::uint32_t p, typename IntShort>
59 inline
61 {
62 }
63 
64 
65 template <typename I, DGtal::uint32_t p, typename IntShort>
66 inline
69 {
70  //We copy the image extent.
71  myLowerBoundCopy = Point(); //(O,O,...O)
72  myUpperBoundCopy = aImage.domain().upperBound() - aImage.domain().lowerBound();
73  myDisplacementVector = aImage.domain().lowerBound();
74  myExtent = myUpperBoundCopy - myLowerBoundCopy;
75 
77  I output ( typename I::Domain(myLowerBoundCopy, myUpperBoundCopy));
78  I swap ( typename I::Domain(myLowerBoundCopy, myUpperBoundCopy));
79 
80  bool isSwap = reconstructionInternal(aImage,output,swap);
81 
82  if ( !isSwap )
83  {
84  //swap.translateDomain(myDisplacementVector);
85  return castValues(swap);
86  }
87  else
88  {
89  //output.translateDomain(myDisplacementVector);
90  return castValues(output);
91  }
92 }
93 
94 template <typename I, DGtal::uint32_t p, typename IntShort>
95 template <typename Set>
96 inline
97 void
99 {
101  //BOOST_CONCEPT_ASSERT(( CDigitalSet<Set> ));
102 
103  //We copy the image extent and translate the image domains to (0,..0)x(Upper-Lower)
104  myLowerBoundCopy = Point(); //(O,O,...O)
105  myUpperBoundCopy = aImage.domain().upperBound() - aImage.domain().lowerBound();
106  myDisplacementVector = aImage.domain().lowerBound();
107  myExtent = myUpperBoundCopy - myLowerBoundCopy;
108 
109  typename I::Domain domain(myLowerBoundCopy,myUpperBoundCopy);
110 
111  I output ( typename I::Domain(myLowerBoundCopy, myUpperBoundCopy ));
112  I swap ( typename I::Domain( myLowerBoundCopy, myUpperBoundCopy ));
113 
114  bool isSwap = reconstructionInternal(aImage,output,swap);
115 
116  for(typename I::Domain::ConstIterator it=domain.begin(),
117  itend = domain.end();
118  it != itend;
119  ++it)
120  if (isSwap)
121  {
122  if ( output(*it) > 0)
123  aSet.insertNew((*it) + myDisplacementVector);
124  }
125  else
126  {
127  if ( swap(*it) > 0)
128  aSet.insertNew((*it) + myDisplacementVector);
129  }
130 }
131 
132 
133 template <typename I, DGtal::uint32_t p, typename IntShort>
134 inline
135 bool
137 {
138 
139  //We copy input image (implicit translation of values)
140  typename I::Iterator ito=output.begin();
141 
142  for(typename I::ConstIterator it=aImage.begin(), itend = aImage.end();
143  it != itend;
144  ++it,++ito)
145  (*ito) = (*it);
146 
147  bool isSwap = true;
148 
149  //We process the dimensions swaping the temporary buffers
150  for ( Dimension dim = 0; dim < I::dimension ; dim++ )
151  {
152  if ( isSwap )
153  computeSteps ( output, swap, dim );
154  else
155  computeSteps ( swap, output, dim );
156 
157  isSwap = !isSwap;
158  }
159 
160  return isSwap;
161 }
162 
163 
164 
165 
166 template <typename I, DGtal::uint32_t p, typename IntShort>
167 inline
170 {
171  //We threshold input values
172  OutputImage output(typename OutputImage::Domain(myLowerBoundCopy, myUpperBoundCopy));
173  typename OutputImage::Iterator ito = output.begin();
174  for(typename I::ConstIterator it=input.begin(),
175  itend = input.end();
176  it != itend;
177  ++it,++ito)
178  if ( (*it) > 0)
179  (*ito) = myForegroundValue;
180  else
181  (*ito) = myBackgroundValue;
182  return output;
183 }
184 
185 
186 
187 template <typename I, DGtal::uint32_t p, typename IntShort>
188 inline
189 void
191  I &output,
192  const Dimension dim) const
193 {
194  std::string title = "RDT dimension " + boost::lexical_cast<string>( dim ); ;
195  trace.beginBlock ( title );
196 
197  typedef typename Domain::ConstSubRange::ConstIterator ConstDomIt;
198 
199  //We setup the subdomain iterator
200  //the iterator will scan dimension using the order:
201  // {n-1, n-2, ... 1} (we skip the '0' dimension.
202 
203  std::vector<Size> subdomain;
204  subdomain.reserve(I::dimension - 1);
205  for (unsigned int k = 0; k < I::dimension ; k++)
206  if ( (I::dimension - 1 - k) != dim)
207  subdomain.push_back( I::dimension - 1 - k );
208 
209  Domain localDomain(myLowerBoundCopy, myUpperBoundCopy);
210  Size maxSize = myExtent.normInfinity();
211 
212  //Stacks used in the envelope computation
213  Integer *s = new Integer[maxSize+1];
214  Integer *t = new Integer[maxSize+1];
215 
216  ASSERT( s != NULL);
217  ASSERT( t != NULL);
218 
219  //We process the dimensions to construct a Point
220  for (ConstDomIt it = localDomain.subRange( subdomain ).begin(),
221  itend = localDomain.subRange( subdomain ).end(); it != itend; ++it)
222  {
223  computeSteps1D ( input, output, (*it), dim, s, t );
224  }
225 
226  delete[] s;
227  delete[] t;
228 
229  trace.endBlock();
230 
231 }
232 
235 template <typename I, DGtal::uint32_t p, typename IntShort>
236 void
238  I & output,
239  const Point &startingPoint,
240  const Size dim,
241  Integer s[],
242  Integer t[] ) const
243 {
244  Coordinate w;
245  Coordinate q = 0;
246 
247  Point sQ = startingPoint;
248  Point pU = startingPoint;
249 
250  //trace.info()<<endl<<"Enter startingPoint="<<startingPoint<<endl;
251 
252  //init of the stack structure
253  pU[dim] = myLowerBoundCopy[dim];
254  while ((pU[dim] <= myUpperBoundCopy[dim])
255  && (input ( pU ) == 0))
256  pU[dim] ++;
257 
258  if ( pU[dim] > myUpperBoundCopy[dim] )
259  {
260  for(typename I::SpanIterator it= output.spanBegin(startingPoint,dim),
261  itend=output.spanEnd(startingPoint,dim);
262  it != itend; ++it)
263  output.setValue(it, 0);
264  return;
265  }
266 
267  q = 0;
268  s[q] = pU[dim];
269  sQ[dim] = s[q];
270  t[q] = myLowerBoundCopy[dim];
271 
272  //Forward Scan
273 
274  for ( int u = pU[dim] + 1; u <= myUpperBoundCopy[dim] ; u++ )
275  {
276  pU[ dim ] = u;
277  if ( input( pU ) == 0 )
278  {
279  //trace.info() << "Ctd " << pU ;
280  continue;
281  }
282 
283  while ( ( q >= 0 ) &&
284  ( myMetric.reversedF ( t[q], s[q], (const int)input ( sQ ) ) <
285  myMetric.reversedF ( t[q], u, (const int)input ( pU ) ) ) )
286  {
287  q--;
289  if (q>=0)
290  sQ[dim] = s[q];
291  }
292 
293  if ( q < 0 )
294  {
295  q = 0;
296  s[0] = u;
297  t[0] = myLowerBoundCopy[dim];
298  sQ[dim] = u;
299  }
300  else
301  {
302  sQ[dim] = s[q];
303  w = 1 + myMetric.reversedSep ( s[q],
304  (const int)input ( sQ ),
305  u,
306  (const int)input ( pU ) );
307 
308  if (( w <= myUpperBoundCopy[dim] ) && (w>= myLowerBoundCopy[dim]))
309  {
310  q++;
311  s[q] = u;
312  sQ[dim] = u;
313  t[q] = w;
314  }
315  }
316  }
317 
318  Point last = startingPoint;
319 
320  ASSERT(q>=0);
321 
322  //Backward Scan
323  for (last[dim] = myUpperBoundCopy[dim];
324  last[dim] >= myLowerBoundCopy[dim] ;
325  last[dim]-- )
326  {
327  if (myMetric.reversedF ( last[dim] , s[q], (const int)input ( sQ )) > 0 )
328  output.setValue ( last, myMetric.reversedF ( last[dim] , s[q], (const int)input ( sQ ) ) );
329  else
330  output.setValue ( last, 0 );
331 
332  if (( last[dim] == t[q] ) && (q > 0))
333  {
334  q--;
335  sQ[dim] = s[q];
336  }
337  }
338 }
339 
340 
341 // //
343 
344