comp.lang.idl-pvwave archive
Messages from Usenet group comp.lang.idl-pvwave, compiled by Paulo Penteado

Home » Public Forums » archive » Principle axes transform of image volumes
Show: Today's Messages :: Show Polls :: Message Navigator
E-mail to friend 
Switch to threaded view of this topic Create a new topic Submit Reply
Principle axes transform of image volumes [message #31167] Fri, 07 June 2002 03:19 Go to next message
Marcus O'Brien is currently offline  Marcus O'Brien
Messages: 16
Registered: October 2000
Junior Member
Hi,

I've been trying for a very long time now to implement a principle axes
transformation for the coregistration of MR image volumes. My rather
simplistic understanding of how this should work is:

Find centre of mass
Calculate inertia matrix of image in centre of mass coordinate system
Find eigenvalues and eigenvectors of inertia matrix
Matrix multiply centre of mass coordinates by eigenvectors then
transform back to cartesian coordinates

Voila image is rotated onto it's principle axes!

I should mention that I have no natural feel for maths and my 'play with
it till it works' approach to life has proved to be a dismal failure in
this project. I've tried many variations of code in the last months to
try to get the principle axes transform to work for 3D matricies.
Including a hack of Martin Downing's stunning transform_volume. I've
included the inertia matrix code, and principle axes code (minus all the
widget state variable stuff). These are loop versions as it may be
easier for someone to spot any obvious screw ups on my part, and the
matrix multiplication is (I think) quaternion, as playing with that
seemed to give something close to registration.

If anyone has any hints or observations (give up is acceptable, and very
close :) I'd be more than happy to hear them.

Thanks

Marc O'Brien

function Inertia3D, imagearray, com

; Calculate inertia matrix for image
sarr = size(imagearray)
x = sarr[1]
y = sarr[2]
z = sarr[3]
npix = x * y * z

inertia = dblarr(3,3)

for i=-com[0], (x-com[0])-1 do begin
for j=-com[1], (y-com[1])-1 do begin
for k=-com[2], (z-com[2])-1 do begin
pixelval = getpix_3dcom(i,j,k,com,imagearray)

; Moment of inertia = mass * distance ^ 2
; xx
temp = pixelval * (j^2 + k^2)
inertia[0,0] = inertia[0,0] + temp

; yy
temp = pixelval * (k^2 + i^2)
inertia[1,1] = inertia[1,1] + temp

; zz
temp = pixelval * (i^2 + j^2)
inertia[2,2] = inertia[2,2] + temp


; Products of inertia
; xy
temp = (pixelval * i * j)
inertia[0,1] = inertia[0,1] + temp

; xz
temp = (pixelval * i * k)
inertia[0,2] = inertia[0,2] + temp

; yz
temp = (pixelval * j * k)
inertia[1,2] = inertia[1,2] + temp
endfor
endfor
endfor


; Get mean
inertia[0,0] = inertia[0,0] / npix
inertia[1,1] = inertia[1,1] / npix
inertia[2,2] = inertia[2,2] / npix
inertia[0,1] = (inertia[0,1]) / npix
inertia[0,2] = (inertia[0,2]) / npix
inertia[2,1] = (inertia[2,1]) / npix

; zx
inertia[2,0] = inertia[0,2]
; yx
inertia[1,0] = inertia[0,1]
; zy
inertia[1,2] = inertia[2,1]

return, inertia
end


pro OnPax3D, event

<snip>
; Volumes are vol and nc although for testing both volumes have
; been the same with one rotated
; Get volume data
ivol = volarray[*,*,*]
inc = ncarray[*,*,*]
sizevol = size(ivol)
sizenc = size(inc)

; Get centers of mass
volcom=dblarr(3)
nccom=dblarr(3)
nccom=ROUND(COM_n(inc, /DOUBLE))-1
volcom=ROUND(COM_n(ivol,/DOUBLE))-1


; Calculate inertia matrix for vol image
I1 = Inertia3D(ivol,volcom)
; Calculate inertia matrix for nc image
I2 = Inertia3D(inc,nccom)

; Get eigencolumns for volume image
S1 = I1
TRIRED, S1, D1, E, /DOUBLE
TRIQL, D1, E, S1, /DOUBLE

; Get eigencolumns for non contrast volume
S2 = I2
TRIRED, S2, D2, F, /DOUBLE
TRIQL, D2, F, S2, /DOUBLE

; Create the rotation matrices
;R1 = S1 ## TRANSPOSE(S2)
;R2 = S2 ## TRANSPOSE(S1)
R1 = TRANSPOSE(S1)
R2 = TRANSPOSE(S2)

; Create arrays to store transformed images
newvol = dblarr(sizevol[1],sizevol[2],sizevol[3])
newnc = dblarr(sizenc[1],sizenc[2],sizenc[3])

; Get array dimension sizes
sxvol = sizevol[1]
syvol = sizevol[2]
szvol = sizevol[3]
sxnc = sizenc[1]
sync = sizenc[2]
sznc = sizenc[3]

quartmat1 = dblarr(4,4)
quartmat1[3,*] = 0
quartmat1[*,3] = 0
quartmat1[3,3] = 1
quartmat1[0:2,0:2] = R1
quartmat2 = dblarr(4,4)
quartmat2[3,*] = 0
quartmat2[*,3] = 0
quartmat2[3,3] = 1
quartmat2[0:2,0:2] = R2

print, quartmat1
print
print, quartmat2

quartvec = TRANSPOSE([1,1,1,1])
newquartvec = TRANSPOSE([1,1,1,1])

; Back to the loops
for z=0, szvol-1 do begin
for y=0, syvol-1 do begin
for x=0, sxvol-1 do begin
curpix = [x,y,z]

; Convert to centre of mass coordinates
curpix = curpix - volcom
quartvec[0:2] = curpix
newquartvec = quartmat1 ## quartvec
; Convert back to cartessian
newquartvec[0:2] = newquartvec[0:2] + volcom
newquartvec = ABS(FIX(newquartvec))
; Check for outliers
if newquartvec[0] GE sxvol then newquartvec[0] = sxvol -1
if newquartvec[1] GE syvol then newquartvec[1] = syvol -1
if newquartvec[2] GE szvol then newquartvec[2] = szvol -1
; Copy pixel location
newvol[x,y,z] = ivol[newquartvec[0],newquartvec[1],newquartvec[2]]

; Repeat for second image
curpix = [x,y,z]
curpix = curpix - nccom
quartvec[0:2] = curpix
newquartvec = quartmat2 ## quartvec
newquartvec[0:2] = newquartvec[0:2] + nccom
newquartvec = ABS(FIX(newquartvec))
if newquartvec[0] GE sxnc then newquartvec[0] = sxnc -1
if newquartvec[1] GE sync then newquartvec[1] = sync -1
if newquartvec[2] GE sznc then newquartvec[2] = sznc -1
newnc[x,y,z] = inc[newquartvec[0],newquartvec[1],newquartvec[2]]
endfor ; x
endfor ; y
endfor ; z
<snip>
end

--
Tel: 0208 725 2857
Fax: 0208 725 2992

St George's Hospital Medical School
Department of Biochemistry and Immunology
Cranmer Terrace
Tooting
London SW17 0RE
Re: Principle axes transform of image volumes [message #32912 is a reply to message #31167] Thu, 14 November 2002 15:35 Go to previous message
David Fanning is currently offline  David Fanning
Messages: 11724
Registered: August 2001
Senior Member
Martin Downing (martin.downing@ntlworld.com) writes:

> And yes I have been in hiding!

Well, it's good of you to show up again. We missed
you. :-)

Cheers,

David
--
David W. Fanning, Ph.D.
Fanning Software Consulting, Inc.
Phone: 970-221-0438, E-mail: david@dfanning.com
Coyote's Guide to IDL Programming: http://www.dfanning.com/
Toll-Free IDL Book Orders: 1-888-461-0155
Re: Principle axes transform of image volumes [message #32916 is a reply to message #31167] Thu, 14 November 2002 14:38 Go to previous message
Martin Downing is currently offline  Martin Downing
Messages: 136
Registered: September 1998
Senior Member
Hi Marc,

I just came across this posting of yours in the archive while doing some
work writing a routine for principle moments of inertia for point masses.
It appeared as though you never got any replies, and I noticed that in
Inertia3D you have the wrong sign for your products of inertia (they should
be negative)

I.E should be:
; Products of inertia
; xy
temp = (pixelval * i * j)
inertia[0,1] = inertia[0,1] - temp

NOT:
inertia[0,1] = inertia[0,1] + temp

Hope this is of help. (but probably not anymore!).

regards

Martin

ps. Cant remember how to reply to a message on the google archive - hence
this mess. And yes I have been in hiding!


Marc's original posting on 7/6/2002 follows:
------------------------------------------------------------ ----------------
------------
From: m.obrien@sghms.ac.uk (m.obrien@sghms.ac.uk)
Subject: Principle axes transform of image volumes
This is the only article in this thread
View: Original Format
Newsgroups: comp.lang.idl-pvwave
Date: 2002-06-07 03:25:47 PST


Hi,

I've been trying for a very long time now to implement a principle axes
transformation for the coregistration of MR image volumes. My rather
simplistic understanding of how this should work is:

Find centre of mass
Calculate inertia matrix of image in centre of mass coordinate system
Find eigenvalues and eigenvectors of inertia matrix
Matrix multiply centre of mass coordinates by eigenvectors then
transform back to cartesian coordinates

Voila image is rotated onto it's principle axes!

I should mention that I have no natural feel for maths and my 'play with
it till it works' approach to life has proved to be a dismal failure in
this project. I've tried many variations of code in the last months to
try to get the principle axes transform to work for 3D matricies.
Including a hack of Martin Downing's stunning transform_volume. I've
included the inertia matrix code, and principle axes code (minus all the
widget state variable stuff). These are loop versions as it may be
easier for someone to spot any obvious screw ups on my part, and the
matrix multiplication is (I think) quaternion, as playing with that
seemed to give something close to registration.

If anyone has any hints or observations (give up is acceptable, and very
close :) I'd be more than happy to hear them.

Thanks

Marc O'Brien

function Inertia3D, imagearray, com

; Calculate inertia matrix for image
sarr = size(imagearray)
x = sarr[1]
y = sarr[2]
z = sarr[3]
npix = x * y * z

inertia = dblarr(3,3)

for i=-com[0], (x-com[0])-1 do begin
for j=-com[1], (y-com[1])-1 do begin
for k=-com[2], (z-com[2])-1 do begin
pixelval = getpix_3dcom(i,j,k,com,imagearray)

; Moment of inertia = mass * distance ^ 2
; xx
temp = pixelval * (j^2 + k^2)
inertia[0,0] = inertia[0,0] + temp

; yy
temp = pixelval * (k^2 + i^2)
inertia[1,1] = inertia[1,1] + temp

; zz
temp = pixelval * (i^2 + j^2)
inertia[2,2] = inertia[2,2] + temp


; Products of inertia
; xy
temp = (pixelval * i * j)
inertia[0,1] = inertia[0,1] + temp

; xz
temp = (pixelval * i * k)
inertia[0,2] = inertia[0,2] + temp

; yz
temp = (pixelval * j * k)
inertia[1,2] = inertia[1,2] + temp
endfor
endfor
endfor


; Get mean
inertia[0,0] = inertia[0,0] / npix
inertia[1,1] = inertia[1,1] / npix
inertia[2,2] = inertia[2,2] / npix
inertia[0,1] = (inertia[0,1]) / npix
inertia[0,2] = (inertia[0,2]) / npix
inertia[2,1] = (inertia[2,1]) / npix

; zx
inertia[2,0] = inertia[0,2]
; yx
inertia[1,0] = inertia[0,1]
; zy
inertia[1,2] = inertia[2,1]

return, inertia
end


pro OnPax3D, event

<snip>
; Volumes are vol and nc although for testing both volumes have
; been the same with one rotated
; Get volume data
ivol = volarray[*,*,*]
inc = ncarray[*,*,*]
sizevol = size(ivol)
sizenc = size(inc)

; Get centers of mass
volcom=dblarr(3)
nccom=dblarr(3)
nccom=ROUND(COM_n(inc, /DOUBLE))-1
volcom=ROUND(COM_n(ivol,/DOUBLE))-1


; Calculate inertia matrix for vol image
I1 = Inertia3D(ivol,volcom)
; Calculate inertia matrix for nc image
I2 = Inertia3D(inc,nccom)

; Get eigencolumns for volume image
S1 = I1
TRIRED, S1, D1, E, /DOUBLE
TRIQL, D1, E, S1, /DOUBLE

; Get eigencolumns for non contrast volume
S2 = I2
TRIRED, S2, D2, F, /DOUBLE
TRIQL, D2, F, S2, /DOUBLE

; Create the rotation matrices
;R1 = S1 ## TRANSPOSE(S2)
;R2 = S2 ## TRANSPOSE(S1)
R1 = TRANSPOSE(S1)
R2 = TRANSPOSE(S2)

; Create arrays to store transformed images
newvol = dblarr(sizevol[1],sizevol[2],sizevol[3])
newnc = dblarr(sizenc[1],sizenc[2],sizenc[3])

; Get array dimension sizes
sxvol = sizevol[1]
syvol = sizevol[2]
szvol = sizevol[3]
sxnc = sizenc[1]
sync = sizenc[2]
sznc = sizenc[3]

quartmat1 = dblarr(4,4)
quartmat1[3,*] = 0
quartmat1[*,3] = 0
quartmat1[3,3] = 1
quartmat1[0:2,0:2] = R1
quartmat2 = dblarr(4,4)
quartmat2[3,*] = 0
quartmat2[*,3] = 0
quartmat2[3,3] = 1
quartmat2[0:2,0:2] = R2

print, quartmat1
print
print, quartmat2

quartvec = TRANSPOSE([1,1,1,1])
newquartvec = TRANSPOSE([1,1,1,1])

; Back to the loops
for z=0, szvol-1 do begin
for y=0, syvol-1 do begin
for x=0, sxvol-1 do begin
curpix = [x,y,z]

; Convert to centre of mass coordinates
curpix = curpix - volcom
quartvec[0:2] = curpix
newquartvec = quartmat1 ## quartvec
; Convert back to cartessian
newquartvec[0:2] = newquartvec[0:2] + volcom
newquartvec = ABS(FIX(newquartvec))
; Check for outliers
if newquartvec[0] GE sxvol then newquartvec[0] = sxvol -1
if newquartvec[1] GE syvol then newquartvec[1] = syvol -1
if newquartvec[2] GE szvol then newquartvec[2] = szvol -1
; Copy pixel location
newvol[x,y,z] = ivol[newquartvec[0],newquartvec[1],newquartvec[2]]

; Repeat for second image
curpix = [x,y,z]
curpix = curpix - nccom
quartvec[0:2] = curpix
newquartvec = quartmat2 ## quartvec
newquartvec[0:2] = newquartvec[0:2] + nccom
newquartvec = ABS(FIX(newquartvec))
if newquartvec[0] GE sxnc then newquartvec[0] = sxnc -1
if newquartvec[1] GE sync then newquartvec[1] = sync -1
if newquartvec[2] GE sznc then newquartvec[2] = sznc -1
newnc[x,y,z] = inc[newquartvec[0],newquartvec[1],newquartvec[2]]
endfor ; x
endfor ; y
endfor ; z
<snip>
end

--
Tel: 0208 725 2857
Fax: 0208 725 2992

St George's Hospital Medical School
Department of Biochemistry and Immunology
Cranmer Terrace
Tooting
London SW17 0RE



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

--
----------------------------------------
Martin Downing,
Clinical Research Physicist,
Grampian Orthopaedic RSA Research Centre,
Woodend Hospital, Aberdeen, AB15 6LS.
  Switch to threaded view of this topic Create a new topic Submit Reply
Previous Topic: idl obj gaphics and opengl - how similar?
Next Topic: 3D Skeletonization

-=] Back to Top [=-
[ Syndicate this forum (XML) ] [ RSS ] [ PDF ]

Current Time: Wed Oct 08 15:57:17 PDT 2025

Total time taken to generate the page: 0.00694 seconds