5
votes

I have to write a program in c# able to parse DICOM and display axial, coronal and sagittal cuts.

Seems like it's a lot of work, but I have to do it so !

Big first step would be to understand DICOM files I guess.

I've been reading this tutorial http://dicomiseasy.blogspot.ru/ but he's using this RZDCX library that I'm not allowed to buy.

There are still some good explanations about DICOM attributes and I've also been reading some parts of the standard (part 3 above all)

But I'm having big trouble to understand them all. There are those image attributes: pixel representation, pixel data, planar configuration... I guess it's very important to understand them to be able to display the image, and I think I should learn more about how pixels actually work to have a better understanding.

But there is still one thing I really can't figure out :

How or where am I suppose to have this three different cuts? (axial/coronal/sagittal). I've been looking for attributes about them in the standard but I did not find any. So may be we find them with some kind of calculation, but I don't know which variables I should use with which formula?

4
1 more hint: You are concerned about the attributes of the image pixel module and how to correctly interpret the different possible combinations, and you are right, this is not trivial. Assuming you will end up using DCMTK ;-) for accessing the DICOM data there is a class called DicomImage which can take this burden from you. It offers a method getInterData() with which you can obtain the pixel data in a normalized manner (i.e. the pixel data values have been mapped to the real world range and are stored as 8,16 or 32 bit signed/unsigned integer). That helps a lot about this issue.kritzel_sw
I'm currently looking at DCMTK documentation, and I understand that getInterData() might be usefull, but this would allow to get one kind of pixel representation (and to display one image then) right? I just don't understand how I could extract 3 different images from one pixel representationCharrette
@Charnette: You can not. The type of image (i.e. the type used to represent the pixel values) is implicitly determined upon construction of the image. With getRepresentation() you can retrieve the type as enum (e.g. EPR_Uint16 for unsigned short). The benefit of using it is that the appropriate type is chosen by DcmImage and the InterData contains the real pixel values in contrast to the PixelData element in the DICOM file which contains data that still has to be transformed with the modality LUT.kritzel_sw

4 Answers

10
votes

You are right, this is quite a big task! And you are probably not going to find someone here who can provide a step-by-step tutorial for you, However some hints:

  1. The DICOM standard is awkward and needs a steep learning curve at the beginning. The DICOM Cookbook helped me a lot to become familiar with the terms and the structure of the documentation.
  2. There are plenty of other toolkits around, some of them are free and ship with a very liberal license, such as DCMTK. These take away the burden to learn how the information is encoded in the various binary formats which slightly differ and provide a uniform API to access the information quite easily. I would strongly advise against writing your own DICOM implementation from scratch.
  3. The DICOM attributes which define the 3D position and orientation of a slice or frame are ImagePositionPatient (0020,0032) , ImageOrientationPatient (0020,0037) and PixelSpacing (0028,0030). These can be used to order the slices correctly and calculate interpolated intersection slices.
  4. Make sure to look at the Enhanced CT/MR Information object definitions. In general there are two ways to store a stack of images in DICOM: Singleframe (one file per image) and Multiframe (one file for one or more stacks of images). They differ in the way that you can obtain the information mentioned above.

HTH and good luck!

5
votes

This question is already 3 y.o., but maybe my answer will be helpful for somebody.

@user6867490 has already referenced to the beautiful article by Roni Zaharia.

The only thing that I would like to add is: you can simply get access to the Image Orientation (Patient), Tag (0020,0037) by writing

f = dicom.read_file(dicom_file_name)
f.ImageOrientationPatient

If you'll obtain:

['1', '0', '0', '0', '0', '-1'] you are dealing with Coronal plane view

['0', '1', '0', '0', '0', '-1'] you are dealing with Sagittal plane view

['1', '0', '0', '0', '1', '0'] you are dealing with Axial plane view

In my case, there was a dataset containing a few images of Sagittal and lots of Axial views (which I needed actually). So, I simply iterated through the whole dataset and did a simple logical comparison to filter out all the saggitals.

2
votes

This is a python implementation to find plane of an IMA file. Refer: http://dicomiseasy.blogspot.com/2013/06/getting-oriented-using-image-plane.html

import pydicom # for gettind information out of the IMA files
import numpy as np

"""
This function takes IOP of an image and returns its plane (Sagittal, Coronal, Transverse)
"""

def file_plane(IOP):
    IOP_round = [round(x) for x in IOP]
    plane = np.cross(IOP_round[0:3], IOP_round[3:6])
    plane = [abs(x) for x in plane]
    if plane[0] == 1:
        return "Sagittal"
    elif plane[1] == 1:
        return "Coronal"
    elif plane[2] == 1:
        return "Transverse"

a=pydicom.read_file("path\to\your\DICOM\file.IMA")
IOP = a.ImageOrientationPatient
plane = file_plane(IOP)
0
votes

Sometimes you have to build the different views. For example if you have a CT image set which are axial to the subject, then you can make your own slices for coronal and sagittal views by sampling the image set appropriately. I would start by writing code to simply display the data you have as is as a starting point. By the time that's working you'll have a deeper understanding of the issues.