The inverted image is actually a pretty tricky problem in vtk when dealing with DICOM images. DICOM is very specific about how the orientation vectors are to be used, and VTK absolutely ignores this standard. I'm not sure if it's bugged behavior or not, though.<br>
<br>
Right now, there's an option in VTK to flip the Y coordinate, but I
don't remember what it is and it turns out not to be helpful here,
because you'll also need to flip x and z, most likely.<br><br>DICOM specifies that each imaging plane has the upper left xy coordinate in each 2d slice specified. That coordinate is in tag 0020,0032 (Image Position (Patient)). DICOM then specifies that each subsequent pixel in the x y plane is determined by the spacing from that coordinate (generally positive). So, if you have an x extent of -300 and a pixel spacing of 1 on a 512x512 image, then your x coordinate will span from -300 to 212. This is true regardless of the direction cosines in the image. The direction cosines tell the user the orientation of the patient as regards to the scanner, and should be used to determine display, but not the coordinates of the data.<br>
<br>In VTK, however, that's not true. If the x direction cosine is -1,0,0, then your 512x512 image will be from -300 to -812. That means that all the coordinates in your RTStruct will be completely wrong, and your RTStruct will get drawn off in space some where. That offset problem happens because the RT contour coordinates are exactly specified to the pixel coordinates I described in the previous paragraph.<br>
<br>The solution is somewhat complicated, and hindered by the fact that VTK has some functions in the API that don't work but are apparently there to confuse people. You need to avoid PreserveImageExtentOn when you flip, as it does _absolutely nothing_.<br>
<br>The next problem is that vtk doesn't allow you to flip about any origin other than 0,0,0. (Remember, we have to flip the data itself, not the cameras, because otherwise all the RT information will be misregistered to the original image, regardless of where you're looking).<br>
<br>This is the code I use in Java to solve this problem:<br><br> IPPSorter sorter = new IPPSorter();<br> sorter.SetComputeZSpacing(true);<br> sorter.SetZSpacingTolerance(0.000001);<br>
Boolean sorted = sorter.Sort(theSeriesFiles);<br> //sorter.Sort(ft);<br><br> //have to make a vtk string array<br> FilenamesType sortedFT = sorter.GetFilenames();<br>
long theSize = sortedFT.size();<br> vtkStringArray sa = new vtkStringArray();<br> for (int j = 0; j < theSize; j++) {<br> String theString2 = sortedFT.get(j);<br>
sa.InsertNextValue(theString2);<br> }<br> gdcmReader.SetFileNames(sa);<br><br> gdcmReader.Update();<br> <br> //make sure that we're getting spacing and orientation info<br>
double[] spacing = gdcmReader.GetOutput().GetSpacing();<br> spacing[2] = sorter.GetZSpacing();<br> gdcmReader.GetOutput().SetSpacing(spacing);<br> double[] origin = gdcmReader.GetOutput().GetOrigin();<br>
double[] bounds = gdcmReader.GetOutput().GetBounds();<br> double[] nextOrigin = {0,0,0};//because vtk <br> //will only flip about 0,0,0<br> vtkImageChangeInformation imageSpacingChange = new vtkImageChangeInformation();<br>
imageSpacingChange.SetInput(gdcmReader.GetOutput());<br> imageSpacingChange.SetOutputSpacing(spacing[0], spacing[1], spacing[2]);<br> imageSpacingChange.SetOutputOrigin(nextOrigin );<br>
imageSpacingChange.Update();<br> imageData = imageSpacingChange.GetOutput();<br> //ok, here's the deal with axes<br> //for now, assume all axes are -1 or 1 along the origin<br>
//and then set them all to 1.<br> vtkMatrix4x4 directionCosines = gdcmReader.GetDirectionCosines();<br> //actually have to flip the data, not the camera<br> //and the opposite way to itk.<br>
//but, to make the image display properly, have to flip the camera<br> //anyway? most likely, but depends if this is brain, pelvis, etc<br> boolean willFlip = false;<br> for (int j = 0; j < 3; j++){<br>
if (directionCosines.GetElement(j, j) < 0) {<br> flip[j] = true;<br> willFlip = true;<br> }<br> else {<br> flip[j] = false;<br>
}<br> if (j == 1 ) {<br> flip[j] = !flip[j]; //y is inherently backwards in vtk<br> willFlip = true;<br> }<br> }<br>
<br><br> //vtk's pipelining means I can't easily iterate over axes.<br> //note the switch that doesn't do anything<br> //(that would be PreserveImageExtentOn/Off)<br>
//require that you translate, flip, translate to get the<br> //functionality of this older switch<br> if (willFlip){<br><br> vtk.vtkImageFlip theFlip = new vtk.vtkImageFlip();<br>
theFlip.SetInputConnection(imageSpacingChange.GetOutputPort());<br> theFlip.FlipAboutOriginOn();<br> //gotta find the first axis to flip...<br> boolean keepGoing = false;<br>
if (flip[0]){<br> theFlip.SetFilteredAxis(0);<br> keepGoing = flip[1] && flip[2];<br> } else if (flip[1]){<br> theFlip.SetFilteredAxis(1);<br>
keepGoing = flip[2];<br> } else {<br> theFlip.SetFilteredAxis(2);<br> }<br><br> theFlip.Update();<br> imageData = theFlip.GetOutput();<br>
if (keepGoing){<br> vtk.vtkImageFlip theFlip2 = new vtk.vtkImageFlip();<br> theFlip2.SetInputConnection(theFlip.GetOutputPort());<br> theFlip2.FlipAboutOriginOn();<br>
//gotta find the first axis to flip...<br> boolean keepGoing2 = false;<br> if (flip[1]){<br> theFlip2.SetFilteredAxis(1);<br>
keepGoing = flip[2];<br> } else {<br> theFlip2.SetFilteredAxis(2);<br> }<br><br> theFlip2.Update();<br>
imageData = theFlip2.GetOutput();<br><br> if (keepGoing2){<br> vtk.vtkImageFlip theFlip3 = new vtk.vtkImageFlip();<br> theFlip3.SetInputConnection(theFlip2.GetOutputPort());<br>
theFlip3.FlipAboutOriginOn();<br> //gotta find the first axis to flip...<br> theFlip3.SetFilteredAxis(2);<br><br> theFlip3.Update();<br>
imageData = theFlip3.GetOutput();<br><br> }<br> }<br> }<br> //have to do this because the flipping above only flips about 0,0,0<br>
vtkImageChangeInformation imageSpacingChange2 = new vtkImageChangeInformation();<br> imageSpacingChange2.SetInput(imageData);<br> imageSpacingChange2.SetOutputSpacing(spacing[0], spacing[1], spacing[2]);<br>
double[] extent = new double[3];<br> for (int j = 0; j < 3; j++){<br> extent[j] = bounds[j*2+1]-bounds[j*2];<br> }<br> imageSpacingChange2.SetOutputOrigin(<br>
origin[0] + (flip[0] ? -1 : 0) *extent[0],<br> origin[1] + (flip[1] ? -1 : 0) *extent[1],<br> origin[2] + (flip[2] ? -1 : 0) *extent[2]);<br> imageSpacingChange2.Update();<br>
imageData = imageSpacingChange2.GetOutput();<br> imageMedicalProperties = gdcmReader.GetMedicalImageProperties();<br><br>The above code will NOT work if you have direction cosines that are not unitary (ie, if you have direction cosines that are something like 0.93, -0.4, etc etc). That's because you'll have to add some rotational element in as well. This rotational problem could become a real issue when dealing with MR data and associated RT structs, because MR does not require that the directional cosines be unitary.<br>
<br>I hope that helps,<br>Mark<br><br>-------------<br>
You can use vtkTransform to rotate the RT Dose matric to your desired<br>
orientation.<br>
<br>
Jothy<br>
<br>
On Fri, Nov 5, 2010 at 2:09 AM, Xiaofeng Z <<a href="mailto:xf10036@hotmail.com">xf10036@hotmail.com</a>> wrote:<br>
<br>
> Hi, vtkusers,<br>
><br>
> I have this algorithm that computes dose-volume histogram out of RT<br>
> structureset and RT Dose. Right now the algorithm works only when RT Dose<br>
> has a 1,0,0 and 0,1,0 orientation. I need to use the algorithm for other RT<br>
> Dose orientations. I have too options, either to modify the algorithm, or<br>
> to convert RT Dose orientation to 1,0,0 and 0,1,0. I prefer to former, but<br>
> only if vtkImageData support multiple orientations.<br>
><br>
> So my question is, can vtkImageData store pixel data in different<br>
> orientation, and if so, how the orientation information is set and get?<br>
><br>
> Thanks!<br>
><br>
> Xiaofeng<br>
><br>
><br>
><br>
><br>
> ------------------------------<br>
> From: <a href="mailto:xf10036@hotmail.com">xf10036@hotmail.com</a><br>
> To: <a href="mailto:vtkusers@vtk.org">vtkusers@vtk.org</a><br>
> Date: Thu, 4 Nov 2010 21:02:08 -0400<br>
> Subject: [vtkusers] question on vtkImageData orientation support<br>
><br>
><br>
> Does vtkImageData:SetExt(int ext[]) support inverse orientation, such that<br>
> ext[0]<ext[1], ext[2]<ext[3], etc?<br>
><br>
> Thanks!