SMIL  1.0.4
DMorphoHierarQ.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _D_MORPHO_HIERARQ_HPP
31 #define _D_MORPHO_HIERARQ_HPP
32 
33 #include <queue>
34 #include <deque>
35 
36 #include "Core/include/private/DTypes.hpp"
37 #include "Morpho/include/DStructuringElement.h"
38 
39 namespace smil
40 {
47  enum HQ_STATUS { HQ_CANDIDATE, HQ_QUEUED, HQ_LABELED, HQ_WS_LINE, HQ_FINAL };
48 
52  template <class T> class FIFO_Queue
53  {
54  public:
55  FIFO_Queue(size_t newSize = 0)
56  {
57  data = NULL;
58  if (newSize)
59  initialize(newSize);
60  }
61  virtual ~FIFO_Queue()
62  {
63  if (data)
64  delete[] data;
65  }
66 
67  void reset()
68  {
69  if (data)
70  delete[] data;
71  data = NULL;
72  _size = realSize = 0;
73  }
74  void initialize(size_t newSize)
75  {
76  reset();
77  realSize = max(newSize + 1, size_t(8)); // Avoid to have to small buffer
78  data = new T[realSize];
79  _size = 0;
80  first = 0;
81  last = 0;
82  }
83  inline size_t size()
84  {
85  return _size;
86  }
87  void swap()
88  {
89  memmove(data, data + first, (last - first) * sizeof(T));
90  first = 0;
91  last = _size;
92  }
93  void push(T val)
94  {
95  if (last == realSize)
96  swap();
97  data[last++] = val;
98  _size++;
99  }
100  inline T front()
101  {
102  return data[first];
103  }
104  inline void pop()
105  {
106  _size--;
107  first++;
108  }
109 
110  static const bool preallocate = true;
111 
112  protected:
113  size_t _size;
114  size_t realSize;
115  size_t first;
116  size_t last;
117  T *data;
118  };
119 
120  template <class TokenType = size_t> class STD_Queue : public queue<TokenType>
121  {
122  public:
123  // Dummy constructor for compatibilty with FIFO_Queue one
124  STD_Queue(size_t /*newSize*/ = 0) : queue<TokenType>()
125  {
126  }
127  static const bool preallocate = false;
128  };
129 
130  template <class TokenType = size_t> class STD_Stack : public stack<TokenType>
131  {
132  public:
133  // Dummy operator for compatibility with other containers from smil
134  inline TokenType front()
135  {
136  return this->top();
137  }
138  };
139 
140  template <class T, class TokenType = size_t,
141  class StackType = STD_Queue<TokenType> >
143  {
144  private:
145  size_t GRAY_LEVEL_NBR;
146  size_t GRAY_LEVEL_MIN;
147  size_t GRAY_LEVEL_MAX;
148  StackType **stacks;
149  size_t *tokenNbr;
150  size_t size;
151  size_t higherLevel;
152 
153  bool initialized;
154  const bool reverseOrder;
155 
156  public:
157  HierarchicalQueue(bool rOrder = false) : reverseOrder(rOrder)
158  {
159  stacks = NULL;
160  tokenNbr = NULL;
161  initialized = false;
162  }
164  {
165  reset();
166  delete[] stacks;
167  delete[] tokenNbr;
168  }
169 
170  void reset()
171  {
172  if (!initialized)
173  return;
174 
175  for (size_t i = 0; i < GRAY_LEVEL_NBR; i++) {
176  if (stacks[i]) {
177  delete stacks[i];
178  stacks[i] = NULL;
179  }
180  }
181 
182  initialized = false;
183  }
184 
185  void initialize(const Image<T> &img)
186  {
187  if (initialized)
188  reset();
189 
190  // vector<T> rVals = rangeVal(img);
191 
192  GRAY_LEVEL_MIN = ImDtTypes<T>::min();
193  GRAY_LEVEL_MAX = ImDtTypes<T>::max();
194  GRAY_LEVEL_NBR = ImDtTypes<T>::cardinal();
195 
196  stacks = new StackType *[GRAY_LEVEL_NBR]();
197  tokenNbr = new size_t[GRAY_LEVEL_NBR];
198 
199  if (StackType::preallocate) {
200  size_t *h = new size_t[GRAY_LEVEL_NBR];
201  histogram(img, h);
202 
203  for (size_t i = 0; i < GRAY_LEVEL_NBR; i++) {
204  if (h[i] != 0)
205  stacks[i] = new StackType(h[i]);
206  else
207  stacks[i] = NULL;
208  }
209 
210  delete[] h;
211  } else {
212  for (size_t i = 0; i < GRAY_LEVEL_NBR; i++)
213  stacks[i] = new StackType();
214  }
215 
216  memset(tokenNbr, 0, GRAY_LEVEL_NBR * sizeof(size_t));
217  size = 0;
218 
219  if (reverseOrder)
220  higherLevel = 0;
221  else
222  higherLevel = ImDtTypes<T>::max();
223 
224  initialized = true;
225  }
226 
227  inline size_t getSize()
228  {
229  return size;
230  }
231 
232  inline bool isEmpty()
233  {
234  return size == 0;
235  }
236 
237  inline size_t getHigherLevel()
238  {
239  return GRAY_LEVEL_MIN + higherLevel;
240  }
241 
242  inline void push(T value, TokenType dOffset)
243  {
244  size_t level = size_t(value) - GRAY_LEVEL_MIN;
245  if (reverseOrder) {
246  if (level > higherLevel)
247  higherLevel = level;
248  } else {
249  if (level < higherLevel)
250  higherLevel = level;
251  }
252  stacks[level]->push(dOffset);
253  tokenNbr[level]++;
254  size++;
255  }
256 
257  inline void findNewReferenceLevel()
258  {
259  // XXX JOE - there still may be a problem here...
260  // it was ImDtTypes<T>::max()
261  if (reverseOrder) {
262  for (size_t i = higherLevel - 1; i != GRAY_LEVEL_MAX; i--) {
263  if (tokenNbr[i] > 0) {
264  higherLevel = i;
265  break;
266  }
267  }
268  } else {
269  for (size_t i = higherLevel + 1; i < GRAY_LEVEL_NBR; i++) {
270  if (tokenNbr[i] > 0) {
271  higherLevel = i;
272  break;
273  }
274  }
275  }
276  }
277 
278  inline TokenType pop()
279  {
280  size_t hlSize = tokenNbr[higherLevel];
281  TokenType dOffset = stacks[higherLevel]->front();
282  stacks[higherLevel]->pop();
283  size--;
284 
285  if (hlSize > 1) {
286  tokenNbr[higherLevel]--;
287  } else {
288  if (size > 0) {
289  // Find new ref level (non empty stack)
290  tokenNbr[higherLevel] = 0;
291  findNewReferenceLevel();
292  } else {
293  // Empty -> re-initilize
294  tokenNbr[higherLevel] = 0;
295  if (reverseOrder)
296  higherLevel = 0;
297  else
298  higherLevel = ImDtTypes<size_t>::max();
299  }
300  }
301  return dOffset;
302  }
303  };
304 
307 } // namespace smil
308 
309 #endif // _D_MORPHO_HIERARQ_HPP
Preallocated FIFO Queue.
Definition: DMorphoHierarQ.hpp:53
Definition: DMorphoHierarQ.hpp:143
Main Image class.
Definition: DImage.hpp:57
Definition: DMorphoHierarQ.hpp:121
Definition: DMorphoHierarQ.hpp:131
histogram(const Image< T > &imIn, size_t *h)
Image histogram.
Definition: DImageHistogram.hpp:64
Definition: DTypes.hpp:88