[Insight-users] Python Wrapping: Return an itkImage Object

Luis Ibanez luis . ibanez at kitware . com
Tue, 28 Oct 2003 18:48:32 -0500


Hi Hua,


Thanks for your clear example.


What happens is that Python variables will assume
the type of the object that is assigned to them.

In your example, the member variable  "_image"
receives the type of  "reader.GetOutput()":

       self._image = reader.GetOutput()

but, GetOutput() methods in ITK return *raw* pointers
instead of *smartpointers* (and there are good reasons
for that... but let's skip them here)

So, the variable "self._image" is a raw pointer to
a ImageF2 object.  In the first example, (the one
that works), you are also holding the reader filter,
but this one is assigned from a "New()" method, which
returns a SmartPointer to a reader.  Therefore the
types of the two member variables are

  self._reader : SmartPointer to ImageFileReader F2
  self._image  : raw pointer to ImageF2

you can easily verify this by doing

   print self._reader
   print self._image

In this case, the reader keeps its output alive
after the end of the scope of the init method
(the constructor of your python class).

In the second case, (the one that crashes), the
reader is still holding a smartpointer, but this
time, it is not a member variable of the class.
Therefore it is destroyed at the end of the scope
of the constructor. The "self._image"  being just
a raw pointer cannot prevent the destruction of the
object it is pointing to, and can only watch how its
object is removed from memory.

The solution is to explicity create the "_image" variable
as a SmartPointer to an itkImageF2 and assign to it the raw
pointer returned by the reader, like:

   self._image = itkImageF2_Pointer( reader.GetOutput() );

Now the member variable  "self._image" is a SmartPointer
and it will keep alive the output of the reader even
though the reader itself will be destroyed.



The entire example will look like:


from InsightToolkit import *

class testReturnImage2:
     def __init__(self):
         reader = itkImageFileReaderF2_New()
         reader.SetFileName("image.png")
         reader.Update()
         self._image = itkImageF2_Pointer( reader.GetOutput() );

     def GetImage(self):
         return self._image

app2   = testReturnImage2()
image2 = app2.GetImage()
print "app2: updating image ... "
print image2
image2.Update()
print "      Done."

writer = itkImageFileWriterF2_New()
writer.SetFileName("output.mha")
writer.SetInput( image2.GetPointer() )
writer.Update()



Note that, as a final confirmation of the healthy state
of the image we create a writer and save the image into
a file.


Please let us know if you find any further problem.



Thanks


   Luis


---------------------------------------------------

Hua Qian wrote:
> Hi Glen,
> 
> Yes, a deep copy would solve my problem. However, I didn't
> find anything like that for itk::Image.
> 
> For you VTK to ITK connection problem, you can try to put
> "self." before all the filters you use, I bet the "seg. fault"
> will disappear. This "trick" works for both ITK to VTK and VTK
> to ITK connection. I don't know why, and I am still look for
> an answer. I guess it has something to do with reference counting.
> We have to keep references to all the filters to keep the image
> data pipeline alive.
>   Hua
> 
> 
> Glen Lehmann wrote:
> 
>> Hi Hua,
>>
>> I avoid this when converting from itk::Image to vtkImageData by doing 
>> the following;
>>
>>    def ITK2VTK(self, itkImage):
>>        # this will form the end-point of the ITK pipeline segment
>>        itkExporter = itk.itkVTKImageExportF2_New()
>>        itkExporter.SetInput( itkImage )
>>
>>        # the vtkImageImport will bring our data back into VTK-land
>>        vtkImporter = vtk.vtkImageImport()
>>
>>        # do the magic connection call (once again: only available if 
>> you built
>>        # ITK with ITK_CSWIG_CONNECTVTKITK set to ON)
>>        CVIPy.ConnectITKF2ToVTK(itkExporter.GetPointer(), vtkImporter)
>>
>>        imageData = vtk.vtkImageData()
>>        imageData.DeepCopy( vtkImporter.GetOutput() )
>>
>>        return imageData
>>
>> However, when converting from vtkImageData to itk::Image I get the 
>> same seg. faults that you do because I can't preform a deep copy 
>> operation on the itk::Image.  Is there an equivilant operation in itk?
>>
>> Glen
>>
>> Hua Qian wrote:
>>
>>> Hello,
>>>
>>> Here are two little python classes to test returning an
>>> itkImage object. One class works and the other gives
>>> segmentation fault. Could someone confirm that and
>>> explain why?
>>>
>>> Regards,
>>> Hua
>>>
>>> from InsightToolkit import *
>>>
>>> class testReturnImage1:
>>>    def __init__(self):
>>>        self._reader = itkImageFileReaderF2_New()
>>>        self._reader.SetFileName("../../Testing/Data/Input/cthead1.png")
>>>        self._image = self._reader.GetOutput()
>>>
>>>    def GetImage(self):
>>>        return self._image
>>>
>>> class testReturnImage2:
>>>    def __init__(self):
>>>        reader = itkImageFileReaderF2_New()
>>>        reader.SetFileName("../../Testing/Data/Input/cthead1.png")
>>>        self._image = reader.GetOutput()
>>>          def GetImage(self):
>>>        return self._image
>>>
>>> app1 = testReturnImage1()
>>> image = app1.GetImage()
>>> print "app1: updating image ... "
>>> image.Update()
>>> print "     Done."
>>>
>>> app2 = testReturnImage2()
>>> image2 = app2.GetImage()
>>> print "app2: updating image ... "
>>> image2.Update()
>>> print "      Done."
>>>
>>>
>>>
> 
> 
> _______________________________________________
> Insight-users mailing list
> Insight-users at itk . org
> http://www . itk . org/mailman/listinfo/insight-users
>