Code covered by the BSD License  

Highlights from
Resampling volume or image with affine matrix

4.66667

4.7 | 3 ratings Rate this file 51 Downloads (last 30 days) File Size: 5.38 KB File ID: #21080
image thumbnail

Resampling volume or image with affine matrix

by Jimmy Shen

 

13 Aug 2008 (Updated 16 Apr 2009)

Use affine matrix to convert 3D vol or 2D img to orthogonal one with corresponding affine matrix.

| Watch this File

File Information
Description

3D Affine matrix is such a 4x4 matrix:

M = [ [R T]; [0 0 0 1] ];
[x2 y2 z2 1]’ = M * [x1 y1 z1 1]’ ;

where, R is a 3x3 rotation matrix, and T is a 3x1 translation matrix. [x1 y1 z1] is a location in original 3D image volume, and [x2 y2 z2] is a location in transformed 3D image volume.

Although affine geometric transformation is only limited to parallel projection, it applies to most of the common geometric transformations, including rotation, translation, scaling, reflection, shearing, etc. Some of the common 3D Affine matrices are listed at the bottom of this description.

It may seem easy if you just want to apply the 3D affine matrix to each [x y z] coordinates in the 3D image volume. However, it turns out to be more complicated when you realize that the voxel (smallest element of 3D image volume) in the transformed image may no longer be an orthogonal cube. Therefore, a 3D interpolation algorithms must also be included to transform 3D image volume. I have implemented three interpolation methods in this program.

Usage: [new_img new_M] = affine(old_img, old_M, [new_elem_size], [verbose], [bg], [method]);

old_img - original 2D image or 3D volume. We assume x for the 1st dimension, y for the 2nd dimension, and z for the 3rd dimension.

old_M - a 3x3 2D affine matrix for 2D image, or a 4x4 3D affine matrix for 3D volume. We assume x for the 1st dimension, y for the 2nd dimension, and z for the 3rd dimension.

new_elem_size (optional) - size of voxel along x y z direction for a transformed 3D volume, or size of pixel along x y for a transformed 2D image. We assume x for the 1st dimension y for the 2nd dimension, and z for the 3rd dimension. 'new_elem_size' is 1 if it is default or empty.

verbose (optional) - 1, 0
   1: show transforming progress in percentage
   2: progress will not be displayed
   'verbose' is 1 if it is default or empty.

bg (optional) - background voxel intensity in any extra corner that is caused by 3D interpolation. 0 in most cases. 'bg' will be the average of two corner voxel intensities in original image volume, if it is default or empty.

method (optional) - 1, 2, or 3
   1: for Trilinear interpolation
   2: for Nearest Neighbor interpolation
   3: for Fischer's Bresenham interpolation
   'method' is 1 if it is default or empty.

I suggest that you should use Method 1 (Trilinear) unless you have good reasons to choose other methods. Method 2 (Nearest Neighbor) is slightly faster, but will bring larger interpolation error. The Method 3 (Fischer's Bresenham) is only an implementation to test the special algorithm, and you also need to download my 3D Bresenham's line generation program from:
http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=21057

new_img - transformed 3D image volume

new_M - transformed affine matrix

This program is inspired by:
SPM5 Software from Wellcome Trust Centre for Neuroimaging
http://www.fil.ion.ucl.ac.uk/spm/software
Fischer, J., A. del Rio (2004). A Fast Method for Applying Rigid Transformations to Volume Data, WSCG2004 Conference.
http://wscg.zcu.cz/wscg2004/Papers_2004_Short/M19.pdf

Although this program (affine3d.m) can also run on MATLAB earlier than version 6.5 (R13), the speed will be hundred times slower. So I suggest that you run this program on MATLAB version 6.5 (R13) and above.

The following script is a demo to show you how to use this program. The result is displayed in the above image.

Example 1 (3D rotation):
load mri.mat; old_img = double(squeeze(D));
old_M = [0.88 0.5 3 -90; -0.5 0.88 3 -126; 0 0 2 -72; 0 0 0 1];
new_img = affine(old_img, old_M, 2);
[x y z] = meshgrid(1:128,1:128,1:27);
sz = size(new_img);
[x1 y1 z1] = meshgrid(1:sz(2),1:sz(1),1:sz(3));
figure; slice(x, y, z, old_img, 64, 64, 13.5);
shading flat; colormap(map); view(-66, 66);
figure; slice(x1, y1, z1, new_img, sz(1)/2, sz(2)/2, sz(3)/2);
shading flat; colormap(map); view(-66, 66);

Example 2 (2D interpolation):
load mri.mat; old_img=D(:,:,1,13)';
old_M = [1 0 0; 0 1 0; 0 0 1];
new_img = affine(old_img, old_M, [.2 .4]);
figure; image(old_img); colormap(map);
figure; image(new_img); colormap(map);

Appendix: Common 3D Affine matrices:

Translation (displacement of [dX dY dZ] for all voxels):
old_M = [
 1 0 0 dX
 0 1 0 dY
 0 0 1 dZ
 0 0 0 1 ];

Rotation (about X axis):
old_M = [
 1 0 0 0
 0 cosX -sinX 0
 0 sinX cosX 0
 0 0 0 1 ];

Scaling:
old_M = [
 sX 0 0 0
 0 sY 0 0
 0 0 sZ 0
 0 0 0 1 ];

MATLAB release MATLAB 6.5 (R13)
Tags for This File  
Everyone's Tags
Tags I've Applied
Add New Tags Please login to tag files.
Comments and Ratings (5)
19 Aug 2008 jichao zhao

That is excellent, thanks for sharing.

20 Aug 2008 gg kiss

in the demo code the the size of new_img is different from the old you get some errors. To correct you can use:

sz = size(new_img)
[x1 y1 z1] = meshgrid(1:sz(2),1:sz(1),1:sz(3));
figure; slice(x1, y1, z1, new_img, 64, 64, 13);
shading flat; colormap(map); view(-66, 66);

25 Oct 2008 wafa BT

hi ....
it is verey nice ..
i would like to have help plz ..
 Ihave 3d array I insert slices to it and I need to compared 2 slices 4 pixel togather if it equal to the value than I will divided it by 8 and so on

16 Apr 2009 Hamid Sarve

Dear Jimmy,

Thank you for the contribution.

Translation seems buggy, at least it doesn't work at all for me. I've been using a
[ 1 0 0 dx;
 0 1 0 dy;
0 0 1 dz;
0 0 0 1;]
matrix.

The input and output volume are pretty much the same.

Regards,
Hamid

16 Apr 2009 Jimmy Shen

Hi Hamid:

The translation means the translation of the volume originator, which is specified by your affine matrix (old_M).

If there is no rotation, scaling, shearing, etc, the volume is untouched, and the new affine matrix (new_M) uses the translation that you specified.

In other words, with new_vol/new_M, you can plot a volume with the originator correctly translated. You can also do so with old_vol/old_M. So in your case, new_vol/new_M should be the same as old_vol/old_M, which is what we expected.

Keep in mind that this program is used to convert the oblique volume or image to orthogonal volume or image.

I think I need to change the title of this program to make it clearer.

Thank you for your feedback,
Jimmy

Please login to add a comment or rating.
Updates
15 Aug 2008

update program comments

19 Aug 2008

Updated Description above and listed Common 3D Affine matrices, including: Translation, reflection, yaw, pitch, roll, and scaling.

22 Aug 2008

Added a "verbose" parameter to provide an opportunity to disable the progress display.

24 Oct 2008

update didn't show up

16 Apr 2009

change title

Tag Activity for this File
Tag Applied By Date/Time
geometric transformation Jimmy Shen 22 Oct 2008 10:14:43
image registration Jimmy Shen 22 Oct 2008 10:14:43
3d Jimmy Shen 22 Oct 2008 10:14:43
image Jimmy Shen 22 Oct 2008 10:14:43
volume Jimmy Shen 22 Oct 2008 10:14:43
voxel Jimmy Shen 22 Oct 2008 10:14:43
mapping Jimmy Shen 22 Oct 2008 10:14:43
affine Jimmy Shen 22 Oct 2008 10:14:43
space Jimmy Shen 22 Oct 2008 10:14:43
transform Jimmy Shen 22 Oct 2008 10:14:43
2d Cristina McIntire 07 Nov 2008 12:44:05
3d Cristina McIntire 10 Nov 2008 10:55:04
image Cristina McIntire 10 Nov 2008 10:55:08
affine gyanendra sheoran 27 Jan 2009 12:22:03
2d Francisco 28 Oct 2009 19:46:04
2d MichaelK Kim 18 Aug 2010 22:25:52
affine Vincent Bonin 08 Oct 2010 18:38:20
volume Aijun Zhu 21 Apr 2011 12:58:28

Contact us at files@mathworks.com