File Exchange

image thumbnail

Medical Image Reader and Viewer

version 3.9 (917 KB) by Josh Schaefferkoetter
A toolbox to handle reading, viewing, and writing dicom images, supporting simultaneous PET/MR

56 Downloads

Updated 23 Mar 2018

View License

This toolbox can read and write medical imaging data in dicom format with the 'readImages' function. The output of this function is a structure containing attributes of the image or volume. This structure can then be used as input into other functions in the toolbox.
This toolbox supports:
- reading and writing of dicom data
- mapping of volume voxel locations
- oblique slice alignment and registration
- manual 3D image rotation
- selecting and extracting single voxel coordinates
- drawing 2D or 3D region-of-interest masks
- coregistered image viewing supports PET/CT and PET/MR

Syntax:
CT = readImages([CT_ImageDirectoryPath]);
PET = readImages([PET_ImageDirectoryPath]);
VolumeViewer3D(CT,PET)
VolumeViewer3D(CT,PET,'align','trim')
coords = VolumeViewer3D(PET,CT,'getCoords');
mask = VolumeViewer3D(PET,CT,'drawROI');

Comments and Ratings (60)

Every time I restart the Matlab I keep getting this error and no code is changed

Error in VolumeViewer3D>initiateObject (line 7267)
if ~isempty(test)

Error in VolumeViewer3D>formatFigure (line 1937)
f = initiateObject('3DviewerFig','figure',str);

Error in VolumeViewer3D>initialSetup (line 1558)
handles.figure.f1 = formatFigure(handles.figure.figPos);

Error in VolumeViewer3D (line 184)
initialSetup(inStruct);

Dear all,

this is my code to view CT image by slice
P = zeros(256, 256, 72);
for K = 1 : 72
petname = sprintf('I4%03d.dcm', K);
P(:,:,K) = dicomread(petname);
end
imshow3D(P)

then, this is my code for view SPECT image by slice,

Noted: all my 512 slice SPECT image stored in one file.
[spect map]=dicomread('128x128');
info = dicominfo('128x128');
gp=info.SliceThickness;
spect=(squeeze(spect));%smooth3
aa=size(spect);aa=aa(3);
imshow3D(spect);

Anybody can help me to fuse both SPECT and CT images?

Jie Deng

Huan Liu

Hi Josh,thank you very much for your reply. I will follow your help and have a careful look at the function "coregisterLocs". Thank you very much.

Hi Huan,
The image volumes are interpolated on a new set of mutual points, which are rotated and resampled, but not translated. The program finds the rotation matrix that transforms the orientation defined by the "Image Orientation Patient" (axes-cosine vector) from one image volume to the other. It then resamples both images to the same pixel grid in that space. Check the function "coregisterLocs" for an idea.

Huan Liu

Hi Josh,I encountered a problem when I read your code and used image for testing,after PET and MRI images are registered , according to the way of planning system,how to obtain translation and rotation?Looking forward to your reply!Thanks very much.

It's a simple conversion but you need the information about injected dose, uptake time etc. See the function 'calculateSUV' for an idea...

Dan Smith

I'm trying to take a .mat file converted from a DICOM image and convert back the SUV values that were changed upon the conversion to show up in the mat file. Can you help?

Hello. I just tried this toolbox and I encountered this problem when I read in DICOM format images. I didnt change anything. Can u help me ?

Attempt to execute SCRIPT test as a function:
C:\Users\ariuka\Desktop\diplom\my code\test.m

Error in VolumeViewer3D>initiateObject (line 7267)
if ~isempty(test)

Error in VolumeViewer3D>formatFigure (line 1937)
f = initiateObject('3DviewerFig','figure',str);

Error in VolumeViewer3D>initialSetup (line 1558)
handles.figure.f1 = formatFigure(handles.figure.figPos);

Error in VolumeViewer3D (line 184)
initialSetup(inStruct);

Error in test (line 4)
tic; VolumeViewer3D(PET); toc

There will only be an output if you pass 'getCoords' or 'drawROI' arguments. In these cases, the output will match the space of the first input (not the "aligned" space used for viewing, for example if using the 'align' argument). When running the tool, read the printed statements displayed in the command window - they should help you to understand what the program is doing.

yes sir, i have corrected that problem( i was reading the images with readDicomImages and now i have used readImages).
the output of 'align' or 'trim' is not giving registered images
i have 23 mri image sequences and 47 pet image sequences. both mri and pet are of dicom standard. do i need to apply any other step to successfully implement registration.

Your inputs are not correct. Were the mr1 and pet1 structures returned by the function 'readImages'?

@Josh
Sir i am unable to get the coordinates, the following error is displayed:
coords = VolumeViewer3D(mr1,pet1,'getCoords');
Image data is not defined in (structure) input 1
...so ignoring (structure) input 1
Image data is not defined in (structure) input 2
...so ignoring (structure) input 2
Undefined function or variable "siz".

Error in VolumeViewer3D (line 361)
if ~(numel(size(inStruct.locX))==numel(siz) && all(size(inStruct.locX)==siz)) || ...

This toolbox was designed to show the coregistered slices in a common display axis, so the volumes are interpolated to share the same image matrix and pixel dimensions. By default, the target interpolation points are generated by using the finest resolution between the 2 volumes (found independently in each dimension), and if the final calculated matrix is too big, it is downsampled to produce more manageable data. You can avoid this downsampling by passing the argument 'full' as an additional input to VolumeViewer3D; then the full size interpolation matrix will be used. In this case, the original data will still be interpolated, but the coregistered data will have higher resolution - this may help the issue your are facing.

We are using Medical Image Reader and Viewer to coregister FDG-PET and CT Perfusion datasets. The registration works very well, but we are now realizing that the original resolution and matrix size is modified and interpolated. It would be very helpful for us, if the original resolutions and matrix sizes could be preserved. Do you see a possibility to do this? Thx

@Josh
both of VolumeViewer3D(PET,CT) and VolumeViewer3D(PET) give me the voxel count (in side the box (Bq/ml:)), not SUV value; what is the solution to this problem?

put a breakpoint on the 2nd line of calculateSUV function. Then call "parseInputs(varargin{:});" at the command line and see what is the error. PM me if you need more help

Thanks @Josh to replay me ,,,,, i am try it but it failed so try to putting the all parameters (injection dose , start injection time, aquestion time, half life time for FDG, scale factor, dose calibration factor ) from dicom header and try to test it but it also not work internal the viewer ...... can you help me and tell me steps to how it work.

Hi Mahmoud,
It's likely that you are missing something needed to compute the SUV conversion factor. Put a breakpoint at the beginning of the function "calculateSUV" to make sure all the necessary information is being passet to it.

Thanks for the availability this toolbox but how using SUV function to show the SUV internal the Volume Viewer in place of Bq/ml.

IGNORE MY PREVIOUS COMMENT. DIDN'T KNOW I HAD TO SCROLL AAAAALLLLL THE WAY TO THE BOTTOM OF THE PAGE TO FIND THE DEPENDENCIES.

Huan Liu

Hi Josh,thanks for your reply.I'm so sorry I do not have your email,Can you give me your email address,I sent email to you,thanks!

Hi Huan,
I never received a message from you. Either contact me directly or turn on the option for me to contact you directly.

Huan Liu

Hi Josh,I encountered this problem when I read in DICOM format images,I read images with the folder that you wrote,I've tried it many times and it has always been this error.The error as follow:
E: \ Softwale \ R2014a \ toolbox \ dirart_programs_06_02_2011 \ dirart_programs_06_02_2011 \ support_programs \ matlab levelset toolbox \ test.m
Error VolumeViewer3D> StartObject (line 7256)
if ~ isempty (test)
Error VolumeViewer3D> formatFigure (line 1931)
f = GetObject ('3DviewerFig', 'figure', str);
Error VolumeViewer3D> initialSetup (line 1552)
handles.figure.f1 = formatFigure (handles.figure.figPos);
Error VolumeViewer3D (line 184)
initialSetup (inStruct);
Examples (line 21)
Can you help me analyze what went wrong?
Can you give me a help?Thanks!

Huan Liu

Huan Liu

Ok, thanks a lot ,I've sent you an email at fileexchange.Please give me a help for the work,thanks very much!

Huan,
It's not clear what you are doing - have you modified the code? Please contact me directly if you need more help

Huan Liu

Hi Josh,I downloaded your Medical Image Reader and Viewer code, I imported the image but there was an error trying to execute SCRIPT test as a function:
E: \ Softwale \ R2014a \ toolbox \ dirart_programs_06_02_2011 \ dirart_programs_06_02_2011 \ support_programs \ matlab levelset toolbox \ test.m

Error VolumeViewer3D> StartObject (line 7256)
if ~ isempty (test)

Error VolumeViewer3D> formatFigure (line 1931)
f = GetObject ('3DviewerFig', 'figure', str);

Error VolumeViewer3D> initialSetup (line 1552)
handles.figure.f1 = formatFigure (handles.figure.figPos);

Error VolumeViewer3D (line 184)
initialSetup (inStruct);

Examples (line 21)
tic; VolumeViewer3D (PET); toc
Can you help me solve it?

HiJosh and everyones, i have face this problem? please help me

VolumeViewer3D(p, c)
coregistering volumes...
Cannot find an exact (case-sensitive) match for 'Settings'

The closest match is: settings in C:\New folder\pet\settings.m

Error in VolumeViewer3D>initialSetup (line 1535)
s = Settings;

Error in VolumeViewer3D (line 184)
initialSetup(inStruct);

At line 230 in dicm_hdr, the operation s.PixelData.Start = p.iPixelData; creates the structure field 'PixelData' within structure 's'. Since your version is complaining, try to add the following line just before this, at line 229

s.PixelData = struct;

Let me know if this works. If it does, I'll make the change and update the version - if not, try to share your data so I can attempt to reproduce the error on my end.

Jie Deng

Hi Josh, it says 'File read error, try again with another file', followed by a pop up window for single file selection. When I select a single .dcm file, here is the error msg. They are GE PET images.

Field assignment to a non-structure array object.

Error in dicm_hdr (line 230)
s.PixelData.Start = p.iPixelData;

Error in readImages>parseInputs (line 363)
test = dicm_hdr([imageDir imageFiles{1}]);

Error in readImages (line 87)
inStruct = parseInputs(varargin{:});

What is the problem you are having? Put a breakpoint on the line containing the call to 'readDicomImages' then call it from the command line to produce the error.

Jie Deng

Thanks for building and sharing this toolbox, very helpful! I am currently using 2017a version but encountered a problem reading images using 'readImages', do you have any idea why?

Trina Kok

Josh

you can do this easily (e.g. if your mask has the same dimensions as PET.volumes):

mask = logical(mask);
VolumeViewer3D(PET, mask);

YUNTAO YU

@Josh
Sorry Josh, i have presented my question badly. In fact, I have already my mask and I'd like to show it together with PET-CT scan,for example, with "contour" function. But i'm not sure where i should add these codes in your original codes.
Thank you :)

Josh

For example, say you want make a mask of an image 'Im', matching its dimensions, [imX, imY, imZ], for all pixels above 'threshold' in a 11x11x11 box centered on [x, y, z], you could do something like this:

mask = false(imX, imY, imZ);
mask(x - 5 : x + 5, y - 5 : y + 5, z - 5 : z + 5) = true;
mask = mask & Im > threshold;

YUNTAO YU

@Josh
Thanks for the reponse. I have fixed missed information in my dicom file :) And SUV works well! I'm now trying to add a contour mask on the image. Hope for suggestions, thank you :)

Josh

Thanks Yuntao. The viewer shows PET SUV by default, but it must have all the required information from the Dicom, i.e. injection and scan times, subject mass, image quantification units, and radiotracer. Put a breakpoint on the call to 'calculateSUV', then call it manually from the prompt. This will point to the problem.

YUNTAO YU

Thank you Josh Schaefferkoetter. That's a great job which helps me a lot on my project. I think it will be better if the toolbox can also show the suv value :)

Amazing contribution Josh. This tool helped me a lot :)!

Josh

The function was looking for a dicom field that did not exist in those TCIA images. I added a check to avoid this - try the new version. Thanks for pointing this out.

quix

Hi, nice toolbox!

I tried to read in an image from The Cancer Imaging Archive (TCIA) but was unable to. The message is 'File read error, try again with another file'. The message is repeated for any single slice I choose in the series.

The data can be retrieved here: https://public.cancerimagingarchive.net/ncia/externalLinks.jsf?collectionName=QIN-HEADNECK, Subject ID: QIN-HEADNECK-0003

Josh, thank you for the hint. I just doubled each font size and now I have a nice display. I am using your viewer on my iMac 27" with 2560 x 1440 pixels. The original fonts display was really tiny and hard to read. Now it works fine.

Thank your for this helpful toolbox which I am using for my research work!

Josh

Thanks for the feedback. The viewer was tested at high DPI and normal 1080 resolution. What size is your display?

The quick fix would be to do a ctrl-F search through VolumeViewer3D.m for 'FontSize' and change all the necessary field values. Let me know which value works best for the screen you are using.

Is there any chance to increase the font size of the sliders, value outputs and handles in the 3D Viewer window? Unfortunately on my machine everything is pretty small on the screen. But besides that drawback the 3D Viewer is superb!

@Joaquin
I'll consider adding these to the next version. Thanks for the feedback!

Just in case it is useful for others,
With Matlab2014a I needed to add a try/catch in VolumeViewer3D.m (line 3372)
try
if s.matlab.desktop.HighDPISupport
hAxOffset = 0.0005;
vAxOffset = 0.0005;
end
catch
hAxOffset = 0.0007;
vAxOffset = 0.001;
end

Very useful tool. I had to adapt it to read GE images from the cancer imaging archive, because some tags in the dicom info are vendor-specific. I used the dictionary from https://www.mathworks.com/matlabcentral/fileexchange/42997-dicom-to-nifti-converter--nifti-tool-and-viewer
I changed in all cases:
dict = dicm_dict('GE');
meta = dicm_hdr([imageDir '\' imageFile], dict);
instead of:
meta = dicominfo([imageDir '\' imageFile]);

Where/how should I share the data?

@Peter
Thanks for the feedback. I wrote the code to prompt for new image data if any errors were found, this is convenient but makes it tricky to troubleshoot - maybe I'll think of a different way to handle this... In the meantime, if you can share your dicom data, I'll take a look.

Please ignore that last comment, I pressed enter by mistake. The current version does not seem to work for me, using the readImages function, even if I provide the directories it opens a file finder, and whenever I select a file it tells me there is a "File read error, try again with another file."

Hello, getting a file read error

@Gabriel
The output variable is now initialized as a structure so should fix the problem. Let me know if it still doesn't work.

Looks nice program, but I have a similar problem as payam. After loading GE images with MATLAB 2015b:
Field assignment to a non-structure array object.

Error in VolumeViewer3D>parseInputs (line 397)
out.modality = 'VOL';

Error in VolumeViewer3D (line 36)
inStruct = parseInputs(varargin);

@payam
I loaded several PET studies from the TCIA site, including the phantom data, and found a small bug related to the GE and Philips series naming convention; I couldn't reproduce your error though. With which specific data sets were you having issues?

Hi,
The toolbox seems good.
I have tried to read a PET volume from TCIA (www.cancerimagingarchive.net/) using readImages. I faced this error:

Field assignment to a non-structure array object.

Error in readImages (line 82)
out.nSeries = nSeries;

Also the same error for phantom images. I am using Matlab 2015b.

Updates

3.9

Version check for high DPI displays

3.83.0.0

fixed high DPI display bug

3.82.0.0

bug with reading dicom

3.81.0.0

small bug with writing dicom

3.8.0.0

fixed bug for reading dicom files with no extension

3.7.1.0

performance tweaks

3.7.0.0

updated examples

3.6.0.0

faster image coregistration

3.5.0.0

minor improvements

3.4.0.0

incomplete filename bug fix

3.3.0.0

ability to combine 2D and 3D, and volume and mask inputs

3.21.0.0

improved input handling

3.2.0.0

improved input and error handling

3.11.0.0

housekeeping

3.1.0.0

corrected dicom tag writing

3.2.0.0

UI formatted for high DPI displays

3.1.0.0

updated examples

3.1.0.0

updated examples

3.0.0.0

Ability to draw and output 2D or 3D mask

2.11.0.0

output structure initialization

2.1.0.0

modified coregistration

2.0.1.0

GE and Philips series naming convention bug fix

2.0.0.0

minor tweaks

1.9.0.0

fixed smoothing functionality

1.8.0.0

small bug fix

1.7.0.0

minor tweaks and enhancements

1.6.0.0

updated examples

1.5.0.0

faster and more accurate interpolation

1.4.0.0

performance improvements

1.3.0.0

bug fixes

1.2.0.0

improved handling of large image matrices

1.1.0.0

faster and more efficient memory handling

MATLAB Release Compatibility
Created with R2017a
Compatible with any release
Platform Compatibility
Windows macOS Linux
Acknowledgements

Inspired by: freezeColors / unfreezeColors, xiangruili/dicm2nii

html/