3
votes

I am processing a group of DICOM images using both ImageJ and Matlab. In order to do the processing, I need to find spots that have grey levels between 110 and 120 in an 8 bit-depth version of the image.

The thing is: The image that Matlab and ImageJ shows me are different, using the same source file. I assume that one of them is performing some sort of conversion in the grey levels of it when reading or before displaying. But which one of them? And in this case, how can I calibrate do so that they display the same image?

The following image shows a comparison of the image read. In the case of the imageJ, I just opened the application and opened the DICOM image.

In the second case, I used the following MATLAB script:

[image] = dicomread('I1400001');

figure (1)
imshow(image,[]);
title('Original DICOM image');

enter image description here

So which one is changing the original image and if that's the case, how can I modify so that both version looks the same?

2
Is the original DICOM 16-bits per pixel? CT images are 16-bits, look at the BitsAllocated and BitsStored to verify this (0028,0100 and 0028,0101). The reason I bring this up, it might make more sense for your image processing to work on the full range data before the 8-bit display conversions, i.e. WindowCenter and WindowWidth.Chris O

2 Answers

5
votes

It appears that by default ImageJ uses the Window Center and Window Width tags in the DICOM header to perform window and level contrast adjustment on the raw pixel data before displaying it, whereas the MATLAB code is using the full range of data for the display. Taken from the ImageJ User's Guide:

16 Display Range of DICOM Images

With DICOM images, ImageJ sets the initial display range based on the Window Center (0028, 1050) and Window Width (0028, 1051) tags. Click Reset on the W&L or B&C window and the display range will be set to the minimum and maximum pixel values.

So, setting ImageJ to use the full range of pixel values should give you an image to match the one displayed in MATLAB. Alternatively, you could use dicominfo in MATLAB to get those two tag values from the header, then apply window/leveling to the data before displaying it. Your code will probably look something like this (using the formula from the first link above):

img = dicomread('I1400001');
imgInfo = dicominfo('I1400001');
c = double(imgInfo.WindowCenter);
w = double(imgInfo.WindowWidth);
imgScaled = 255.*((double(img)-(c-0.5))/(w-1)+0.5);  % Rescale the data
imgScaled = uint8(min(max(imgScaled, 0), 255));      % Clip the edges

Note that 1) double is used to convert to double precision to avoid integer arithmetic, 2) the data is assumed to be unsigned 8-bit integers (which is what the result is converted back to), and 3) I didn't use the variable name image because there is already a function with that name. ;)

2
votes

A normalized CT image (e.g. after the modality LUT transformation) will have an intensity value ranging from -1024 to position 2000+ in the Hounsfield unit (HU). So, an image processing filter should work within this image data range. On the other hand, a RGB display driver can only display 256 shades of gray. To overcome this limitation, most typical medical viewers apply Window Leveling to create a view of the image where the anatomy of interest has the proper contrast to display in the RGB display driver (mapping the image data of interest to 256 or less shades of gray). One of the ways to define the Window Level settings is to use Window Center (0028,1050) and Window Width (0028,1051) tags. Also, a single CT image can have multiple Window Level values and each pair is basically a view of the anatomy of interest. So using view data for image processing, instead actual image data, may not produce consistent results.