ITK  5.0.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  using Compare = std::less< TInputPixel >;
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 
77  ~RankHistogram() = default;
78 
80  {
81  if(this != &hist)
82  {
83  m_Map = hist.m_Map;
84  m_Rank = hist.m_Rank;
85  m_Below = hist.m_Below;
86  m_Entries = hist.m_Entries;
87  m_InitVal = hist.m_InitVal;
88  m_RankValue = hist.m_RankValue;
90  if ( m_Initialized )
91  {
92  m_RankIt = m_Map.find(m_RankValue);
93  }
94  }
95  return *this;
96  }
97 
98  void AddPixel(const TInputPixel & p)
99  {
100  m_Map[p]++;
101  if ( !m_Initialized )
102  {
103  m_Initialized = true;
104  m_RankIt = m_Map.begin();
105  m_Entries = m_Below = 0;
106  m_RankValue = p;
107  }
108  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
109  {
110  ++m_Below;
111  }
112  ++m_Entries;
113  }
114 
115  void RemovePixel(const TInputPixel & p)
116  {
117  m_Map[p]--;
118  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
119  {
120  --m_Below;
121  }
122  --m_Entries;
123  // this is the change that makes this version less efficient. The
124  // simplest approach I can think of with maps, though
125  if ( m_Entries <= 0 )
126  {
127  m_Initialized = false;
128  m_Below = 0;
129  m_Map.clear();
130  }
131  }
132 
133  bool IsValid()
134  {
135  return m_Initialized;
136  }
137 
138  TInputPixel GetValueBruteForce()
139  {
140  SizeValueType count = 0;
141  SizeValueType target = (int)( m_Rank * ( m_Entries - 1 ) ) + 1;
142  for( typename MapType::iterator it=m_Map.begin(); it != m_Map.end(); it++ )
143  {
144  count += it->second;
145  if( count >= target )
146  {
147  return it->first;
148  }
149  }
151  }
152 
153  TInputPixel GetValue(const TInputPixel &)
154  {
155  SizeValueType target = (SizeValueType)( m_Rank * ( m_Entries - 1 ) ) + 1;
156  SizeValueType total = m_Below;
157  SizeValueType ThisBin;
158  bool eraseFlag = false;
159 
160  if ( total < target )
161  {
162  auto searchIt = m_RankIt;
163  typename MapType::iterator eraseIt;
164 
165  while ( searchIt != m_Map.end() )
166  {
167  // cleaning up the map - probably a better way of organising
168  // the loop. Currently makes sure that the search iterator is
169  // incremented before deleting
170  ++searchIt;
171  ThisBin = searchIt->second;
172  total += ThisBin;
173  if ( eraseFlag )
174  {
175  m_Map.erase(eraseIt);
176  eraseFlag = false;
177  }
178  if ( ThisBin <= 0 )
179  {
180  eraseFlag = true;
181  eraseIt = searchIt;
182  }
183  if ( total >= target )
184  {
185  break;
186  }
187  }
188  if (searchIt == m_Map.end())
189  {
190  --searchIt;
191  }
192  m_RankValue = searchIt->first;
193  m_RankIt = searchIt;
194  }
195  else
196  {
197  auto searchIt = m_RankIt;
198  typename MapType::iterator eraseIt;
199 
200  while ( searchIt != m_Map.begin() )
201  {
202  ThisBin = searchIt->second;
203  unsigned int tbelow = total - ThisBin;
204  if ( tbelow < target ) // we've overshot
205  {
206  break;
207  }
208  if ( eraseFlag )
209  {
210  m_Map.erase(eraseIt);
211  eraseFlag = false;
212  }
213  if ( ThisBin <= 0 )
214  {
215  eraseIt = searchIt;
216  eraseFlag = true;
217  }
218  total = tbelow;
219 
220  --searchIt;
221  }
222  m_RankValue = searchIt->first;
223  m_RankIt = searchIt;
224  }
225 
226  m_Below = total;
227  itkAssertInDebugAndIgnoreInReleaseMacro( m_RankValue == GetValueBruteForce() );
228  return ( m_RankValue );
229  }
230 
231  void SetRank(float rank)
232  {
233  m_Rank = rank;
234  }
235 
236  void AddBoundary(){}
237 
238  void RemoveBoundary(){}
239 
241  {
242  return false;
243  }
244 
245 protected:
246  float m_Rank;
247 
248 private:
249  using MapType = typename std::map< TInputPixel, SizeValueType, Compare >;
250 
254  TInputPixel m_RankValue;
255  TInputPixel m_InitVal;
258 
259  // This iterator will point at the desired rank value
260  typename MapType::iterator m_RankIt;
261 };
262 
263 
264 template< typename TInputPixel >
266 {
267 public:
268  using Compare = std::less< TInputPixel >;
269 
271  {
273  m_Vec.resize(m_Size, 0);
276  {
278  }
279  else
280  {
282  }
283  m_Entries = m_Below = 0;
285  m_Rank = 0.5;
286  }
287 
288  ~VectorRankHistogram() = default;
289 
290  bool IsValid()
291  {
292  return m_Entries > 0;
293  }
294 
295  TInputPixel GetValueBruteForce()
296  {
297  SizeValueType count = 0;
298  SizeValueType target = (SizeValueType)( m_Rank * ( m_Entries - 1 ) ) + 1;
299  for( SizeValueType i=0; i<m_Size; i++ )
300  {
301  count += m_Vec[i];
302  if( count >= target )
303  {
305  }
306  }
308  }
309 
310  TInputPixel GetValue(const TInputPixel &)
311  {
312  return GetValueBruteForce();
313  }
314 
315  void AddPixel(const TInputPixel & p)
316  {
318 
319  m_Vec[q]++;
320  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
321  {
322  ++m_Below;
323  }
324  ++m_Entries;
325  }
326 
327  void RemovePixel(const TInputPixel & p)
328  {
330 
331  itkAssertInDebugAndIgnoreInReleaseMacro( q >= 0 );
332  itkAssertInDebugAndIgnoreInReleaseMacro( q < (int)m_Vec.size() );
333  itkAssertInDebugAndIgnoreInReleaseMacro( m_Entries >= 1 );
334  itkAssertInDebugAndIgnoreInReleaseMacro( m_Vec[q] > 0 );
335 
336  m_Vec[q]--;
337  --m_Entries;
338 
339  if ( m_Compare(p, m_RankValue) || p == m_RankValue )
340  {
341  --m_Below;
342  }
343  }
344 
345  void SetRank(float rank)
346  {
347  m_Rank = rank;
348  }
349 
350  void AddBoundary(){}
351 
352  void RemoveBoundary(){}
353 
355  {
356  return true;
357  }
358 
359 protected:
360  float m_Rank;
361 
362 private:
363  using VecType = typename std::vector< SizeValueType >;
364 
368  TInputPixel m_RankValue;
369  TInputPixel m_InitVal;
370  int m_Below;
372 };
373 
374 // now create MorphologicalGradientHistogram specilizations using the VectorMorphologicalGradientHistogram
375 // as base class
376 
378 
379 template<>
380 class RankHistogram<unsigned char>:
381  public VectorRankHistogram<unsigned char>
382 {
383 };
384 
385 template<>
386 class RankHistogram<signed char>:
387  public VectorRankHistogram<signed char>
388 {
389 };
390 
391 template<>
392 class RankHistogram<bool>:
393  public VectorRankHistogram<bool>
394 {
395 };
396 
398 
399 } // end namespace Function
400 } // end namespace itk
401 #endif
std::less< TInputPixel > Compare
Define numeric traits for std::vector.
unsigned long SizeValueType
Definition: itkIntTypes.h:83
TInputPixel GetValue(const TInputPixel &)
typename std::map< TInputPixel, SizeValueType, Compare > MapType
RankHistogram & operator=(const RankHistogram &hist)
std::less< TInputPixel > Compare
void RemovePixel(const TInputPixel &p)
void RemovePixel(const TInputPixel &p)
void AddPixel(const TInputPixel &p)
typename std::vector< SizeValueType > VecType
signed long OffsetValueType
Definition: itkIntTypes.h:94
void AddPixel(const TInputPixel &p)
TInputPixel GetValue(const TInputPixel &)