3

I am using Matlab to transform an image to target image. I have geometric transformation(tform).

for example this is my 'tform':

    1.0235    0.0022   -0.0607         0
   -0.0276    1.0002    0.0089         0
   -0.0170   -0.0141    1.1685         0
   12.8777    5.0311  -70.0325    1.0000

In Matlab2013, it is possible to do it easily using imwarp:

%nii = 3D MR Image
I = nii.img; 
dii=nii.hdr.dime.pixdim(2:4);
Rfixed=imref3d(size(I),dii(2),dii(1),dii(3));    
new_img= imwarp(old_img, Rfixed, tform, 'OutputView', Rfixed);

the result is perfect using imwarp (red lung in the image)

enter image description here

I need to know how imwarp is working, Then I wrote my own function

function [new_img] = aff3d(old_img, tform, range_x, range_y, range_z)

   [U, V, W] = ndgrid(range_x, range_y, range_z);
   xyz = [reshape(U,[],1)';reshape(V,[],1)';reshape(W,[],1)'];
   xyz = [xyz; ones(1,size(xyz,2))];


   uvw = tform.T * xyz;
   % avoid homogeneous coordinate  
   uvw = uvw(1:3,:)';


   xi = reshape(uvw(:,1), length(range_x),length(range_y),length(range_z));
   yi = reshape(uvw(:,2), length(range_x),length(range_y),length(range_z));
   zi = reshape(uvw(:,3), length(range_x),length(range_y),length(range_z));

   old_img = single(old_img);
   new_img = interp3(old_img,yi,xi,zi,'linear');

   ii = find(isnan(new_img));
   if(~isempty(ii))
      new_img(ii) = 0;
   end
end

enter image description here

the result of my function (more info) is not match with imwarp output ( red lung is not locating in a correct place), anybody can help me?

Community
  • 1
  • 1
Ehsan
  • 517
  • 1
  • 7
  • 32
  • "I need to know how imwarp is working" how about looking at its implementation? `open imwarp` shows the source code – m.s. May 25 '15 at 11:43
  • @m.s. I did but main functions are Mex file and I cannot see the code – Ehsan May 25 '15 at 11:53
  • Try multiplying by inv(TFORM . T) – Ander Biguri May 25 '15 at 12:12
  • @AnderBiguri not working by inv. I am thinking why imwarp of Matlab needs `imref3d`. There is something inside that i dont know. is my method implemented wrong? – Ehsan May 25 '15 at 13:13
  • Try uvw=uvw(1:3,:)'./uvw(4,:) – Ander Biguri May 25 '15 at 13:50
  • @AnderBiguri i lose the image if I divide it. the dimension of above command is not correct but I can do `uvw = uvw(1:3,:)' ./ [uvw(4,:); uvw(4,:); uvw(4,:)]'; ` but as I said it is not working too. im disappointed now. – Ehsan May 25 '15 at 14:05
  • 1
    What does tform. T returns if called in the command window ? – Ander Biguri May 25 '15 at 14:42
  • @AnderBiguri `tform.T` returns like the example (4x4 matrix) that i have shown above, tform is a structure. and geometric transformation matrix is in tform.T – Ehsan May 25 '15 at 14:48
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/78702/discussion-between-ehsan-and-ander-biguri). – Ehsan May 25 '15 at 14:56
  • I just found this, maybe its a key ,http://www.mathworks.com/matlabcentral/answers/67114-what-is-the-difference-between-imwarp-and-imtransform – Ehsan May 25 '15 at 16:52
  • 1
    Could you share why you would want to do exactly what imwarp already does for you? I assume there are all sorts of padding/boundary issues that the mex file takes care of for you, it would not be trivial to try reproducing all that numerics exactly. – Ashish Uthama May 25 '15 at 21:00
  • @Ahish good question, I need motion field and as you said before i used transformationpointforward function. But the motion i take from that function is different from imwarp result. I need to know how exactly imwarp working to get the correct motion field. Since by using imwarp my transformation looks perfect. Thanks – Ehsan May 26 '15 at 01:40
  • 1
    One last comment, the source for IMWARP IS available. The only functions that are compiled MEX are the interpolation routines. Everything else is in MATLAB. Conceptually, you should be able to review all aspects of the IMWARP implementation by stepping through the MATLAB code as needed. – Alex Taylor May 26 '15 at 14:37

1 Answers1

3

As was suggested by Ander, try multiplying by the inverse transformation:

Tinv = tform.invert();
TinvMatrix = Tinv.T;

So your code would become:

function [new_img] = aff3d(old_img, tform, range_x, range_y, range_z)
   [U, V, W] = ndgrid(range_x, range_y, range_z);
   xyz = [reshape(U,[],1)';reshape(V,[],1)';reshape(W,[],1)'];
   xyz = [xyz; ones(1,size(xyz,2))];

   tformInv = invert(tform);
   uvw = tformInv.T * xyz;
   % avoid homogeneous coordinate  
   uvw = uvw(1:3,:)';
   xi = reshape(uvw(:,1), length(range_x),length(range_y),length(range_z));
   yi = reshape(uvw(:,2), length(range_x),length(range_y),length(range_z));
   zi = reshape(uvw(:,3), length(range_x),length(range_y),length(range_z));
   old_img = single(old_img);
   new_img = interp3(old_img,yi,xi,zi,'linear');
   ii = find(isnan(new_img));
   if(~isempty(ii))
      new_img(ii) = 0;
   end
end

In your code, you are interpolating within the old_img to try to find the new_img which has been warped. This implies that what you want to do is use the inverse mapping that maps from the output image space to the input image space. You appear to be interpolating your old image using the forward mapping of points, which is incorrect.

http://blogs.mathworks.com/steve/2006/04/28/spatial-transforms-forward-mapping/ http://blogs.mathworks.com/steve/2006/05/05/spatial-transformations-inverse-mapping/

I would use the above links to review forward vs. inverse mapping. IMWARP uses inverse mapping.

Part of the reason for confusion is that when people think of geometric transformations, they generally think in terms of the forward mapping of how points map from the old_image to the new_image. For this reason, the "T" property of the affine3d transformation is phrased in terms of the forward mapping.

When geometric transformations need to be implemented in software, it's much easier/better to implement things in terms of the inverse mapping. That is what imwarp does, and that's why you need to invert the transformation while you are trying to reproduce the imwarp behavior. If you read the blog post on inverse mapping, this algorithm is exactly what IMWARP is doing.

The only wrinkle you will need to work through is what IMWARP does in non-default coordinate systems (using non-default spatial referencing objects) in the case where the WorldLimits are not evenly divisible by the discrete grid of pixels. This behavior is arbitrary, there is no "right" behavior. The IMWARP behavior is to to honor the requested resolution (PixelExtentInWorld) and to slightly adjust the world limits in this case.

Alex Taylor
  • 1,402
  • 1
  • 9
  • 15
  • I have inversed Tform as @Ander and you said, but the image is not still matching with imwarp. It may because of world coordinate system. I used matlab source code and I solved my problem. Thanks for your help – Ehsan May 26 '15 at 16:01
  • 1
    The insight about the inverse mapping vs forward mapping was very helpful, thanks a lot! – gaborous May 02 '20 at 22:49