<div>Hi Karl,</div><div><br></div><div>I&#39;m glad to hear that you got it working.  I have the cosines going down the columns of the matrix, so that the matrix transforms &quot;raw data&quot; coordinates into patient coordinates.  In other words, option (1).</div>


<div><br></div><div>I was trying to remember why I chose that option... and I think this is the reason: the Z direction cosine vector is not always orthogonal to the X and Y cosine vectors.  In a tilted-gantry CT scan, the volume is rhombus-shaped, and the Z direction cosine is the direction in which the gantry moves between slices (i.e. not the cross product of the X and Y vectors).  In this case, you will get the correct transform if you choose option (1), but will get the wrong transform if you choose option (2).</div>


<div><br></div><div>Most DICOM scans provide an orthogonal volume, and for these it makes no difference.  It is only with the rare non-orthogonal scan volumes that the difference becomes apparent.</div><div><br></div><div>


  David</div><br><div class="gmail_quote">On Mon, Nov 22, 2010 at 12:35 PM, Karl <span dir="ltr">&lt;<a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


David,<br>
<br>
Thanks for the help.  I have gotten it to work.  It was an issue with a<br>
matrix being transposed when it shouldn&#39;t.  I have one final question.  When<br>
I load the directional cosines from the header should they go into the rows<br>
or columns of the directional cosine matrix.<br>
<br>
For example I get the same results if I:<br>
1) load the cosines into columns of matrix, multiply origin by inverse, and<br>
multiply data set by cosine matrix<br>
2) load the cosines into rows of matrix, multiply origin by matrix, multiply<br>
data set by inverse of cosine matrix<br>
<br>
I know these are the same thing mathematically, but which one is correct<br>
based on convention.  I believe the first one is correct.<br>
<br>
Thanks for all the help getting this to work.<br>
<font color="#888888"><br>
Karl<br>
</font><div><br>
-----Original Message-----<br>
From: <a href="mailto:vtkusers-bounces@vtk.org" target="_blank">vtkusers-bounces@vtk.org</a> [mailto:<a href="mailto:vtkusers-bounces@vtk.org" target="_blank">vtkusers-bounces@vtk.org</a>] On Behalf<br>
Of David Gobbi<br>
</div><div><div></div><div>Sent: Friday, November 19, 2010 4:22 PM<br>
To: <a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a><br>
Subject: Re: [vtkusers] using itk transform in vtk<br>
<br>
Hi Karl,<br>
<br>
I meant to reply to you this morning but was distracted by other tasks...<br>
<br>
The DICOM code that I have (which is actually written in Python) does<br>
things like this:<br>
<br>
        matrix = vtk.vtkMatrix4x4()<br>
        for j in range(3):<br>
            matrix.SetElement(j,0,rowOrientation[j])<br>
            matrix.SetElement(j,1,columnOrientation[j])<br>
            matrix.SetElement(j,2,sliceOrientation[j])<br>
<br>
The above code builds the direction cosines from the DICOM<br>
orientation, the slice orientation is the cross product of the other<br>
two orientations.  Then, to convert the DICOM position into the<br>
ImageData origin, I use the following.  This code is so old it uses<br>
Python Numeric... but I&#39;ll give it to you raw, and you can figure out<br>
how to do the same thing with vtkMatrix4x4.<br>
<br>
        origin = Numeric.array(position)<br>
        dircos = Numeric.transpose(Numeric.array([rowOrientation,<br>
columnOrientation, sliceOrientation]))<br>
        origin = list(LinearAlgebra.solve_linear_equations(dircos,origin))<br>
<br>
I apologize for the python code, but as you can see, your own code<br>
more-or-less duplicates what I do.  So all that I can suggest is the<br>
following:<br>
<br>
1) Check the value that reader-&gt;GetDataOrigin() returns.  Make sure<br>
that it really is the same as the ImagePositionPatient value in the<br>
DICOM header.<br>
<br>
2) Check the math, just to make sure that matrices aren&#39;t accidentally<br>
transposed or any of the other mistakes that we often make.<br>
<br>
  David<br>
<br>
<br>
On Fri, Nov 19, 2010 at 12:00 PM, Karl &lt;<a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a>&gt; wrote:<br>
&gt; David,<br>
&gt; Thanks for walking me through another way.  I have attempted to implement<br>
&gt; what you propose, but am not doing something quite right.  Would you mind<br>
&gt; reviewing my procedure below and pointing out where I go wrong.  I suspect<br>
&gt; it is with the origin.  The following code is called twice, once for the<br>
&gt; non-transformed data, and once for the transformed data, hopefully they<br>
show<br>
&gt; up in the same spot:)<br>
&gt;<br>
&gt; // load data<br>
&gt; vtkGDCMImageReader *reader = vtkGDCMImageReader::New();<br>
&gt; reader-&gt;SetFileName( filename );<br>
&gt; reader-&gt;SetFileLowerLeft(1); // do not recalculate origin or y-flip data<br>
&gt;<br>
&gt; // get directional cosines<br>
&gt; double directionalCosines[3][3];<br>
&gt;<br>
image-&gt;GetImageOrientationPatient(directionalCosines[0][0],directionalCosine<br>
&gt; s[0][1],<br>
&gt;<br>
&gt;<br>
directionalCosines[0][2],directionalCosines[1][0],directionalCosines[1][1],<br>
&gt;    directionalCosines[1][2]);<br>
&gt; directionalCosines[2][0] =<br>
&gt;<br>
directionalCosines[0][1]*directionalCosines[1][2]-directionalCosines[0][2]*d<br>
&gt; irectionalCosines[1][1];<br>
&gt; directionalCosines[2][1] =<br>
&gt;<br>
directionalCosines[0][2]*directionalCosines[1][0]-directionalCosines[0][0]*d<br>
&gt; irectionalCosines[1][2];<br>
&gt; directionalCosines[2][2] =<br>
&gt;<br>
directionalCosines[0][0]*directionalCosines[1][1]-directionalCosines[0][1]*d<br>
&gt; irectionalCosines[1][0];<br>
&gt;<br>
&gt; // create directional cosine matrix, transforms from raw data space to<br>
&gt; patient space<br>
&gt; vtkMatrix4x4* dc = vtkMatrix4x4::New();<br>
&gt; dc-&gt;Identity();<br>
&gt; dc-&gt;SetElement(0,0,directionalCosines[0][0]);<br>
&gt; dc-&gt;SetElement(0,1,directionalCosines[0][1]);<br>
&gt; dc-&gt;SetElement(0,2,directionalCosines[0][2]);<br>
&gt; dc-&gt;SetElement(1,0,directionalCosines[1][0]);<br>
&gt; dc-&gt;SetElement(1,1,directionalCosines[1][1]);<br>
&gt; dc-&gt;SetElement(1,2,directionalCosines[1][2]);<br>
&gt; dc-&gt;SetElement(2,0,directionalCosines[2][0]);<br>
&gt; dc-&gt;SetElement(2,1,directionalCosines[2][1]);<br>
&gt; dc-&gt;SetElement(2,2,directionalCosines[2][2]);<br>
&gt;<br>
&gt; // inverse directional cosine matrix, transform from patient space to raw<br>
&gt; data space<br>
&gt; vtkMatrix4x4* dcInverse = vtkMatrix4x4::New();<br>
&gt; dc-&gt;Invert(dc,dcInverse);<br>
&gt;<br>
&gt; // calculate new origin, transform from patient space to raw data space<br>
&gt; double origin[4];<br>
&gt; origin[3]=1;<br>
&gt; reader-&gt;GetDataOrigin(origin);<br>
&gt; dcInverse-&gt;MultiplyPoint(origin,origin);<br>
&gt;<br>
&gt; // apply new origin<br>
&gt; vtkImageChangeInformation* information = vtkImageChangeInformation::New();<br>
&gt; information-&gt;SetOutputOrigin(origin[0], origin[1], origin[2]);<br>
&gt; information-&gt;SetInputConnection(reader-&gt;GetOutputPort());<br>
&gt;<br>
&gt; // create polydata<br>
&gt; vtkMarchingCubes* march = vtkMarchingCubes::New();<br>
&gt; march-&gt;SetInputConnection(information-&gt;GetOutputPort());<br>
&gt;<br>
&gt; // transform polydata from raw data space to patient space<br>
&gt; vtkTransformPolyDataFilter* transformToPatientSpace =<br>
&gt; vtkTransformPolyDataFilter::New();<br>
&gt; vtkTransform* matrixTransform = vtkTransform::New();<br>
&gt; matrixTransform-&gt;SetMatrix(dc);<br>
&gt; transformToPatientSpace-&gt;SetTransform(matrixTransform);<br>
&gt; transformToPatientSpace-&gt;SetInputConnection(march-&gt;GetOutputPort());<br>
&gt;<br>
&gt; //*************************************<br>
&gt; // this section is only called for the non-transformed data<br>
&gt; // load and apply itk transform<br>
&gt; vtkMatrix4x4* itkMatrix =<br>
&gt; [param0 param1 param2 param9]<br>
&gt; [param3 param4 param5 param10]<br>
&gt; [param6 param7 param8 param11]<br>
&gt; [0 0 0 1] // from itk writing out matrix<br>
&gt; itkMatrix-&gt;Invert(itkMatrix,itkMatrix); // itk actually provides inverse<br>
&gt; transforms<br>
&gt;<br>
&gt; vtkTransform* matrixTransform = vtkTransform::New();<br>
&gt; matrixTransform-&gt;SetMatrix(itkMatrix);<br>
&gt;<br>
&gt; vtkTransformPolyDataFilter* itkTransform =<br>
&gt; vtkTransformPolyDataFilter::New();<br>
&gt; itkTransform-&gt;SetTranform(matrixTransform);<br>
&gt;<br>
itkTransform-&gt;SetInputConnection(transformToPatientSpace-&gt;GetOutputPort());<br>
&gt; **************************************//<br>
&gt;<br>
&gt; // display polydata<br>
&gt; vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();<br>
&gt; mapper-&gt;SetInputConnection(transformToPatientSpace -&gt;GetOutputPort());<br>
&gt;<br>
&gt; vtkActor* actor = vtkActor::New();<br>
&gt; actor-&gt;SetMapper(mapper);<br>
&gt;<br>
&gt;<br>
&gt; I believe I am accomplishing the following.<br>
&gt; Load the data already transformed by itk (data A).  Apply transform to<br>
&gt; change it from raw data space to patient space.  Display data.   VTK space<br>
&gt; now corresponds to this patient space.<br>
&gt;<br>
&gt; Load untransformed data (data B).  Apply transform to change it from its<br>
raw<br>
&gt; data space to its patient space.  Apply inverse itk transform to change it<br>
&gt; from its patient space to data A&#39;s patient space.  Display data.<br>
&gt;<br>
&gt; Thanks<br>
&gt;<br>
&gt;<br>
&gt; -----Original Message-----<br>
&gt; From: <a href="mailto:vtkusers-bounces@vtk.org" target="_blank">vtkusers-bounces@vtk.org</a> [mailto:<a href="mailto:vtkusers-bounces@vtk.org" target="_blank">vtkusers-bounces@vtk.org</a>] On Behalf<br>
&gt; Of David Gobbi<br>
&gt; Sent: Thursday, November 18, 2010 4:55 PM<br>
&gt; To: <a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a><br>
&gt; Subject: Re: [vtkusers] using itk transform in vtk<br>
&gt;<br>
&gt; I haven&#39;t looked into gdcmreslice myself, but the procedure that you<br>
&gt; have outlined is very different from what I have used with DICOM<br>
&gt; files.  What I do is as follows:<br>
&gt;<br>
&gt; 1) Read the image as-is, i.e. do not allow the reader to flip it or do<br>
&gt; any other adjustments.  Computing the vtkImageData Origin is tricky,<br>
&gt; this Origin is in VTK&#39;s &quot;data coordinate space&quot; for the vtkImageData,<br>
&gt; while DICOM&#39;s ImagePositionPatient is in DICOM patient coordinates.<br>
&gt; So I have to use the direction cosines matrix (see step 3) to convert<br>
&gt; ImagePositionPatient to the vtkImageData Origin that I use.<br>
&gt;<br>
&gt; 2) Compute the Z spacing by measuring the distance between adjacent<br>
&gt; DICOM slices, and checking the direction of the cross product of x, y<br>
&gt; direction cosines from ImageOrientationPatient to make sure the slices<br>
&gt; are in the right order<br>
&gt;<br>
&gt; 3) Use the direction cosines to create an &quot;image orientation matrix&quot;.<br>
&gt; I do not re-order the axes of the image with vtkImageReslice (as far<br>
&gt; as I&#39;m concerned, doing so just complicates the whole process, and<br>
&gt; cannot account for oblique orientations)<br>
&gt;<br>
&gt; So at this point, I have a DICOM image with X as the row direction<br>
&gt; (left-to-right), Y as the column direction (top-to-bottom), and Z as<br>
&gt; the slice direction.  I also have a vtkMatrix4x4 that is a<br>
&gt; transformation matrix from this &quot;raw&quot; coordinate system to the DICOM<br>
&gt; patient coordinate system.  Then, I identify one of my DICOM data sets<br>
&gt; as my &quot;primary&quot; data set, and identify its DICOM patient coordinate<br>
&gt; system as being identical to my VTK world coordinate system.<br>
&gt;<br>
&gt; When doing registrations, I use a vtkTransform that converts from the<br>
&gt; DICOM patient coordinates of one image, to the DICOM patient<br>
&gt; coordinates of another image.  Each of these images also has a<br>
&gt; vtkMatrix4x4 that contains its direction cosines, which relate the<br>
&gt; vtkImageData data coordinates to the DICOM patient coordinates of that<br>
&gt; image.<br>
&gt;<br>
&gt; By doing the above, I keep the various coordinate spaces as<br>
&gt; compartmentalizes as possible.  I avoid flipping the image or<br>
&gt; resampling it along a new set of axes because that tends to make<br>
&gt; things more confusing, I prefer to just store a direction cosines<br>
&gt; matrix for each image and leave the data alone.<br>
&gt;<br>
&gt;  David<br>
&gt;<br>
&gt;<br>
&gt; On Thu, Nov 18, 2010 at 2:25 PM, Karl &lt;<a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a>&gt; wrote:<br>
&gt;&gt; Mathieu + vtk community,<br>
&gt;&gt; Thanks for replying.  I looked into gdcmrelice.cxx example today.  I was<br>
&gt;&gt; unsuccessful in using that approach to achieve results.  In case it<br>
&gt; matters<br>
&gt;&gt; I have gdcm 2.0.16 and vtk 5.4.2.<br>
&gt;&gt;<br>
&gt;&gt; If I understand correctly the following process is applied:<br>
&gt;&gt; 1)Load image with vtkGDCMImageReader.  Due to differences in origin the<br>
&gt;&gt; reader shifts the origin along the y-axis (based on the directional<br>
&gt; cosines)<br>
&gt;&gt; and reverses the order of the slices along the y direction.<br>
&gt;&gt;<br>
&gt;&gt; 2)This reversal of order along the y-axis also results in the x-axis<br>
&gt;&gt; appearing flipped, so the vtkImageFlip filter is used to undo that<br>
effect.<br>
&gt;&gt;<br>
&gt;&gt; 3)vtkImageReslice is then used to reorientate the data to lie along the<br>
&gt;&gt; actual dicom x,y,z axes instead of the row, column, slice sampling of the<br>
&gt;&gt; data set.  This doesn&#39;t seem the best approach because it results in<br>
&gt;&gt; obliquely resampling the entire data set.<br>
&gt;&gt; Using this approach does not work correctly.  The data does appear with<br>
&gt; RAH<br>
&gt;&gt; orientation but does not get placed correctly.<br>
&gt;&gt;<br>
&gt;&gt; My code goes something like this:<br>
&gt;&gt; vtkGDCMImageReader *reader = vtkGDCMImageReader::New();<br>
&gt;&gt; reader-&gt;SetFileName( filename );<br>
&gt;&gt;<br>
&gt;&gt; vtkImageFlip *flip = vtkImageFlip::New();<br>
&gt;&gt; flip-&gt;SetInput(reader -&gt;GetOutput());<br>
&gt;&gt; flip-&gt;SetFilteredAxis(0);<br>
&gt;&gt; flip-&gt;Update();<br>
&gt;&gt;<br>
&gt;&gt; vtkImageReslice *reslice = vtkImageReslice::New();<br>
&gt;&gt; reslice-&gt;SetInput(flip-&gt;GetOutput());<br>
&gt;&gt; vtkMatrix4x4 *invert = vtkMatrix4x4::New();<br>
&gt;&gt; invert-&gt;DeepCopy(reader-&gt;GetDirectionCosines() );<br>
&gt;&gt; invert-&gt;Invert();<br>
&gt;&gt; reslice-&gt;SetResliceAxes(invert);<br>
&gt;&gt; reslice-&gt;Update();<br>
&gt;&gt;<br>
&gt;&gt; vtkMarchingCubes* march = vtkMarchingCubes::New();<br>
&gt;&gt; march-&gt;SetInputConnection(reslice-&gt;GetOutputPort());<br>
&gt;&gt;<br>
&gt;&gt; // create transform matrix<br>
&gt;&gt; vtkMatrix4x4* matrix = vtkMatrix4x4::New(); ...<br>
&gt;&gt; vtkTransform* matrixTransform = vtkTransform::New();<br>
&gt;&gt; matrixTransform-&gt;SetMatrix(matrix);<br>
&gt;&gt;<br>
&gt;&gt; vtkTransformPolyDataFilter* transform =<br>
vtkTransformPolyDataFilter::New();<br>
&gt;&gt; transform-&gt;SetTranform(matrixTransform);<br>
&gt;&gt; transform-&gt;SetInputConnection(march-&gt;GetOutputPort());<br>
&gt;&gt;<br>
&gt;&gt; vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();<br>
&gt;&gt; mapper-&gt;SetInputConnection(transform-&gt;GetOutputPort());<br>
&gt;&gt;<br>
&gt;&gt; vtkActor* actor = vtkActor::New();<br>
&gt;&gt; actor-&gt;SetMapper(mapper);<br>
&gt;&gt;<br>
&gt;&gt; This is basically done twice.  Once with the original data and the<br>
&gt; transform<br>
&gt;&gt; from ITK, and once with the data set that has already been transformed by<br>
&gt;&gt; ITK and an identity transform.  The two objects do not appear in the same<br>
&gt;&gt; location.  The dicom images do start out having different origins and<br>
&gt;&gt; directional cosines.  But if both are mapped to physical space correctly<br>
&gt;&gt; they should overlap exactly.<br>
&gt;&gt;<br>
&gt;&gt; Thanks<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; -----Original Message-----<br>
&gt;&gt; From: Mathieu Malaterre [mailto:<a href="mailto:mathieu.malaterre@gmail.com" target="_blank">mathieu.malaterre@gmail.com</a>]<br>
&gt;&gt; Sent: Thursday, November 18, 2010 7:04 AM<br>
&gt;&gt; To: <a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a><br>
&gt;&gt; Subject: Re: [vtkusers] using itk transform in vtk<br>
&gt;&gt;<br>
&gt;&gt; Have you tried the gdcmreslice.cxx example in GDCM ? Is it working for<br>
yuo<br>
&gt; ?<br>
&gt;&gt;<br>
&gt;&gt; Thx<br>
&gt;&gt;<br>
&gt;&gt; On Thu, Nov 18, 2010 at 6:20 AM, Karl &lt;<a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt; Vtk folks and David,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Thanks for responding.  I have yet to have success, but I believe I have<br>
&gt;&gt;&gt; addressed the issues you point out.<br>
&gt;&gt;&gt; I am using vtkGDCMImageReader with the FileLowerLeft flag set to 0.  If<br>
I<br>
&gt;&gt;&gt; understand correctly this importer correctly flips the Y and adjusts the<br>
&gt;&gt;&gt; origin.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; ITK transform is about the 0,0,0 physical coordinate.  When I load the<br>
&gt;&gt; image<br>
&gt;&gt;&gt; in itk the origin information should be used by this importer to<br>
properly<br>
&gt;&gt;&gt; position the image so that the 0,0,0 physical coordinate corresponds to<br>
&gt;&gt; the<br>
&gt;&gt;&gt; 0,0,0 vtk location.  The inverse of the itk transform can then be<br>
&gt; directly<br>
&gt;&gt;&gt; applied to the imported image.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; This still does not work however.  I need to somehow get the vtk<br>
&gt;&gt; coordinate<br>
&gt;&gt;&gt; system to accurately represent the physical coordinate system so that<br>
&gt;&gt;&gt; objects from different dicom images, with different origins and<br>
&gt;&gt; directional<br>
&gt;&gt;&gt; cosines, appear in proper relation to each other.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Any suggestions on how to proceed?<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Thanks<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; -----Original Message-----<br>
&gt;&gt;&gt; From: David Gobbi [mailto:<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>]<br>
&gt;&gt;&gt; Sent: Tuesday, November 16, 2010 4:31 PM<br>
&gt;&gt;&gt; To: <a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a><br>
&gt;&gt;&gt; Cc: <a href="mailto:vtkusers@vtk.org" target="_blank">vtkusers@vtk.org</a><br>
&gt;&gt;&gt; Subject: Re: [vtkusers] using itk transform in vtk<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Hi Karl,<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The VTK transform operates on the physical origin, which can be at any<br>
&gt;&gt;&gt; desired location in the image.  The relationship between DICOM<br>
&gt;&gt;&gt; coordinates and VTK coordinates is explained thusly:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; DICOM has three fields related to the positions of the image voxels in<br>
&gt;&gt;&gt; physical (or patient) space:<br>
&gt;&gt;&gt; - ImagePositionPatient (position of upper right corner)<br>
&gt;&gt;&gt; - ImageOrientationPatient (row and column directions)<br>
&gt;&gt;&gt; - PixelSpacing (X and Y)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; VTK image data has two fields (no orientation):<br>
&gt;&gt;&gt; - Origin (position of lower right corner)<br>
&gt;&gt;&gt; - Spacing (X, Y, and Z)<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Note that the image data &quot;Origin&quot; is a misnomer, it is not the<br>
&gt;&gt;&gt; physical origin of the coordinate system.  It is just the position of<br>
&gt;&gt;&gt; the voxel in the lower left corner.  It is the responsibility of the<br>
&gt;&gt;&gt; VTK image reader that you are using to set the Origin and Spacing of<br>
&gt;&gt;&gt; the data correctly.  (And again, I will repeat that what VTK calls the<br>
&gt;&gt;&gt; image &quot;Origin&quot; is not the physical image origin, it is just a<br>
&gt;&gt;&gt; position).<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; The fundamental difference between these two coordinate systems is not<br>
&gt;&gt;&gt; the location of the origin, it is a vertical flip since DICOM images<br>
&gt;&gt;&gt; are top-to-bottom while VTK images are bottom-to-top.  When dealing<br>
&gt;&gt;&gt; with DICOM, I set the VTK image &quot;origin&quot; to the DICOM<br>
&gt;&gt;&gt; ImagePositionPatient, and then apply a view transform that flips the<br>
&gt;&gt;&gt; image by using a rotation of 180 degrees about the X axis.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;  - David<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On Tue, Nov 16, 2010 at 2:02 PM, Karl &lt;<a href="mailto:bulkmailaddress@gmail.com" target="_blank">bulkmailaddress@gmail.com</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt; Hi,<br>
&gt;&gt;&gt;&gt; I am trying to use an itk transform in vtk.  Here is a high level<br>
&gt;&gt; overview<br>
&gt;&gt;&gt;&gt; of what I do:<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 1) In itk use itk::ImageRegistrationMethod with itk::AffineTransform to<br>
&gt;&gt;&gt; find<br>
&gt;&gt;&gt;&gt; a transform.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 2) I use itk::ResampleImageFilter to create an image transformed using<br>
&gt;&gt; the<br>
&gt;&gt;&gt;&gt; itk::AffineTransform.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 3) I use the GetLastTransformParameters() function to get the affine<br>
&gt;&gt;&gt;&gt; transformation matrix to use in vtk as.<br>
&gt;&gt;&gt;&gt; [param0 param1 param2 param9]<br>
&gt;&gt;&gt;&gt; [param3 param4 param5 param10]<br>
&gt;&gt;&gt;&gt; [param6 param7 param8 param11]<br>
&gt;&gt;&gt;&gt; [0 0 0 1]<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 4) Now in vtk I try to display both the resampled image and the<br>
original<br>
&gt;&gt;&gt;&gt; image with the transform applied.  They should show as exactly the same<br>
&gt;&gt; if<br>
&gt;&gt;&gt; I<br>
&gt;&gt;&gt;&gt; can apply the transform in vtk the same as it is applied in itk.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 5) I load both images in vtk.  The images are binary so I use marching<br>
&gt;&gt;&gt; cubes<br>
&gt;&gt;&gt;&gt; to create meshes of them.  I display the transformed image polydata as<br>
&gt;&gt; is.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 6) I apply a vtkTransform to the original image polydata.  I do this by<br>
&gt;&gt;&gt;&gt; concatenating 3 vtkMatrix4x4. Two to adjust for different origins in<br>
itk<br>
&gt;&gt;&gt; and<br>
&gt;&gt;&gt;&gt; vtk and one for the itk transform.<br>
&gt;&gt;&gt;&gt; Translate_Back * itkTransform * Translate_itk_origin_to_vtk_origin<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Where<br>
&gt;&gt;&gt;&gt; itkTransform is as shown in 3 above.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Translate_itk_origin_to_vtk_origin is<br>
&gt;&gt;&gt;&gt; [1 0 0 -originX]<br>
&gt;&gt;&gt;&gt; [0 1 0 -originY]<br>
&gt;&gt;&gt;&gt; [0 0 1 -originZ]<br>
&gt;&gt;&gt;&gt; [0 0 0 1]<br>
&gt;&gt;&gt;&gt; Where the origin is as found in the dicom header for the original image<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Translate_Back<br>
&gt;&gt;&gt;&gt; [1 0 0 originX]<br>
&gt;&gt;&gt;&gt; [0 1 0 originY]<br>
&gt;&gt;&gt;&gt; [0 0 1 originZ]<br>
&gt;&gt;&gt;&gt; [0 0 0 1]<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 7) Set vtkTransform inverse flag and transform and display the original<br>
&gt;&gt;&gt;&gt; image.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; 8) The two objects show up at different places in the scene instead of<br>
&gt; at<br>
&gt;&gt;&gt;&gt; the same location.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; If I understand this correctly the itk transform is to be applied about<br>
&gt;&gt;&gt; the<br>
&gt;&gt;&gt;&gt; physical origin.  Not the location of the corner pixel or the center of<br>
&gt;&gt;&gt; the<br>
&gt;&gt;&gt;&gt; image.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; The vtk transform uses an origin at the corner of the image.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; By translating by the origin defined in the dicom header I move the<br>
&gt;&gt;&gt; physical<br>
&gt;&gt;&gt;&gt; origin to the corner pixel of the image.  This corrects for the<br>
&gt;&gt;&gt;&gt; discrepancies between the point with itk and vtk apply their<br>
transforms.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Also the itk transform goes from output to input, so the inverse<br>
&gt;&gt; transform<br>
&gt;&gt;&gt;&gt; needs to be applied in vtk.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Can anyone see what I am missing?<br>
&gt;&gt;&gt;&gt; Thanks<br></div></div></blockquote></div>