<font size="2"><font face="verdana,sans-serif">Take a look at the example: </font></font><font size="2"><font face="verdana,sans-serif"><a href="http://vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/itkVtkImageConvert" target="_blank">http://vtk.org/Wiki/VTK/Examples/Cxx/VolumeRendering/itkVtkImageConvert</a><br>


</font></font><div><font face="verdana, sans-serif"><br></font></div>If I call GetMatrix before the line &quot;volume-&gt;SetOrigin(...)&quot;, it returns identity. If I call it after SetPosition, it contains the translation part.<div>

<br></div><div>I usually convert DICOM data to MetaImage format which is more convenient, but still preserves the crucial metadata. For the image in the screenshot I manually edited the image and set an orientation 45 degrees rotated to coordinate frame, because the orientations usually do not visibly deviate from coordinate axes. The point of ITK is to deliver these values to us.</div>

<div><br></div><div>When I get to university tomorrow I will send you the image in question with some accompanying polydata so you can also experiment yourself. The data size is above the list limit, so I will not send it to the list.<br>

<div><font face="verdana, sans-serif"><br></font><div class="gmail_quote">2011/7/5 David Gobbi <span dir="ltr">&lt;<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">


What did you set the image Origin to?  As I said, it should be set to zero.  So by calling volume-&gt;SetOrigin(-origin), my guess is that you were essentially cancelling the origin you had set in the image.<div><br></div>





<div>When you say GetMatrix() returns an identity matrix, do you mean that you get an identity matrix after doing the following:</div><div><br></div><div>[ set the elements of a 4x4 matrix ]</div><div>volume-&gt;SetUserMatrix(matrix);</div>





<div>newmatrix = volume-&gt;GetMatrix();</div><div><br></div><div>the &quot;newmatrix&quot; is identity, even though &quot;matrix&quot; was not?  Because that is not what I see myself... I see a &quot;newmatrix&quot; that is the result of compositing my &quot;matrix&quot; with whatever other transformations have been set for the volume (i.e. via SetOrigin(), SetPosition(), SetOrientation()).  I.e. the final transform matrix used by the volume is your usermatrix _plus_ the other transformations.</div>





<div><br></div><div>In any case, if you have to call SetPosition(), SetOrigin() on the volume, then there must be something you have not accounted for in the matrix.  Either that, or you have set the Origin of your vtkImageData when you shouldn&#39;t have.</div>





<div><br></div><div>Also, please note that my discussion assumes that you retrieved the DICOM Spacing, Orientation, and Position directly from the DICOM header.  I&#39;m assuming that ITK is not manipulating these values in any way before presenting them to you.</div>


<div><div></div><div>


<div><br></div><div> - David<br><div><br></div><div><br><div class="gmail_quote">2011/7/5 Dženan Zukić <span dir="ltr">&lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">





<font size="2"><font face="verdana,sans-serif">I built matrix myself and used SetUserMatrix. But that did not work. In addition to that I had to use SetPosition and SetOrigin. My question was why did I have to do that in addition to the manually constructed matrix which also contained translation part.<br>







</font></font><div><font face="verdana, sans-serif"><br></font></div><div><font face="verdana, sans-serif">Without any manual trickery GetMatrix returns an identity matrix. The spacing which is taken from vtkImage is not in that matrix, but somewhere else. The other information (orientation and position) is completely ignored.</font></div>







<div><font face="verdana, sans-serif"><br></font></div><div><font face="verdana, sans-serif">Regards,</font></div><div><font face="verdana, sans-serif">Dženan</font></div><div><div></div><div>

<div><font face="verdana, sans-serif"><br></font><div class="gmail_quote">2011/7/5 David Gobbi <span dir="ltr">&lt;<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">







The best way to work out coordinate transformation is to consider what happens to the position of a single pixel (I,J,K) in the image.<br><br>DICOM transformations go like this: first, there is a stack of images where each pixel identified by column and row, i.e. by (I,J,0) indices (for now, I&#39;m just considering a single slice so the Z index is zero).  These are then multiplied by the column and row spacing, to get (I*sx, J*sy, 0).  Then they are multiplied by the Orientation matrix, which is constructed by creating a 3x3 matrix where the first two columns are from the ImageOrientationPatient tag in the header, and the third column (usually) the cross product of the first two columns.  Finally, the last step in creating (x,y,z) patient coordinates is to add the ImagePositionPatient to the stretched and rotated (I,J,0) pixel indices.  So, that is how patient coordinates are computed for DICOM images.<br>









<br>In VTK, the (I,J,K) indices of the voxels are called the &quot;structured coords&quot; of the image.  To convert these to VTK&#39;s &quot;data coords&quot;, i.e. what VTK uses for polydata and for the mappers, the IJK indices have to be multiplied by the image Spacing (just like they are multiplied by the spacing for DICOM) and then the Origin is added to these values to get VTK &quot;data coordinates.&quot;  Finally, the data coordinates are multiplied by a 4x4 matrix (the vtkProp3D&#39;s matrix, i.e. the matrix that is composed of the position and rotation of the vtkVolume).  This results in VTK &quot;world coordinates&quot;.<br>









<br>In summary:<br>DICOM -&gt; scale by Spacing, rotate by Orientation, translate by Position<br>VTK -&gt; scale by Spacing, translate by Origin, then rotate and translate by a 4x4 matrix<br><br>There is nothing in DICOM that corresponds to the Origin of a VTK image data, i.e. in DICOM the scale operation is followed directly by the rotation.  So when dealing with pure DICOM patient coords in VTK, the image Origin should generally be set to (0,0,0).  Furthermore, the DICOM Orientation and Position become subsumed into a singe 4x4 VTK matrix transformation.  The 4x4 matrix is constructed from the 3x3 DICOM orientation matrix, and the last column is set to the DICOM Position.<br>









<br>Now what I said about the Origin always being set to zero... that represents the &quot;purest&quot; way of expressing DICOM patient coords in VTK.  But it is not the only way.  Another choice would be to take the DICOM Position, multiply it by the inverse of the orientation matrix, and then set the Origin to that.  In that case, the &quot;translation&quot; part of the VTK 4x4 matrix would be zero.<br>









<br>Finally, getting to your question about calling SetOrigin() and SetPosition() on the vtkVolume.  The vtkVolume, as I discussed, has an internal 4x4 matrix (that you can get by calling volume-&gt;GetMatrix()), and this matrix is constructed from the Origin, Orientation, and Position of the vtkVolume.  The order of operations here is that the 4x4 matrix is constructed by translating by the _negative_ of the origin, rotating by the orientation, and translating once again by the position.  But the Orientation is a nasty issue here... there is no easy way to figure out the angles you would need to use for SetOrientation to achieve the correct ImageOrientationPatient for your DICOM.  However, it is straightforward to directly construct a 4x4 matrix as I discussed above.  So my recommendation is to _never, ever_ use the SetOrigin(), SetOrientation(), and SetPosition() methods when visualizing DICOM data.  Instead, build the 4x4 rotation+position matrix yourself, and use SetUserMatrix() to attach it to your volume.<div>









<br></div><div>The reason that SetOrigin() and SetPosition() worked for you is that, by setting both to the same value, you end up changing the center of rotation.  But heed my advice: if you want to do things quantitatively, the best way to do so is by building the 4x4 transformation matrix yourself.  Letting VTK build it for you is IMHO just adding a lot of extra unknowns into the mix.</div>









<div><br></div><div> - David<br><br><br><br><br>2011/7/5 Dženan Zukić &lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;:<div><div></div><div><br>&gt; I solved this (see my other mail). But I still don&#39;t know why I had to set<br>









&gt; origin and position:<br>&gt; volume-&gt;SetOrigin(-origin[0], -origin[1], -origin[2]);<br>&gt; volume-&gt;SetPosition(-origin[0], -origin[1], -origin[2]);<br>&gt; Can you explain it? Also, a link to some text explaining vtk&#39;s coordinate<br>









&gt; transformation system for future reference would be very appreciated (if<br>&gt; such a text exists). I had been searching but could not find a source which<br>&gt; explains in which order are the transformation matrices applied, in which<br>









&gt; space are voxels of a vtkVolume etc.<br>&gt; Regards,<br>&gt; Dženan<br>&gt; 2011/7/1 Dženan Zukić &lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;<br>&gt;&gt;<br>&gt;&gt; I did the math, and it should be as simple as this:<br>









&gt;&gt;<br>&gt;&gt; VisualizingImageType::DirectionType d=logic-&gt;visualizing-&gt;GetDirection();<br>&gt;&gt; vtkMatrix4x4 *mat=vtkMatrix4x4::New(); //identity matrix<br>&gt;&gt; for (int i=0; i&lt;3; i++)<br>&gt;&gt;     for (int k=0; k&lt;3; k++)<br>









&gt;&gt;         mat-&gt;SetElement(i,k, d(i,k));<br>&gt;&gt; VisualizingImageType::PointType origin=logic-&gt;visualizing-&gt;GetOrigin();<br>&gt;&gt; for (int i=0; i&lt;3; i++)<br>&gt;&gt;     mat-&gt;SetElement(i,3, origin[i]);<br>









&gt;&gt; //mat-&gt;Invert(); //inverse produces even wrong orientation<br>&gt;&gt; volume-&gt;SetUserMatrix(mat);<br>&gt;&gt; However this does not work. This is a simple transformation from scaled<br>&gt;&gt; index space (vtkVolume handles spacing) to DICOM physical space. If no one<br>









&gt;&gt; has any suggestion, I will simply have to create a system of linear<br>&gt;&gt; equations from which to construct the VTK&#39;s transform matrix. And equations<br>&gt;&gt; I will have to obtain by passing a number of points through ITK&#39;s<br>









&gt;&gt; transformation and add some simple objects to the vtk scene at that spot and<br>&gt;&gt; on index space spot but with VTK transformation applied.<br>&gt;&gt; Regards,<br>&gt;&gt; Dženan<br>&gt;&gt; 2011/6/29 Dženan Zukić &lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;<br>









&gt;&gt;&gt;<br>&gt;&gt;&gt; I tried trial and error: premultiply translation, postmultiply, divide by<br>&gt;&gt;&gt; and multiply by spacing, all that unsuccessfully. Now I need to work out the<br>&gt;&gt;&gt; math :D<br>









&gt;&gt;&gt;<br>&gt;&gt;&gt; 2011/6/29 David Gobbi &lt;<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>&gt;<br>&gt;&gt;&gt;&gt;<br>&gt;&gt;&gt;&gt; Hi Dzenan,<br>&gt;&gt;&gt;&gt;<br>&gt;&gt;&gt;&gt; For your code, my guess is that the &quot;translation&quot; part of the 4x4<br>









&gt;&gt;&gt;&gt; matrix should be set to something like the origin multiplied by the<br>&gt;&gt;&gt;&gt; rotation matrix, but there might be other little details that you need<br>&gt;&gt;&gt;&gt; to take care of.  My only suggestion is that you don&#39;t try to fix it<br>









&gt;&gt;&gt;&gt; through trial-end-error.  Use pencil-and-paper to work through the<br>&gt;&gt;&gt;&gt; math.<br>&gt;&gt;&gt;&gt;<br>&gt;&gt;&gt;&gt;  - David<br>&gt;&gt;&gt;&gt;<br>&gt;&gt;&gt;&gt; 2011/6/29 Dženan Zukić &lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;:<br>









&gt;&gt;&gt;&gt; &gt; Hi David,<br>&gt;&gt;&gt;&gt; &gt;<br>&gt;&gt;&gt;&gt; &gt; with this I try to do what you suggested, i.e. consider VTK&#39;s world<br>&gt;&gt;&gt;&gt; &gt; coordinate system as DICOM patient coordinate system:<br>









&gt;&gt;&gt;&gt; &gt; //red is the transformation-related code<br>&gt;&gt;&gt;&gt; &gt; void MainWindow::updateVisualization()<br>&gt;&gt;&gt;&gt; &gt; {<br>&gt;&gt;&gt;&gt; &gt;     typedef itk::ImageToVTKImageFilter&lt;VisualizingImageType&gt;<br>









&gt;&gt;&gt;&gt; &gt; itkVtkConverter;<br>&gt;&gt;&gt;&gt; &gt;     itkVtkConverter::Pointer conv=itkVtkConverter::New();<br>&gt;&gt;&gt;&gt; &gt;     conv-&gt;SetInput(logic-&gt;visualizing);<br>&gt;&gt;&gt;&gt; &gt;     vtkGPUVolumeRayCastMapper *mapper =<br>









&gt;&gt;&gt;&gt; &gt; vtkGPUVolumeRayCastMapper::New();<br>&gt;&gt;&gt;&gt; &gt;     mapper-&gt;SetInput(conv-&gt;GetOutput());<br>&gt;&gt;&gt;&gt; &gt;     if (volume)<br>&gt;&gt;&gt;&gt; &gt;         volume-&gt;Delete();<br>









&gt;&gt;&gt;&gt; &gt;     volume=vtkVolume::New();<br>&gt;&gt;&gt;&gt; &gt;     volume-&gt;SetProperty( myTransferFunction );<br>&gt;&gt;&gt;&gt; &gt;     volume-&gt;SetMapper( mapper );<br>&gt;&gt;&gt;&gt; &gt;     mapper-&gt;SetBlendModeToComposite();<br>









&gt;&gt;&gt;&gt; &gt;     VisualizingImageType::DirectionType<br>&gt;&gt;&gt;&gt; &gt; d=logic-&gt;visualizing-&gt;GetDirection();<br>&gt;&gt;&gt;&gt; &gt;     vtkMatrix4x4 *mat=vtkMatrix4x4::New();<br>&gt;&gt;&gt;&gt; &gt;     for (int i=0; i&lt;3; i++)<br>









&gt;&gt;&gt;&gt; &gt;         for (int k=0; k&lt;3; k++)<br>&gt;&gt;&gt;&gt; &gt;             mat-&gt;SetElement(i,k, d(i,k));<br>&gt;&gt;&gt;&gt; &gt;     mat-&gt;SetElement(3,3, 1);<br>&gt;&gt;&gt;&gt; &gt;     VisualizingImageType::SpacingType sp =<br>









&gt;&gt;&gt;&gt; &gt; logic-&gt;visualizing-&gt;GetSpacing();<br>&gt;&gt;&gt;&gt; &gt;     VisualizingImageType::PointType<br>&gt;&gt;&gt;&gt; &gt; origin=logic-&gt;visualizing-&gt;GetOrigin();<br>&gt;&gt;&gt;&gt; &gt;     for (int i=0; i&lt;3; i++)<br>









&gt;&gt;&gt;&gt; &gt;         mat-&gt;SetElement(i,3, origin[i]/sp[i]);<br>&gt;&gt;&gt;&gt; &gt;     volume-&gt;SetUserMatrix(mat); //orientation and size OK, position<br>&gt;&gt;&gt;&gt; &gt; wrong<br>&gt;&gt;&gt;&gt; &gt;     vtkRenderer *renderer =<br>









&gt;&gt;&gt;&gt; &gt; vis-&gt;GetRenderWindow()-&gt;GetRenderers()-&gt;GetFirstRenderer();<br>&gt;&gt;&gt;&gt; &gt;     renderer-&gt;RemoveAllViewProps();<br>&gt;&gt;&gt;&gt; &gt;     renderer-&gt;AddVolume( volume );<br>









&gt;&gt;&gt;&gt; &gt;     defaultCameraPos(); //centers view on the volume, looking at it<br>&gt;&gt;&gt;&gt; &gt; from<br>&gt;&gt;&gt;&gt; &gt; left<br>&gt;&gt;&gt;&gt; &gt;     vis-&gt;GetRenderWindow()-&gt;Render();<br>









&gt;&gt;&gt;&gt; &gt;<br>&gt;&gt;&gt;&gt; &gt;<br>&gt;&gt;&gt;&gt; &gt; vis-&gt;GetRenderWindow()-&gt;GetRenderers()-&gt;GetFirstRenderer()-&gt;ResetCamera();<br>&gt;&gt;&gt;&gt; &gt; }<br>&gt;&gt;&gt;&gt; &gt; The polygonal data is in DICOM&#39;s patient coordinate system (vertex<br>









&gt;&gt;&gt;&gt; &gt; positions<br>&gt;&gt;&gt;&gt; &gt; from itk::Image-&gt;TransformIndexToPhysicalPoint() etc). The orientation<br>&gt;&gt;&gt;&gt; &gt; is<br>&gt;&gt;&gt;&gt; &gt; correct, but I can&#39;t get the position correctly. I have tried<br>









&gt;&gt;&gt;&gt; &gt; -origin[i]/sp[i], origin[i]*sp[i], origin[i], -origin[i], -2*origin[i]<br>&gt;&gt;&gt;&gt; &gt; and<br>&gt;&gt;&gt;&gt; &gt; similar combinations but none of them worked. Any suggestion to what<br>&gt;&gt;&gt;&gt; &gt; am I<br>









&gt;&gt;&gt;&gt; &gt; doing wrong?<br>&gt;&gt;&gt;&gt; &gt; Regards,<br>&gt;&gt;&gt;&gt; &gt; Dženan<br>&gt;&gt;&gt;&gt; &gt; 2011/6/29 David Gobbi &lt;<a href="mailto:david.gobbi@gmail.com" target="_blank">david.gobbi@gmail.com</a>&gt;<br>









&gt;&gt;&gt;&gt; &gt;&gt;<br>&gt;&gt;&gt;&gt; &gt;&gt; On Tue, Jun 28, 2011 at 9:40 AM, Dženan Zukić &lt;<a href="mailto:dzenanz@gmail.com" target="_blank">dzenanz@gmail.com</a>&gt;<br>&gt;&gt;&gt;&gt; &gt;&gt; wrote:<br>







&gt;&gt;&gt;&gt; &gt;&gt; &gt; Hi David,<br>

&gt;&gt;&gt;&gt; &gt;&gt; &gt;<br>&gt;&gt;&gt;&gt; &gt;&gt; &gt; I am interested in this too:<br>&gt;&gt;&gt;&gt; &gt;&gt; &gt; Does the above approach affect the polygonal actors in the scene<br>&gt;&gt;&gt;&gt; &gt;&gt; &gt; (segmented<br>









&gt;&gt;&gt;&gt; &gt;&gt; &gt; parts of the image)?<br>&gt;&gt;&gt;&gt; &gt;&gt; &gt; Regards,<br>&gt;&gt;&gt;&gt; &gt;&gt; &gt; Dženan<br>&gt;&gt;&gt;&gt; &gt;&gt;<br>&gt;&gt;&gt;&gt; &gt;&gt; When the DICOM patient coordinate system is used as the VTK world<br>









&gt;&gt;&gt;&gt; &gt;&gt; coordinate system, the assumption is that everything (images AND<br>&gt;&gt;&gt;&gt; &gt;&gt; polydata) would have a either already be in the patient coordinate<br>&gt;&gt;&gt;&gt; &gt;&gt; system, or if not, you would to have a 4x4 transform to set as the<br>









&gt;&gt;&gt;&gt; &gt;&gt; actor&#39;s UserMatrix (or UserTransform).  I.e. a transform to bring the<br>&gt;&gt;&gt;&gt; &gt;&gt; data from its original coordinate system into the patient coordinate<br>&gt;&gt;&gt;&gt; &gt;&gt; system.<br>









&gt;&gt;&gt;&gt; &gt;&gt;<br>&gt;&gt;&gt;&gt; &gt;&gt;  - David<br>&gt;&gt;&gt;&gt; &gt;<br>&gt;&gt;&gt;&gt; &gt;<br>&gt;&gt;&gt;<br>&gt;&gt;<br>&gt;<br>&gt;<br><br></div></div></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div></div>
</div></div></blockquote></div><br></div>
</div>