<table cellspacing="0" cellpadding="0" border="0" ><tr><td valign="top" style="font: inherit;"><div>Thank you for clarifying your point,</div><div><br></div><div>Yes you are right, the itk::WarpImageFilter uses the deformation field to map a</div><div><br></div><div>point from the output space to the input space. This is basically resides in the difference</div><div><br></div><div>between a transformation and a warping, as in transformation a point from the input space</div><div><br></div><div>is mapped to the output space with no guarantees for back transformations or size </div><div><br></div><div>correspondence which is only natural since there are numerous types of transformations</div><div><br></div><div>with high levels of complexity and that would make it a fairly hard task to obtain the </div><div><br></div><div>inverse transformation (as you pointed out).</div><div><br></div><div>On the opposite side, the whole point of warping is
to map points from the output space to</div><div><br></div><div>the input space, hence the itk::WarpImageFilter does its work with inverse mapping, this</div><div><br></div><div>also avoids creation of holes and overlaps in the output image.</div><div><br></div><div>Best regards,</div><div><br></div><div>Dawood</div><div><br></div><div><br></div>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<div><br></div><div>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<br><br>--- On <b>Tue, 5/24/11, Gao, Yi
<i><gaoyi.cn@gmail.com></i></b> wrote:<br><blockquote style="border-left: 2px solid rgb(16, 16, 255); margin-left: 5px; padding-left: 5px;"><br>From: Gao, Yi <gaoyi.cn@gmail.com><br>Subject: Re: question on itkWarpImageFilter<br>To: "Dawood Masslawi" <davoud_zzz@yahoo.com><br>Cc: insight-users@itk.org<br>Date: Tuesday, May 24, 2011, 8:10 AM<br><br><div class="plainMail">Hi Dawood,<br><br>Thanks for the answer.<br><br>The reason I was asking is because that when previously dealing with<br>image transformation, I thought we need to know "where it is from"<br>from the transformation information, which tells "where to go".<br><br>For example, if image A is to be translated by 10 pixel to the RIGHT.<br>Then, we go through the new image, and for each pixel we find out<br>"where it is from": 10 pixel from the LEFT. Note in such cases, the<br>output image do NOT have to be the same size as the input one.<br>Moreover, if A is a simple binary
image with an object in the center,<br>then in the transformed image, the object would appear to be a little<br>on the right (on the screen, and assuming the output region is the<br>same as the input one.)<br><br>Therefore I thought for transformation with general vector deformation<br>field, this would be the same. However getting the inverse transform<br>from a vector field is in general difficult. So I asked the previous<br>question.<br><br>However, for transformation with vector deformation field, it does not<br>seems to be working that way. The transformation information (vector<br>field) directly tells "where it is from". I did the following<br>experiment:<br><br>1. I generate a 2D image A of the width 100 and height 50. In the<br>middle (middle of the left-right) 1/3 region it has some content.<br><br>2. I generate a vector field D, the 1st component of each vector is<br>10, and the 2nd component is 0. Therefore I hope this vector field to<br>do
the same as the translation above. And I expect the transformed<br>image, B, has the object moved to the RIGHT.<br><br>3. However, the result is opposites to that of the 2D Translation<br>Transformation. The object appears to the LEFT.<br><br>4. No problem, because this is consistent with the Software Guide:<br>p_in = p_out + deformationVector.<br><br>5. I think this confirms the behavior that the vector field tells<br>"where is from".<br><br>6. So seems that the we should say the deformation is defined on the<br>domain of the *output image*?<br><br><br><br>Here is my testing code:<br><br>#include "itkImage.h"<br>#include "itkImageFileWriter.h"<br>#include "itkWarpImageFilter.h"<br>#include "itkLinearInterpolateImageFunction.h"<br><br><br>template<typename itkImage_t><br>typename itkImage_t::Pointer generate_image(int nx, int ny);<br><br>template<typename deformation_t><br>typename deformation_t::Pointer generate_deformation_field(int nx,
int ny);<br><br>template<typename itkImage_t><br>void write_image(typename itkImage_t::Pointer im, std::string file_name);<br><br><br>int main( int argc, char * argv[] )<br>{<br> const unsigned int Dimension = 2;<br><br> typedef float VectorComponentType;<br> typedef itk::Vector< VectorComponentType, Dimension > VectorPixelType;<br> typedef itk::Image< VectorPixelType, Dimension > DeformationFieldType;<br><br> typedef unsigned char PixelType;<br> typedef itk::Image< PixelType, Dimension > ImageType;<br><br><br> int nx = 100;<br> int ny = 50;<br> ImageType::Pointer img = generate_image<ImageType>(nx, ny);<br><br> DeformationFieldType::Pointer deformationField
=<br>generate_deformation_field<DeformationFieldType>(nx, ny);<br><br> typedef itk::LinearInterpolateImageFunction< ImageType, double ><br>InterpolatorType;<br> InterpolatorType::Pointer interpolator = InterpolatorType::New();<br><br> typedef itk::WarpImageFilter< ImageType, ImageType,<br>DeformationFieldType > FilterType;<br> FilterType::Pointer filter = FilterType::New();<br> filter->SetInterpolator( interpolator );<br> filter->SetOutputSpacing( deformationField->GetSpacing() );<br> filter->SetOutputOrigin( deformationField->GetOrigin() );<br> filter->SetOutputDirection( deformationField->GetDirection() );<br> filter->SetDeformationField( deformationField );<br> filter->SetInput( img );<br> filter->Update();<br><br> write_image<ImageType>(img, "a.nrrd");<br>
write_image<ImageType>(filter->GetOutput(), "b.nrrd");<br> write_image<DeformationFieldType>(deformationField, "c.nrrd");<br><br> return EXIT_SUCCESS;<br>}<br><br>template<typename itkImage_t><br>typename itkImage_t::Pointer generate_image(int nx, int ny)<br>{<br> typename itkImage_t::IndexType start = {{0, 0}};<br> typename itkImage_t::SizeType size = {{nx, ny}};<br><br> typename itkImage_t::RegionType region;<br> region.SetSize(size);<br> region.SetIndex(start);<br><br> typename itkImage_t::Pointer img = itkImage_t::New();<br> img->SetRegions(region);<br> img->Allocate();<br> img->FillBuffer(0);<br><br> for (int ix = nx/3; ix < 2*nx/3; ++ix)<br> {<br> for (int iy = 0; iy < ny; ++iy)<br> {<br> typename itkImage_t::IndexType idx = {{ix,
iy}};<br><br> img->SetPixel(idx, static_cast<typename<br>itkImage_t::PixelType>(127*(sin(ix/2.0) + 1)));<br> }<br> }<br><br> return img;<br>}<br><br><br><br>template<typename deformation_t><br>typename deformation_t::Pointer generate_deformation_field(int nx, int ny)<br>{<br> typename deformation_t::IndexType start = {{0, 0}};<br> typename deformation_t::SizeType size = {{nx, ny}};<br><br> typename deformation_t::RegionType region;<br> region.SetSize(size);<br> region.SetIndex(start);<br><br> typename deformation_t::PixelType v;<br> v[0] = 0.0;<br> v[1] = 0.0;<br><br> typename deformation_t::Pointer deformationField = deformation_t::New();<br> deformationField->SetRegions(region);<br> deformationField->Allocate();<br> deformationField->FillBuffer(v);<br><br> for (int ix = 0;
ix < nx; ++ix)<br> {<br> for (int iy = 0; iy < ny; ++iy)<br> {<br> typename deformation_t::IndexType idx = {{ix, iy}};<br><br> //v[0] = ix/5.0;<br> v[0] = 10;<br> v[1] = 0;<br><br> deformationField->SetPixel(idx, v);<br> }<br> }<br><br> return deformationField;<br>}<br><br><br>template<typename itkImage_t><br>void write_image(typename itkImage_t::Pointer im, std::string file_name)<br>{<br> typedef itk::ImageFileWriter< itkImage_t > WriterType;<br> typename WriterType::Pointer writer = WriterType::New();<br> writer->SetFileName( file_name.c_str() );<br> writer->SetInput( im );<br><br> try<br> {<br>
writer->Update();<br> }<br> catch( itk::ExceptionObject & excp )<br> {<br> std::cerr << "Exception thrown " << std::endl;<br> std::cerr << excp << std::endl;<br> }<br><br> return;<br>}<br><br><br><br><br><br><br><br>On Tue, May 24, 2011 at 4:38 AM, Dawood Masslawi <<a ymailto="mailto:davoud_zzz@yahoo.com" href="/mc/compose?to=davoud_zzz@yahoo.com">davoud_zzz@yahoo.com</a>> wrote:<br>><br>> Hi Yi,<br>> Each vector in the deformation filed image has the same dimension as the input image,<br>> meaning that it has equal number of dimensions for each pixel corresponding to movement<br>> of the input pixel. Naturally the deformation field image would have the same size as<br>> the input image so it wold cover all the pixels in the input image.<br>> As for your third question, note
that the input and output image would also have the same<br>> size, so using the deformation field it is clear that which pixels correspond to each other.<br>> Hope this answers your questions,<br>> Dawood<br>><br>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<br>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<br>><br>> Dear group,<br>><br>> I'm a little confused about the itkWarpImageFilter....<br>><br>> 1. I understand that in computing the deformed (output) image, we<br>> should go
through the domain of the *output* image, and inversely<br>> trace back (according to the deformation vector field) to find the<br>> intensity in the input image.<br>><br>> 2. However, on page 242 of the software guide, above equation 6.21, we<br>> see that the deformation vector field (as a vector image) should have<br>> the same size as the *input* image. So the deformation field is<br>> defined on the domain of the *input* image.<br>><br>> 3. Then, go back to item 1, how do we achieve the inversion of the<br>> vector field so as it defines on the domain of the *output* image?<br>><br>> Is there anything I misunderstand? Thanks for any hint!<br>><br>> Best,<br>> yi<br></div></blockquote></div></td></tr></table>