-
Notifications
You must be signed in to change notification settings - Fork 0
/
itkVariableProjectImageFilter.h
298 lines (254 loc) · 11.2 KB
/
itkVariableProjectImageFilter.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
#ifndef __itkVariableProjectImageFilter_h
#define __itkVariableProjectImageFilter_h
#include "itkImageToImageFilter.h"
#include "itkConceptChecking.h"
#include <numeric>
#define __itkVariableProjectImageFilter_MULTITHREADED
//#undef __itkVariableProjectImageFilter_MULTITHREADED
namespace itk
{
/** \class VariableProjectImageFilter
* \brief Implements an accumulation of an image along a selected direction.
*
* This class accumulates an image along a dimension and reduce the size
* of this dimension to 1. The dimension being accumulated is set by
* AccumulateDimension.
*
* Each pixel is the cumulative sum of the pixels along the collapsed
* dimension and reduce the size of the accumulated dimension to 1 (only
* on the accumulated).
*
* The dimensions of the InputImage and the OutputImage must be the same.
*
*
*
* This class is parameterized over the type of the input image and
* the type of the output image.
*
*
* \author Emiliano Beronich
*
* This filter was contributed by Emiliano Beronich
*
* \ingroup IntensityImageFilters Singlethreaded
*/
template <class TInputImage, class TOutputImage, template< typename , typename > class TProjectorTemplate >
class ITK_EXPORT VariableProjectImageFilter : public ImageToImageFilter<TInputImage,TOutputImage>
{
public:
/** Standard class typedefs. */
typedef VariableProjectImageFilter Self;
typedef ImageToImageFilter<TInputImage,TOutputImage> Superclass;
typedef SmartPointer<Self> Pointer;
typedef SmartPointer<const Self> ConstPointer;
/** Method for creation through the object factory. */
itkNewMacro(Self);
/** Run-time type information (and related methods). */
itkTypeMacro(VariableProjectImageFilter, ImageToImageFilter);
/** Some convenient typedefs. */
typedef TInputImage InputImageType;
typedef typename InputImageType::Pointer InputImagePointer;
typedef typename InputImageType::RegionType InputImageRegionType;
typedef typename InputImageType::PixelType InputImagePixelType;
typedef TOutputImage OutputImageType;
typedef typename OutputImageType::Pointer OutputImagePointer;
typedef typename OutputImageType::RegionType OutputImageRegionType;
typedef typename OutputImageType::PixelType OutputImagePixelType;
typedef TProjectorTemplate< typename TInputImage::PixelType, typename TOutputImage::PixelType > ProjectorType;
/** ImageDimension enumeration */
itkStaticConstMacro(InputImageDimension, unsigned int,
TInputImage::ImageDimension);
itkStaticConstMacro(OutputImageDimension, unsigned int,
TOutputImage::ImageDimension);
/** Input and output images must be the same dimension. */
itkConceptMacro(ImageDimensionCheck,
(Concept::SameDimension<itkGetStaticConstMacro(InputImageDimension),
itkGetStaticConstMacro(OutputImageDimension)>));
/** Set the direction in which to accumulate the data. It must be
* set before the update of the filter. Defaults to the last
* dimension. */
itkGetMacro( AccumulateDimension, unsigned int );
itkSetMacro( AccumulateDimension, unsigned int );
void SetProjector( const ProjectorType& proj) { m_Projector = proj; }
const ProjectorType& GetProjector( void ) const { return m_Projector; }
protected:
VariableProjectImageFilter();
virtual ~VariableProjectImageFilter() {};
void PrintSelf(std::ostream& os, Indent indent) const;
/** Apply changes to the output image information. */
virtual void GenerateOutputInformation();
/** Apply changes to the input image requested region. */
virtual void GenerateInputRequestedRegion();
/** This method implements the actual accumulation of the image.
*
* \sa ImageToImageFilter::ThreadedGenerateData(),
* ImageToImageFilter::GenerateData() */
#ifndef __itkVariableProjectImageFilter_MULTITHREADED
void GenerateData(void);
#else
void ThreadedGenerateData(const OutputImageRegionType &outputRegionForThread, int threadId);
#endif
private:
VariableProjectImageFilter(const Self&); //purposely not implemented
void operator=(const Self&); //purposely not implemented
unsigned int m_AccumulateDimension;
ProjectorType m_Projector;
};
} // end namespace itk
/*
template <class TInputPixel, class TOutputPixel, const int ptype>
class MinMaxProjector {
public:
static const int MaxType = 1;
static const int MinType = 2;
MinMaxProjector() { Clear(); }
void Clear() { value = (ptype == MaxType)?itk::NumericTraits< TOutputPixel >::min() : itk::NumericTraits< TOutputPixel >::max(); }
void AddValue( const TInputPixel& val) { value = (ptype == MaxType)?
std::max( value, static_cast<TOutputPixel>( val ) ) :
std::min( value, static_cast<TOutputPixel>( val ) )
; }
TOutputPixel GetProjectedValue(void) { return value; }
bool operator!=(MinMaxProjector<TInputPixel, TOutputPixel, ptype> const& obj)
{ return obj.value != value; }
private:
TOutputPixel value;
};
template <class TInputPixel, class TOutputPixel, const int ptype>
std::ostream& operator<<(std::ostream& stream, MinMaxProjector<TInputPixel, TOutputPixel, ptype> const& obj)
{ stream << toString( (ptype == MinMaxProjector<TInputPixel, TOutputPixel, ptype>::MaxType)?"Maximum":"Minimum") << "Projector" << std::endl; return stream; }
template <class TInputPixel, class TOutputPixel>
class MaximumProjector: public MinMaxProjector< TInputPixel, TOutputPixel, MinMaxProjector<TInputPixel,TOutputPixel,0>::MaxType > {
};
template <class TInputPixel, class TOutputPixel>
class MinimumProjector: public MinMaxProjector< TInputPixel, TOutputPixel, MinMaxProjector<TInputPixel,TOutputPixel,0>::MinType > {
};
template <class TInputPixel, class TOutputPixel>
class softMipProjector {
public:
void Print(std::ostream& stream) const {
stream << "softMipProjector:" << std::endl;
for( softMipVertexContainer::const_iterator it = softMipFunction.begin(); it != softMipFunction.end(); ++it) {
stream << "[" << it->first << "," << it->second * NormalizeFactor << "] ";
}
stream << std::endl;
for( double t = 0.0; t <= 1.0; t += 0.1) {
stream << "[" << t << "," << GetValue( t ) << "] ";
}
stream << std::endl;
}
softMipProjector():NormalizeFactor(0.0), MaxPosition(0.0) {}
explicit softMipProjector(double f) {
AddVertex( 0.0, 1.0 );
if (f != 0.0) AddVertex( f, f * f );
else AddVertex( 0.000000001, 0);
AddVertex( 1.0, 0.0 );
}
void Clear() { pixels.clear(); }
void AddValue( const TInputPixel& val) { pixels.push_back( val ); }
TOutputPixel GetProjectedValue(void) {
typename PixelContainer::size_type quantil_index = static_cast<typename PixelContainer::size_type>(pixels.size() * MaxPosition);
// std::nth_element( pixels.begin(), pixels.begin() + quantil_index, pixels.end(), std::greater< TInputPixel >() );
std::partial_sort( pixels.begin(), pixels.begin() + quantil_index, pixels.end(), std::greater< TInputPixel >() );
double val = 0.0;
typename PixelContainer::const_iterator pixit = pixels.begin();
for(int i = 0; i < quantil_index; ++i)
val += *pixit++ * GetIntegral( i );
return static_cast<TOutputPixel>(val);
}
void AddVertex( double position, double value) {
Integrals.clear();
if (position >= 0.0 && position <= 1.0 ) {
softMipFunction[ position ] = value;
MaxPosition = std::max( position, MaxPosition );
softMipVertexContainer::const_iterator it = softMipFunction.begin();
NormalizeFactor = it->first * it->second;
softMipVertexContainer::const_iterator old = it;
++it;
while (it != softMipFunction.end()) {
NormalizeFactor += ( it->first - old->first) * ( it->second + old->second ) / 2;
old = it;
++it;
}
NormalizeFactor += ( 1.0 - old->first) * old->second;
if (NormalizeFactor != 0.0) NormalizeFactor = 1.0 / NormalizeFactor;
}
}
bool operator!=(softMipProjector<TInputPixel, TOutputPixel> const& obj)
{ return false; }
private:
double GetValue( double pos ) const {
if (softMipFunction.empty()) return 0.0;
softMipVertexContainer::const_iterator it = softMipFunction.lower_bound( pos );
if ( it == softMipFunction.end() ) return NormalizeFactor * (--it)->second;
if ( it == softMipFunction.begin() ) return NormalizeFactor * it->second;
softMipVertexContainer::const_iterator pre = it; --pre;
return NormalizeFactor *
( pre->second + ( it->second - pre->second ) * (pos - pre->first) / ( it->first - pre->first ) );
}
double GetIntegral( int i) {
if (Integrals.size() != pixels.size() ) {
Integrals.resize( pixels.size() );
double last;
double current = GetValue( 0.0 );
double step = 1.0 /pixels.size();
double pos = step;
for(int k = 0; k < pixels.size(); ++k) {
last = current;
current = GetValue( pos );
Integrals[k] = step * ( last + current ) / 2.0;
pos += step;
}
}
return Integrals[ i ];
}
double NormalizeFactor;
double MaxPosition;
typedef std::vector< TOutputPixel > PixelContainer;
typedef std::vector< double > IntegralContainer;
IntegralContainer Integrals;
typedef std::map< double, double > softMipVertexContainer;
softMipVertexContainer softMipFunction;
PixelContainer pixels;
};
template <class TInputPixel, class TOutputPixel>
std::ostream& operator<<(std::ostream& stream, softMipProjector<TInputPixel, TOutputPixel> const& obj)
{ stream << "softMipProjector" << std::endl; return stream; }
template <class TInputPixel, class TOutputPixel>
class AverageProjector {
public:
AverageProjector() { Clear(); }
void Clear() { sum = .0; num = 0; }
void AddValue( const TInputPixel& val) { sum += val; num++; }
TOutputPixel GetProjectedValue(void) {
return static_cast<TOutputPixel>( sum / num );
}
bool operator!=(AverageProjector<TInputPixel, TOutputPixel> const& obj)
{ return false; }
private:
double sum;
unsigned int num;
};
template <class TInputPixel, class TOutputPixel>
std::ostream& operator<<(std::ostream& stream, AverageProjector<TInputPixel, TOutputPixel> const& obj)
{ stream << "AverageProjector" << std::endl; return stream; }
*/
template<class TImagePointerType, template < typename, typename > class Projector>
TImagePointerType ImageProjector(TImagePointerType image,
Projector<typename TImagePointerType::ObjectType::PixelType, typename TImagePointerType::ObjectType::PixelType> proj =
Projector<typename TImagePointerType::ObjectType::PixelType, typename TImagePointerType::ObjectType::PixelType>(),
int AccumulateDimension = -1) {
typedef typename TImagePointerType::ObjectType TImageType;
typedef itk::VariableProjectImageFilter< TImageType, TImageType, Projector > ProjectFilterType;
typename ProjectFilterType::Pointer pf = ProjectFilterType::New();
pf->SetProjector( proj );
if (AccumulateDimension != -1) pf->SetAccumulateDimension( AccumulateDimension );
pf->SetInput( image );
pf->Update();
TImagePointerType PImage;
PImage = pf->GetOutput();
return PImage;
}
#ifndef ITK_MANUAL_INSTANTIATION
#include "itkVariableProjectImageFilter.txx"
#endif
#endif