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