ITK  4.13.0
Insight Segmentation and Registration Toolkit
itkRankHistogram.h
Go to the documentation of this file.
1 /*=========================================================================
2  *
3  * Copyright Insight Software Consortium
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  *=========================================================================*/
18 // histogram from the moving histogram operations
19 #ifndef itkRankHistogram_h
20 #define itkRankHistogram_h
21 
22 #include "itkIntTypes.h"
23 #include "itkNumericTraits.h"
24 
25 #include <map>
26 #include <vector>
27 
28 namespace itk
29 {
30 namespace Function
31 {
32 
33 /* \class RankHistogram
34  * \brief A simple histogram class hierarchy. One specialization will
35  * be maps, the other vectors.
36  *
37  * This version is intended for keeping track of arbitrary ranks. It
38  * is based on the code from consolidatedMorphology.
39  *
40  * This is a modified version for use with masks. Need to allow for
41  * the situation in which the map is empty.
42  *
43  * This code was contributed in the Insight Journal paper:
44  * "Efficient implementation of kernel filtering"
45  * by Beare R., Lehmann G
46  * https://hdl.handle.net/1926/555
47  * http://www.insight-journal.org/browse/publication/160
48  *
49  * /sa VectorRankHistogram
50  */
51 template< typename TInputPixel >
53 {
54 public:
55 
56  typedef std::less< TInputPixel > Compare;
57 
59  {
60  m_Rank = 0.5;
61  m_Below = m_Entries = 0;
62  // can't set m_RankIt until something has been put in the histogram
63  m_Initialized = false;
66  {
68  }
69  else
70  {
72  }
74  m_RankIt = m_Map.begin(); // equivalent to setting to the initial value
75  }
76 
78  {}
79 
81  {
82  if(this != &hist)
83  {
84  m_Map = hist.m_Map;
85  m_Rank = hist.m_Rank;
86  m_Below = hist.m_Below;
87  m_Entries = hist.m_Entries;
88  m_InitVal = hist.m_InitVal;
89  m_RankValue = hist.m_RankValue;
91  if ( m_Initialized )
92  {
93  m_RankIt = m_Map.find(m_RankValue);
94  }
95  }
96  return *this;
97  }
98 
99  void AddPixel(const TInputPixel & p)
100  {
101  m_Map[p]++;
102  if ( !m_Initialized )
103  {
104  m_Initialized = true;
105  m_RankIt = m_Map.begin();
106  m_Entries = m_Below = 0;
107  m_RankValue = p;
108  }
109  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
110  {
111  ++m_Below;
112  }
113  ++m_Entries;
114  }
115 
116  void RemovePixel(const TInputPixel & p)
117  {
118  m_Map[p]--;
119  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
120  {
121  --m_Below;
122  }
123  --m_Entries;
124  // this is the change that makes this version less efficient. The
125  // simplest approach I can think of with maps, though
126  if ( m_Entries <= 0 )
127  {
128  m_Initialized = false;
129  m_Below = 0;
130  m_Map.clear();
131  }
132  }
133 
134  bool IsValid()
135  {
136  return m_Initialized;
137  }
138 
139  TInputPixel GetValueBruteForce()
140  {
141  SizeValueType count = 0;
142  SizeValueType target = (int)( m_Rank * ( m_Entries - 1 ) ) + 1;
143  for( typename MapType::iterator it=m_Map.begin(); it != m_Map.end(); it++ )
144  {
145  count += it->second;
146  if( count >= target )
147  {
148  return it->first;
149  }
150  }
152  }
153 
154  TInputPixel GetValue(const TInputPixel &)
155  {
156  SizeValueType target = (SizeValueType)( m_Rank * ( m_Entries - 1 ) ) + 1;
157  SizeValueType total = m_Below;
158  SizeValueType ThisBin;
159  bool eraseFlag = false;
160 
161  if ( total < target )
162  {
163  typename MapType::iterator searchIt = m_RankIt;
164  typename MapType::iterator eraseIt;
165 
166  while ( searchIt != m_Map.end() )
167  {
168  // cleaning up the map - probably a better way of organising
169  // the loop. Currently makes sure that the search iterator is
170  // incremented before deleting
171  ++searchIt;
172  ThisBin = searchIt->second;
173  total += ThisBin;
174  if ( eraseFlag )
175  {
176  m_Map.erase(eraseIt);
177  eraseFlag = false;
178  }
179  if ( ThisBin <= 0 )
180  {
181  eraseFlag = true;
182  eraseIt = searchIt;
183  }
184  if ( total >= target )
185  {
186  break;
187  }
188  }
189  if (searchIt == m_Map.end())
190  {
191  --searchIt;
192  }
193  m_RankValue = searchIt->first;
194  m_RankIt = searchIt;
195  }
196  else
197  {
198  typename MapType::iterator searchIt = m_RankIt;
199  typename MapType::iterator eraseIt;
200 
201  while ( searchIt != m_Map.begin() )
202  {
203  ThisBin = searchIt->second;
204  unsigned int tbelow = total - ThisBin;
205  if ( tbelow < target ) // we've overshot
206  {
207  break;
208  }
209  if ( eraseFlag )
210  {
211  m_Map.erase(eraseIt);
212  eraseFlag = false;
213  }
214  if ( ThisBin <= 0 )
215  {
216  eraseIt = searchIt;
217  eraseFlag = true;
218  }
219  total = tbelow;
220 
221  --searchIt;
222  }
223  m_RankValue = searchIt->first;
224  m_RankIt = searchIt;
225  }
226 
227  m_Below = total;
228  itkAssertInDebugAndIgnoreInReleaseMacro( m_RankValue == GetValueBruteForce() );
229  return ( m_RankValue );
230  }
231 
232  void SetRank(float rank)
233  {
234  m_Rank = rank;
235  }
236 
237  void AddBoundary(){}
238 
239  void RemoveBoundary(){}
240 
242  {
243  return false;
244  }
245 
246 protected:
247  float m_Rank;
248 
249 private:
250  typedef typename std::map< TInputPixel, SizeValueType, Compare > MapType;
251 
255  TInputPixel m_RankValue;
256  TInputPixel m_InitVal;
259 
260  // This iterator will point at the desired rank value
261  typename MapType::iterator m_RankIt;
262 };
263 
264 
265 template< typename TInputPixel >
267 {
268 public:
269  typedef std::less< TInputPixel > Compare;
270 
272  {
274  m_Vec.resize(m_Size, 0);
277  {
279  }
280  else
281  {
283  }
284  m_Entries = m_Below = 0;
286  m_Rank = 0.5;
287  }
288 
290 
291  bool IsValid()
292  {
293  return m_Entries > 0;
294  }
295 
296  TInputPixel GetValueBruteForce()
297  {
298  SizeValueType count = 0;
299  SizeValueType target = (SizeValueType)( m_Rank * ( m_Entries - 1 ) ) + 1;
300  for( SizeValueType i=0; i<m_Size; i++ )
301  {
302  count += m_Vec[i];
303  if( count >= target )
304  {
306  }
307  }
309  }
310 
311  TInputPixel GetValue(const TInputPixel &)
312  {
313  return GetValueBruteForce();
314  }
315 
316  void AddPixel(const TInputPixel & p)
317  {
319 
320  m_Vec[q]++;
321  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
322  {
323  ++m_Below;
324  }
325  ++m_Entries;
326  }
327 
328  void RemovePixel(const TInputPixel & p)
329  {
331 
332  itkAssertInDebugAndIgnoreInReleaseMacro( q >= 0 );
333  itkAssertInDebugAndIgnoreInReleaseMacro( q < (int)m_Vec.size() );
334  itkAssertInDebugAndIgnoreInReleaseMacro( m_Entries >= 1 );
335  itkAssertInDebugAndIgnoreInReleaseMacro( m_Vec[q] > 0 );
336 
337  m_Vec[q]--;
338  --m_Entries;
339 
340  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
341  {
342  --m_Below;
343  }
344  }
345 
346  void SetRank(float rank)
347  {
348  m_Rank = rank;
349  }
350 
351  void AddBoundary(){}
352 
353  void RemoveBoundary(){}
354 
356  {
357  return true;
358  }
359 
360 protected:
361  float m_Rank;
362 
363 private:
364  typedef typename std::vector< SizeValueType > VecType;
365 
369  TInputPixel m_RankValue;
370  TInputPixel m_InitVal;
371  int m_Below;
373 };
374 
375 // now create MorphologicalGradientHistogram specilizations using the VectorMorphologicalGradientHistogram
376 // as base class
377 
379 
380 template<>
381 class RankHistogram<unsigned char>:
382  public VectorRankHistogram<unsigned char>
383 {
384 };
385 
386 template<>
387 class RankHistogram<signed char>:
388  public VectorRankHistogram<signed char>
389 {
390 };
391 
392 template<>
393 class RankHistogram<bool>:
394  public VectorRankHistogram<bool>
395 {
396 };
397 
399 
400 } // end namespace Function
401 } // end namespace itk
402 #endif
signed long OffsetValueType
Definition: itkIntTypes.h:154
unsigned long SizeValueType
Definition: itkIntTypes.h:143
TInputPixel GetValue(const TInputPixel &)
static ITK_CONSTEXPR_FUNC T max(const T &)
RankHistogram & operator=(const RankHistogram &hist)
std::less< TInputPixel > Compare
std::map< TInputPixel, SizeValueType, Compare > MapType
void RemovePixel(const TInputPixel &p)
static ITK_CONSTEXPR_FUNC T NonpositiveMin()
void RemovePixel(const TInputPixel &p)
std::less< TInputPixel > Compare
Define additional traits for native types such as int or float.
std::vector< SizeValueType > VecType
void AddPixel(const TInputPixel &p)
void AddPixel(const TInputPixel &p)
TInputPixel GetValue(const TInputPixel &)