[Insight-developers] Memory leak in an edge detection filter
Massimo Esposito
mass.esposito at gmail.com
Tue Sep 18 05:03:50 EDT 2007
Dear All,
I use an edge detection filter to preprocess medical images before of
segmentation.
Although the filter works, a huge memory leak is detected at line 247 of the
filter source code set at the queue of the mail text.
Could someone help me to overcome that problem?
Thank you in advance
Massimo
///FILTER SOURCE
CODE///////////////////////////////////////////////////////////////////////////////
0
1 #ifndef __EdgePreprocessingFilter_h_
2 #define __EdgePreprocessingFilter_h_
3
4
5
6
7
8 #include "stdafx.h"
9 #include "itkCommand.h"
10 #include "itkCastImageFilter.h"
11 #include "itkDiscreteGaussianImageFilter.h"
12 #include "itkGradientMagnitudeImageFilter.h"
13 #include "itkImageAdaptor.h"
14 #include "itkMinimumMaximumImageCalculator.h"
15 #include "itkProgressAccumulator.h"
16 #include "itkRescaleIntensityImageFilter.h"
17 #include "itkUnaryFunctorImageFilter.h"
18 #include "EdgePreprocessingSettings.h"
19
20
21 /**
22 * The g() function that remaps the gradient magnitude image to the
23 * range 0 to 1.
24 */
25 template<class TInput, class TOutput>
26 class EdgeRemappingFunctor
27 {
28 public:
29 typedef EdgeRemappingFunctor<TInput, TOutput> Self;
30
31 void SetParameters(float intensityMin, float intensityMax,
32 float exponent, float kappa)
33 {
34 m_KappaFactor = 1.0f / kappa;
35 m_Exponent = exponent;
36 m_IntensityBase = intensityMin;
37 m_IntensityScale = 1.0f / (intensityMax - intensityMin);
38 }
39
40 inline TOutput operator()(const TInput &x)
41 {
42 float xNorm = (static_cast<float>(x)-m_IntensityBase)*m_IntensityScale;
43 float y = 1.0f / (1.0f + pow(xNorm * m_KappaFactor,m_Exponent));
44 return static_cast<TOutput> (y);
45 }
46
47 bool operator ==(const Self &z)
48 {
49 return
50 m_KappaFactor == z.m_KappaFactor &&
51 m_IntensityBase == z.m_IntensityBase &&
52 m_IntensityScale == z.m_IntensityScale &&
53 m_Exponent == z.m_Exponent;
54 }
55
56 bool operator !=(const Self &z)
57 { return !(*this == z); }
58
59 private:
60
61 float m_KappaFactor;
62 float m_IntensityBase;
63 float m_IntensityScale;
64 float m_Exponent;
65 };
66
67 /**
68 * \class EdgePreprocessingImageFilter
69 * \brief A filter used for edge preprocessing of images.
70 *
71 * This functor implements a Gaussian blur, followed by a gradient
magnitude
72 * operator, followed by a 'contrast enhancement' intensity remapping
filter.
73 */
74 template <typename TInputImage,typename TOutputImage = TInputImage>
75 class EdgePreprocessingImageFilter:
76 public itk::ImageToImageFilter<TInputImage,TOutputImage>
77 {
78 public:
79 //typedef vnl_vector_fixed<float,3> Vector3f;
80
81 /** Standard class typedefs. */
82 typedef EdgePreprocessingImageFilter Self;
83 typedef itk::ImageToImageFilter<TInputImage,TOutputImage> Superclass;
84 typedef itk::SmartPointer<Self> Pointer;
85 typedef itk::SmartPointer<const Self> ConstPointer;
86
87 /** Pixel Type of the input image */
88 typedef TInputImage InputImageType;
89 typedef typename InputImageType::PixelType InputPixelType;
90 typedef itk::SmartPointer<InputImageType> InputImagePointer;
91
92 /** Pixel Type of the output image */
93 typedef TOutputImage OutputImageType;
94 typedef typename OutputImageType::PixelType OutputPixelType;
95 typedef itk::SmartPointer<OutputImageType> OutputImagePointer;
96
97 /** Type used for internal calculations */
98 typedef float RealType;
99 typedef itk::Image<RealType,3> InternalImageType;
100 typedef itk::SmartPointer<InternalImageType> InternalImagePointer;
101
102 /** Functor type used for thresholding */
103 typedef EdgeRemappingFunctor<RealType,OutputPixelType> FunctorType;
104
105 /** Method for creation through the object factory. */
106 itkNewMacro(Self)
107
108 /** Image dimension. */
109 itkStaticConstMacro(ImageDimension, unsigned int,
110 TInputImage::ImageDimension);
111
112 /** Assign new edge processing settings */
113 void SetEdgePreprocessingSettings(const EdgePreprocessingSettings
&settings);
114
115
116 protected:
117
118 EdgePreprocessingImageFilter();
119 virtual ~EdgePreprocessingImageFilter() {};
120 void PrintSelf(std::ostream& os, itk::Indent indent) const;
121
122 /** Generate Data */
123 void GenerateData( void );
124
125 /**
126 * This method maps an input region to an output region. It's necessary
to
127 * reflect the way this filter pads the requested region
128 */
129 void GenerateInputRequestedRegion();
130
131 private:
132
133 /** The unary functor filter type used for remapping */
134 typedef itk::UnaryFunctorImageFilter<
135 InternalImageType,TOutputImage,FunctorType> RemappingFilterType;
136 typedef typename RemappingFilterType::Pointer RemappingFilterPointer;
137
138 /** The min / max calculator used to compute gradient range */
139 typedef itk::MinimumMaximumImageCalculator<
140 InternalImageType> CalculatorType;
141 typedef typename CalculatorType::Pointer CalculatorPointer;
142
143 /** Adaptor used to cast to float */
144 typedef itk::CastImageFilter<
145 InputImageType,InternalImageType> CastFilterType;
146 typedef typename CastFilterType::Pointer CastFilterPointer;
147
148 /** Gaussian smoothing filter */
149 typedef itk::DiscreteGaussianImageFilter<
150 InternalImageType,InternalImageType> GaussianFilterType;
151 typedef typename GaussianFilterType::Pointer GaussianFilterPointer;
152
153 /** Gradient magnitude filter */
154 typedef itk::GradientMagnitudeImageFilter<
155 InternalImageType,InternalImageType> GradientFilterType;
156 typedef typename GradientFilterType::Pointer GradientFilterPointer;
157
158 /** Intensity rescaling filter */
159 typedef itk::RescaleIntensityImageFilter<
160 InternalImageType,InternalImageType> RescaleFilterType;
161 typedef typename RescaleFilterType::Pointer RescaleFilterPointer;
162
163 /** Progress accumulator object */
164 typedef itk::ProgressAccumulator::Pointer AccumulatorPointer;
165
166 CastFilterPointer m_CastFilter;
167 RemappingFilterPointer m_RemappingFilter;
168 GaussianFilterPointer m_GaussianFilter;
169 GradientFilterPointer m_GradientFilter;
170 CalculatorPointer m_Calculator;
171 RescaleFilterPointer m_RescaleFilter;
172
173 EdgePreprocessingSettings m_EdgePreprocessingSettings;
174
175 /** Progress tracking object */
176 AccumulatorPointer m_ProgressAccumulator;
177
178 };
179
180 #ifndef ITK_MANUAL_INSTANTIATION
181 //#include "EdgePreprocessingImageFilter.txx"
182
183 using namespace itk;
184
185 template<typename TInputImage,typename TOutputImage>
186 EdgePreprocessingImageFilter<TInputImage,TOutputImage>
187 ::EdgePreprocessingImageFilter()
188 {
189
190 // Construct the adaptor
191 m_CastFilter = CastFilterType::New();
192 m_CastFilter->ReleaseDataFlagOn();
193 m_CastFilter->SetInput(this->GetInput());
194
195 // Construct the Gaussian filter
196 m_GaussianFilter = GaussianFilterType::New();
197 m_GaussianFilter->SetUseImageSpacing(false);
198 m_GaussianFilter->ReleaseDataFlagOn();
199 m_GaussianFilter->SetInput(m_CastFilter->GetOutput());
200
201 // The gradient magnitude filter
202 m_GradientFilter = GradientFilterType::New();
203 m_GradientFilter->ReleaseDataFlagOn();
204 m_GradientFilter->SetInput(m_GaussianFilter->GetOutput());
205
206 // The normalization filter
207 m_RescaleFilter = RescaleFilterType::New();
208 m_RescaleFilter->ReleaseDataFlagOn();
209 m_RescaleFilter->SetOutputMinimum(0.0f);
210 m_RescaleFilter->SetOutputMaximum(1.0f);
211 m_RescaleFilter->SetInput(m_GradientFilter->GetOutput());
212
213 // Construct the Remapping filter
214 m_RemappingFilter = RemappingFilterType::New();
215 m_RemappingFilter->ReleaseDataFlagOn();
216 m_RemappingFilter->SetInput(m_RescaleFilter->GetOutput());
217
218 // Create the progress accumulator
219 m_ProgressAccumulator = itk::ProgressAccumulator::New();
220 m_ProgressAccumulator->SetMiniPipelineFilter(this);
221
222 // Register the filters with the progress accumulator
223 m_ProgressAccumulator->RegisterInternalFilter(m_CastFilter,0.1f);
224 m_ProgressAccumulator->RegisterInternalFilter(m_GaussianFilter,0.6f);
225 m_ProgressAccumulator->RegisterInternalFilter(m_GradientFilter,0.1f);
226 m_ProgressAccumulator->RegisterInternalFilter(m_RescaleFilter,0.1f);
227 m_ProgressAccumulator->RegisterInternalFilter(m_RemappingFilter,0.1f);
228 }
229
230 template<typename TInputImage,typename TOutputImage>
231 void
232 EdgePreprocessingImageFilter<TInputImage,TOutputImage>
233 ::GenerateData()
234 {
235 // Get the input and output pointers
236 const typename InputImageType::ConstPointer inputImage =
this->GetInput();
237 typename OutputImageType::Pointer outputImage = this->GetOutput();
238
239 // Initialize the progress counter
240 m_ProgressAccumulator->ResetProgress();
241
242 // Allocate the output image
243 outputImage->SetBufferedRegion(outputImage->GetRequestedRegion());
244 outputImage->Allocate();
245
246 // Pipe in the input image
247 m_CastFilter->SetInput(inputImage); //Here the memory leak is detected!!
248
249
250 // Set the variance
251 Vector3f variance(
252 m_EdgePreprocessingSettings.GetGaussianBlurScale() *
253 m_EdgePreprocessingSettings.GetGaussianBlurScale());
254 m_GaussianFilter->SetVariance(variance.data_block());
255
256 // Construct the functor
257 FunctorType functor;
258 functor.SetParameters(0.0f,1.0f,
259 m_EdgePreprocessingSettings.GetRemappingExponent(),
260 m_EdgePreprocessingSettings.GetRemappingSteepness());
261
262 // Assign the functor to the filter
263 m_RemappingFilter->SetFunctor(functor);
264
265 // Call the filter's GenerateData()
266 m_RemappingFilter->GraftOutput(outputImage);
267 m_RemappingFilter->Update();
268
269 // graft the mini-pipeline output back onto this filter's output.
270 // this is needed to get the appropriate regions passed back.
271 GraftOutput( m_RemappingFilter->GetOutput() );
272
273 }
274
275 template<typename TInputImage,typename TOutputImage>
276 void
277 EdgePreprocessingImageFilter<TInputImage,TOutputImage>
278 ::PrintSelf(std::ostream& os, Indent indent) const
279 {
280 Superclass::PrintSelf(os,indent);
281 }
282
283 template<typename TInputImage,typename TOutputImage>
284 void
285 EdgePreprocessingImageFilter<TInputImage,TOutputImage>
286 ::SetEdgePreprocessingSettings(const EdgePreprocessingSettings
&settings)
287 {
288 if(!(settings == m_EdgePreprocessingSettings))
289 {
290 m_EdgePreprocessingSettings = settings;
291 this->Modified();
292 }
293 }
294
295 template<typename TInputImage,typename TOutputImage>
296 void
297 EdgePreprocessingImageFilter<TInputImage,TOutputImage>
298 ::GenerateInputRequestedRegion()
299 {
300 // Make sure we call the parent's implementation
301 Superclass::GenerateInputRequestedRegion();
302
303 // Get pointers to the input and output
304 InputImagePointer inputPtr =
305 const_cast< TInputImage * >( this->GetInput() );
306 OutputImagePointer outputPtr = this->GetOutput();
307
308 // Use the largest possible region (hack)
309 inputPtr->SetRequestedRegion(
310 inputPtr->GetLargestPossibleRegion());
311 }
312
313 #endif
314
315 #endif // __EdgePreprocessingFilter_h_
316
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.itk.org/mailman/private/insight-developers/attachments/20070918/b995bb94/attachment.html
More information about the Insight-developers
mailing list