<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 &quot;stdafx.h&quot;</p>
<p>9 #include &quot;itkCommand.h&quot;</p>
<p>10 #include &quot;itkCastImageFilter.h&quot;</p>
<p>11 #include &quot;itkDiscreteGaussianImageFilter.h&quot;</p>
<p>12 #include &quot;itkGradientMagnitudeImageFilter.h&quot;</p>
<p>13 #include &quot;itkImageAdaptor.h&quot;</p>
<p>14 #include &quot;itkMinimumMaximumImageCalculator.h&quot;</p>
<p>15 #include &quot;itkProgressAccumulator.h&quot;</p>
<p>16 #include &quot;itkRescaleIntensityImageFilter.h&quot;</p>
<p>17 #include &quot;itkUnaryFunctorImageFilter.h&quot;</p>
<p>18 #include &quot;EdgePreprocessingSettings.h&quot;</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&lt;class TInput, class TOutput&gt;</p>
<p>26 class EdgeRemappingFunctor</p>
<p>27 {</p>
<p>28 public:</p>
<p>29 typedef EdgeRemappingFunctor&lt;TInput, TOutput&gt; 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 &amp;x)</p>
<p>41 {</p>
<p>42 float xNorm = (static_cast&lt;float&gt;(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&lt;TOutput&gt; (y);</p>
<p>45 }</p>
<p>46</p>
<p>47 bool operator ==(const Self &amp;z)</p>
<p>48 { </p>
<p>49 return </p>
<p>50 m_KappaFactor == z.m_KappaFactor &amp;&amp;</p>
<p>51 m_IntensityBase == z.m_IntensityBase &amp;&amp;</p>
<p>52 m_IntensityScale == z.m_IntensityScale &amp;&amp;</p>
<p>53 m_Exponent == z.m_Exponent;</p>
<p>54 }</p>
<p>55</p>
<p>56 bool operator !=(const Self &amp;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 &#39;contrast enhancement&#39; intensity remapping filter.</p>
<p>73 */</p>
<p>74 template &lt;typename TInputImage,typename TOutputImage = TInputImage&gt;</p>
<p>75 class EdgePreprocessingImageFilter: </p>
<p>76 public itk::ImageToImageFilter&lt;TInputImage,TOutputImage&gt;</p>
<p>77 {</p>
<p>78 public:</p>
<p>79 //typedef vnl_vector_fixed&lt;float,3&gt; Vector3f;</p>
<p>80</p>
<p>81 /** Standard class typedefs. */</p>
<p>82 typedef EdgePreprocessingImageFilter Self;</p>
<p>83 typedef itk::ImageToImageFilter&lt;TInputImage,TOutputImage&gt; Superclass;</p>
<p>84 typedef itk::SmartPointer&lt;Self&gt; Pointer;</p>
<p>85 typedef itk::SmartPointer&lt;const Self&gt; 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&lt;InputImageType&gt; 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&lt;OutputImageType&gt; OutputImagePointer;</p>
<p>96</p>
<p>97 /** Type used for internal calculations */</p>
<p>98 typedef float RealType;</p>
<p>99 typedef itk::Image&lt;RealType,3&gt; InternalImageType;</p>
<p>100 typedef itk::SmartPointer&lt;InternalImageType&gt; InternalImagePointer;</p>
<p>101</p>
<p>102 /** Functor type used for thresholding */</p>
<p>103 typedef EdgeRemappingFunctor&lt;RealType,OutputPixelType&gt; 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 &amp;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&amp; 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&#39;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&lt;</p>
<p>135 InternalImageType,TOutputImage,FunctorType&gt; 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&lt;</p>
<p>140 InternalImageType&gt; 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&lt;</p>
<p>145 InputImageType,InternalImageType&gt; CastFilterType;</p>
<p>146 typedef typename CastFilterType::Pointer CastFilterPointer;</p>
<p>147</p>
<p>148 /** Gaussian smoothing filter */</p>
<p>149 typedef itk::DiscreteGaussianImageFilter&lt;</p>
<p>150 InternalImageType,InternalImageType&gt; GaussianFilterType;</p>
<p>151 typedef typename GaussianFilterType::Pointer GaussianFilterPointer;</p>
<p>152</p>
<p>153 /** Gradient magnitude filter */</p>
<p>154 typedef itk::GradientMagnitudeImageFilter&lt;</p>
<p>155 InternalImageType,InternalImageType&gt; GradientFilterType;</p>
<p>156 typedef typename GradientFilterType::Pointer GradientFilterPointer;</p>
<p>157</p>
<p>158 /** Intensity rescaling filter */</p>
<p>159 typedef itk::RescaleIntensityImageFilter&lt;</p>
<p>160 InternalImageType,InternalImageType&gt; 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 &quot;EdgePreprocessingImageFilter.txx&quot;</p>
<p>182</p>
<p>183 using namespace itk;</p>
<p>184</p>
<p>185 template&lt;typename TInputImage,typename TOutputImage&gt;</p>
<p>186 EdgePreprocessingImageFilter&lt;TInputImage,TOutputImage&gt;</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-&gt;ReleaseDataFlagOn();</p>
<p>193 m_CastFilter-&gt;SetInput(this-&gt;GetInput()); </p>
<p>194</p>
<p>195 // Construct the Gaussian filter</p>
<p>196 m_GaussianFilter = GaussianFilterType::New();</p>
<p>197 m_GaussianFilter-&gt;SetUseImageSpacing(false);</p>
<p>198 m_GaussianFilter-&gt;ReleaseDataFlagOn();</p>
<p>199 m_GaussianFilter-&gt;SetInput(m_CastFilter-&gt;GetOutput());</p>
<p>200</p>
<p>201 // The gradient magnitude filter</p>
<p>202 m_GradientFilter = GradientFilterType::New();</p>
<p>203 m_GradientFilter-&gt;ReleaseDataFlagOn();</p>
<p>204 m_GradientFilter-&gt;SetInput(m_GaussianFilter-&gt;GetOutput()); </p>
<p>205</p>
<p>206 // The normalization filter</p>
<p>207 m_RescaleFilter = RescaleFilterType::New();</p>
<p>208 m_RescaleFilter-&gt;ReleaseDataFlagOn();</p>
<p>209 m_RescaleFilter-&gt;SetOutputMinimum(0.0f);</p>
<p>210 m_RescaleFilter-&gt;SetOutputMaximum(1.0f);</p>
<p>211 m_RescaleFilter-&gt;SetInput(m_GradientFilter-&gt;GetOutput());</p>
<p>212</p>
<p>213 // Construct the Remapping filter</p>
<p>214 m_RemappingFilter = RemappingFilterType::New();</p>
<p>215 m_RemappingFilter-&gt;ReleaseDataFlagOn();</p>
<p>216 m_RemappingFilter-&gt;SetInput(m_RescaleFilter-&gt;GetOutput());</p>
<p>217</p>
<p>218 // Create the progress accumulator</p>
<p>219 m_ProgressAccumulator = itk::ProgressAccumulator::New();</p>
<p>220 m_ProgressAccumulator-&gt;SetMiniPipelineFilter(this);</p>
<p>221</p>
<p>222 // Register the filters with the progress accumulator</p>
<p>223 m_ProgressAccumulator-&gt;RegisterInternalFilter(m_CastFilter,0.1f);</p>
<p>224 m_ProgressAccumulator-&gt;RegisterInternalFilter(m_GaussianFilter,0.6f);</p>
<p>225 m_ProgressAccumulator-&gt;RegisterInternalFilter(m_GradientFilter,0.1f);</p>
<p>226 m_ProgressAccumulator-&gt;RegisterInternalFilter(m_RescaleFilter,0.1f);</p>
<p>227 m_ProgressAccumulator-&gt;RegisterInternalFilter(m_RemappingFilter,0.1f);</p>
<p>228 }</p>
<p>229</p>
<p>230 template&lt;typename TInputImage,typename TOutputImage&gt;</p>
<p>231 void</p>
<p>232 EdgePreprocessingImageFilter&lt;TInputImage,TOutputImage&gt;</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-&gt;GetInput();</p>
<p>237 typename OutputImageType::Pointer outputImage = this-&gt;GetOutput();</p>
<p>238</p>
<p>239 // Initialize the progress counter</p>
<p>240 m_ProgressAccumulator-&gt;ResetProgress();</p>
<p>241</p>
<p>242 // Allocate the output image</p>
<p>243 outputImage-&gt;SetBufferedRegion(outputImage-&gt;GetRequestedRegion());</p>
<p>244 outputImage-&gt;Allocate();</p>
<p>245</p>
<p>246 // Pipe in the input image</p>
<p>247 m_CastFilter-&gt;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-&gt;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-&gt;SetFunctor(functor);</p>
<p>264</p>
<p>265 // Call the filter&#39;s GenerateData()</p>
<p>266 m_RemappingFilter-&gt;GraftOutput(outputImage);</p>
<p>267 m_RemappingFilter-&gt;Update();</p>
<p>268</p>
<p>269 // graft the mini-pipeline output back onto this filter&#39;s output.</p>
<p>270 // this is needed to get the appropriate regions passed back.</p>
<p>271 GraftOutput( m_RemappingFilter-&gt;GetOutput() );</p>
<p>272</p>
<p>273 }</p>
<p>274</p>
<p>275 template&lt;typename TInputImage,typename TOutputImage&gt;</p>
<p>276 void</p>
<p>277 EdgePreprocessingImageFilter&lt;TInputImage,TOutputImage&gt;</p>
<p>278 ::PrintSelf(std::ostream&amp; os, Indent indent) const</p>
<p>279 {</p>
<p>280 Superclass::PrintSelf(os,indent);</p>
<p>281 }</p>
<p>282</p>
<p>283 template&lt;typename TInputImage,typename TOutputImage&gt;</p>
<p>284 void </p>
<p>285 EdgePreprocessingImageFilter&lt;TInputImage,TOutputImage&gt;</p>
<p>286 ::SetEdgePreprocessingSettings(const EdgePreprocessingSettings &amp;settings)</p>
<p>287 {</p>
<p>288 if(!(settings == m_EdgePreprocessingSettings))</p>
<p>289 {</p>
<p>290 m_EdgePreprocessingSettings = settings; </p>
<p>291 this-&gt;Modified();</p>
<p>292 }</p>
<p>293 }</p>
<p>294</p>
<p>295 template&lt;typename TInputImage,typename TOutputImage&gt;</p>
<p>296 void </p>
<p>297 EdgePreprocessingImageFilter&lt;TInputImage,TOutputImage&gt;</p>
<p>298 ::GenerateInputRequestedRegion()</p>
<p>299 {</p>
<p>300 // Make sure we call the parent&#39;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&lt; TInputImage * &gt;( this-&gt;GetInput() );</p>
<p>306 OutputImagePointer outputPtr = this-&gt;GetOutput();</p>
<p>307</p>
<p>308 // Use the largest possible region (hack)</p>
<p>309 inputPtr-&gt;SetRequestedRegion(</p>
<p>310 inputPtr-&gt;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>