DICOM Image Resize Error

Hi,there. I'm new to matlab and programming.
Since resizing is needed for Alexnet and Googlenet, I`m now working on resizing Dicom File from 256*256*1 to 227*227*3.
Here is my directory:
main
-- a
-- image.dcm(10 dicom file)
 -- b
  -- image.dcm(10 dicom file)
 -- c
  -- image.dcm(10 dicom file)
-- d
  -- image.dcm(10 dicom file).
Here is my code:
%path = current directory
currentdirectory = pwd;
%% Create an ImageDatastore to help you manage the data.currentdirectory = pwd;
categories = {'a', 'b', 'c','d'};
%Because ImageDatastore operates on image file locations,
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.dcm','LabelSource', 'foldernames','ReadFcn',@dicomread);
%resize
imdsResized = imresize3(imds, [227 227 3]);
However, it throws following error:
Error using imresize3
Expected input number 1, V, to be one of these types:
single, double, int8, int16, int32, uint8, uint16, uint32
Instead its type was matlab.io.datastore.ImageDatastore.
Anyone have answer about this situation, pls let me know.
Thanks in advance!

 采纳的回答

Walter Roberson
Walter Roberson 2019-2-16

1 个投票

It is not possible to resize an entire imageDatastore. You would need to loop doing readimage() and resize them one by one, or else use readall() to get back a cell array that you could cellfun() a resize operation on.

26 个评论

ssk
ssk 2019-2-16
编辑:ssk 2019-2-16
Dear Walter Roberson,
Thanks for your advice!
Since I use lots of dataset, I would like to try the second one- "readall() to get back a cell array that you could cellfun() a resize operation on."
However, I'm very new to programming and not sure how to apply this method into my code...
Would you give me more hint to imprement this method or show the exact source code?
Thanks for you in advance!
imdsResized = cellfun(@(img) imresize3(img, [227 227 3]), readall(imds), 'uniform', 0);
Dear Walter,
Really appreciate your advice.
Although I tried to compile your code, it still throws following error..
It seems that dicom file is diffent from jpg image..
Undefined function or variable 'imds'.
You would still need your other code before that,
currentdirectory = pwd;
%% Create an ImageDatastore to help you manage the data.currentdirectory = pwd;
categories = {'a', 'b', 'c','d'};
%Because ImageDatastore operates on image file locations,
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.dcm','LabelSource', 'foldernames','ReadFcn',@dicomread);
ssk
ssk 2019-2-16
编辑:ssk 2019-2-16
I added other code before your code, however it still throws same error: Undefined function or variable 'imds'.
ssk
ssk 2019-2-16
编辑:ssk 2019-2-16
sorry, the error is changed:
Index exceeds the number of array elements (2).
Error in matlab.images.internal.resize.deriveScaleFromSize (line 16)
scale = params.output_size ./ A_size(1:params.num_dims);
Error in imresize3>fixupSizeAndScale (line 487)
params.scale = matlab.images.internal.resize.deriveScaleFromSize(params);
Error in imresize3>parseInputs (line 175)
params = fixupSizeAndScale(params);
Error in imresize3 (line 108)
params = parseInputs(args{:});
Error in test_googlenet>@(img)imresize3(img,[227,227,3])
Error in test_googlenet (line 25)
imdsResized = cellfun(@(img) imresize3(img, [227 227 3]), readall(imds), 'uniform', 0);
your dicom images, are you sure they are color images ? most dicom are grayscale or else sequences or arrays of grayscale .
I figured out that my dicom images are grayscale image. In this case, how can i modify my code to apply into googlenet and alexnet?
imdsResized = cellfun(@(img) repmat(imresize(img, [227 227]), [1 1 3]), readall(imds), 'uniform', 0);
ssk
ssk 2019-2-16
编辑:ssk 2019-2-16
It works well. Sorry to bother you many times. And really appreciate your advice! [1 1 3] means gray scale?
Dear Walter,
I tried to apply your code into following link.
imdsResized = cellfun(@(img) repmat(imresize(img, [224 224 ]), [1 1 3]), readall(imds), 'uniform', 0);
However, I still got error:
Error using trainNetwork (line 150)
The training images are of size 224x224x1 but the input layer expects
images of size 224x224x3.
How can i modify my code:
Thanks in advance!
newext = '.png';
%path = current directory
currentdirectory = pwd;
%% Create an ImageDatastore to help you manage the data.currentdirectory = pwd;
categories = {'a', 'b', 'c','d'};
%Because ImageDatastore operates on image file locations,
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.dcm','LabelSource', 'foldernames','ReadFcn',@dicomread);
%resize
while hasdata(imds)
[img, info] = read(imds);
[filedir, basename, ext] = fileparts(info.Filename);
newfilename = fullfile(filedir, [basename, newext]);
img3 = repmat( imresize(img, [224 224]), [1 1 3] );
imwrite(img3, newfilename);
end
Now you can proceed with the example, but this time specify 'FileExtensions', newext instead of 'FileExtensions','.dcm' in order to pick up the resized files.
repmat(X, [1 1 3]) means that the input, X, is to have its data repeated once in the first dimension, once in the second dimension, and three times in the third dimension. When applied to a grayscale image, it makes three copies of the grayscale data along the third dimension, so you would go from 224 x 224 x 1 to 224 x 224 x 3 . The RGB color system is constructed in a way that equal values specified for the R, G, B components gives you the appearance of grayscale.
Dear Walter,
Thanks for your advice many times.
Based on your code, I tried to compile, however it still has error...
Warning: Data loss and unexpected results may occur with signed pixel data.
> In imwrite (line 454)
In test_googlenet (line 25)
Error using writepng>parseInputs (line 290)
Expected input to be one of these types:
double, single, logical, uint8, uint16
Instead its type was int16.
Error in writepng (line 20)
[results, unmatched] = parseInputs(data,map,filename,varargin{:});
Error in imwrite (line 492)
feval(fmt_s.write, data, map, filename, paramPairs{:});
Error in test_googlenet (line 25)
imwrite(img3, newfilename);
newext = '.png';
%path = current directory
currentdirectory = pwd;
%% Create an ImageDatastore to help you manage the data.currentdirectory = pwd;
categories = {'a', 'b', 'c','d'};
%Because ImageDatastore operates on image file locations,
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.dcm','LabelSource', 'foldernames','ReadFcn',@dicomread);
%resize
while hasdata(imds)
[img, info] = read(imds);
[filedir, basename, ext] = fileparts(info.Filename);
newfilename = fullfile(filedir, [basename, newext]);
img3 = repmat( imresize(im2uint8(img), [224 224]), [1 1 3] );
imwrite(img3, newfilename);
end
Do not be surprised if the resulting images hide a lot of detail or are dim. Your DICOM images appear to be int16, probably CT images. CT images have higher data resolution than can easily fit in uint8, so they are typically stored as 16 bit images; depending on the device, they might be int16 (signed 16 bit) or uint16 (unsigned 16 bit.) However, they effectively never use the full 16 bit range. For example they might be in terms of Hounsfield units, which can range down to -6000 and up to +30000 (for metals). But they more likely will be in factions of a hounsfield with useable data range between roughly -1000 and +10000 or between +3000 and +18000. But only a small portion of that is interesting. When you mechanically scale according to what might be stored in int16 (+/- 32767) then you tend to compress the interesting information into a narrow range. Unfortunately there is no easy general way to automatically pick out the interesting range of data from a CT scan, since "interesting" depends on what you are looking for and range depends upon instrument settings.
Rather than a plain im2uint8, you will probably end up needing to do a mat2gray() passing in a range of values to select between, perhaps something like
img3 = repmat( imresize(mat2gray(img, [-500 1200]), [224 224]), [1 1 3] );
where the [-500 1200] is a range of values that you would have to determine by examing a number of your images with imhist() and data cursor to determine the ranges of what is "interesting" for your particular purposes.
Dear Walter,
Thank you for your explanation in detail. And really sorry to bother you many times.
However, it still throw same error:
Error using trainNetwork (line 150)
The training images are of size 224x224x1 but the input layer expects
images of size 224x224x3.
Error in test_googlenet (line 107)
net = trainNetwork(augimdsTrain,lgraph,options);
My dataset is MRI.
Please post your current code.
%% googlenet
%reference:https://jp.mathworks.com/help/deeplearning/examples/train-deep-learning-network-to-classify-new-images.html
newext = '.png';
%% Create an ImageDatastore to help you manage the data.
currentdirectory = pwd;
categories = {'a', 'b', 'c','d'};
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.dcm','LabelSource', 'foldernames','ReadFcn',@dicomread);
while hasdata(imds)
[img, info] = read(imds);
[filedir, basename, ext] = fileparts(info.Filename);
newfilename = fullfile(filedir, [basename, newext]);
img3 = repmat( imresize(im2uint8(img), [224 224]), [1 1 3] );
imwrite(img3, newfilename);
end
[imdsTrain,imdsValidation] = splitEachLabel(imds,0.5);
%% Load pretrained Network:
net = googlenet;
analyzeNetwork(net)
net.Layers(1)
inputSize = net.Layers(1).InputSize;
%% replace final layer:
if isa(net,'SeriesNetwork')
lgraph = layerGraph(net.Layers);
else
lgraph = layerGraph(net);
end
[learnableLayer,classLayer] = findLayersToReplace(lgraph);
[learnableLayer,classLayer]
numClasses = numel(categories(imdsTrain.Labels));
if isa(learnableLayer,'nnet.cnn.layer.FullyConnectedLayer')
newLearnableLayer = fullyConnectedLayer(numClasses, ...
'Name','new_fc', ...
'WeightLearnRateFactor',10, ...
'BiasLearnRateFactor',10);
elseif isa(learnableLayer,'nnet.cnn.layer.Convolution2DLayer')
newLearnableLayer = convolution2dLayer(1,numClasses, ...
'Name','new_conv', ...
'WeightLearnRateFactor',10, ...
'BiasLearnRateFactor',10);
end
lgraph = replaceLayer(lgraph,learnableLayer.Name,newLearnableLayer);
newClassLayer = classificationLayer('Name','new_classoutput');
lgraph = replaceLayer(lgraph,classLayer.Name,newClassLayer);
figure('Units','normalized','Position',[0.3 0.3 0.4 0.4]);
plot(lgraph)
ylim([0,10])
layers = lgraph.Layers;
connections = lgraph.Connections;
layers(1:10) = freezeWeights(layers(1:10));
lgraph = createLgraphUsingConnections(layers,connections);
%% Train Network
pixelRange = [-30 30];
scaleRange = [0.9 1.1];
imageAugmenter = imageDataAugmenter( ...
'RandXReflection',true, ...
'RandXTranslation',pixelRange, ...
'RandYTranslation',pixelRange, ...
'RandXScale',scaleRange, ...
'RandYScale',scaleRange);
augimdsTrain = augmentedImageDatastore(inputSize(1:2),imdsTrain, ...
'DataAugmentation',imageAugmenter);
augimdsValidation = augmentedImageDatastore(inputSize(1:2),imdsValidation);
options = trainingOptions('sgdm', ...
'MiniBatchSize',10, ...
'MaxEpochs',6, ...
'InitialLearnRate',3e-4, ...
'Shuffle','every-epoch', ...
'ValidationData',augimdsValidation, ...
'ValidationFrequency',3, ...
'Verbose',false, ...
'Plots','training-progress');
net = trainNetwork(augimdsTrain,lgraph,options);
[YPred,scores] = classify(netTransfer,augimdsValidation);
accuracy = mean(YPred == imdsValidation.Labels);
After the while loop that does the resize etc, you need to create a new imageDatastore that uses the same inputs as the other one except that it needs to use file extension .png
Thanks for your advice!
you mean I add this code after while loop?
imds = imageDatastore(fullfile(currentdirectory, categories),'IncludeSubfolders',true,'FileExtensions','.png','LabelSource', 'foldernames');
however it still has error..
Error using trainNetwork (line 150)
Invalid training data. The output size (20) of the last layer does not match the number of classes (4).
Error in test_googlenet (line 98)
net = trainNetwork(augimdsTrain,lgraph,options);
Did you finally get it working? You've accepted this answer.
ssk
ssk 2019-2-17
编辑:ssk 2019-2-17
Sorry to reply again. I solved this problem and finally it worked well!
can you please tell how you solved that resizing problem
Walter said he had to do a loop after getting the datastore. This is exactly what I did in my code below so I imagine he used that or something very similar of his own making. Anyway geetha, it should work for you. It's fairly robust. Since you're asking, I'm assuming you tried the code and it didn't work for you after your modifications. So post your code and I'll fix it.

请先登录,再进行评论。

更多回答(3 个)

Image Analyst
Image Analyst 2019-2-17
编辑:Image Analyst 2019-2-17
Try this utility I wrote to create 227x227 images for input to an AlexNet deep learning network from a folder of aribtrary RGB, gray scale, or binary (logical) images. If that's what you want/need, please accept or vote for my Answer. For dicom images use dicomread() instead of imread().
% Utility to convert arbitrary RGB or gray scale images into RGB images for AlexNet deep learning network.
% Input images are in the current folder AND subfolders within that.
% All the 227x227 output images are created in a subfolder "For AlexNet" of the current folder (not subfolders of the subfolders where the images live).
clc; % Clear the command window.
clearvars;
close all; % Close all figures (except those of imtool.)
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
% Specify the folder where the files live.
myFolder = pwd; % Current folder. Or change to whatever you want.
% Check to make sure that folder actually exists. Warn user if it doesn't.
if ~isfolder(myFolder)
errorMessage = sprintf('Error: The following folder does not exist:\n%s', myFolder);
uiwait(warndlg(errorMessage));
return;
end
% Get a list of all files in the folder AND subfolders with the desired file name pattern.
imds = imageDatastore(pwd, 'FileExtensions','.png')
% Get a list of all filenames.
fileNamesImds = imds.Files;
% Now make an output folder. Create it if it does not exist already.
outputFolder = fullfile(myFolder, 'For AlexNet')
if ~exist(outputFolder, 'dir')
mkdir(outputFolder);
end
numberOfImages = length(fileNamesImds)
for k = 1 : numberOfImages
% Get the input file name.
inputFullFileName = fileNamesImds{k};
fprintf(1, 'Now reading input file "%s" (#%d of %d)\n', inputFullFileName, k, numberOfImages);
% Create the output file name.
[~, baseFileNameNoExt, ext] = fileparts(inputFullFileName);
outputBaseFileName = sprintf('AlexNet %s.png', baseFileNameNoExt);
outputFullFileName = fullfile(outputFolder, outputBaseFileName);
% Read in the input image.
inputImage = imread(inputFullFileName);
imshow(inputImage, []); % Display image.
title(baseFileNameNoExt, 'FontSize', fontSize, 'Interpreter', 'none');
drawnow; % Force display to update immediately.
% If it's logical (binary), convert to uint8, or else imwrite() will throw an error.
if isa(inputImage, 'logical')
inputImage = im2uint8(inputImage);
end
% Create a 227 x 227 RGB true color image.
[rows, columns, numberOfColorChannels] = size(inputImage);
fprintf(' Creating 227 by 227 output file "%s" from the %d by %d input image...\n', outputBaseFileName, rows, columns);
% Ref: https://www.learnopencv.com/number-of-parameters-and-tensor-sizes-in-convolutional-neural-network/
% "Color images of size 227x227x3. The AlexNet paper mentions the input size of 224×224 but that is a typo in the paper."
if numberOfColorChannels == 1
% It's gray scale. Convert to RGB by concatenating gray scale images along the third dimension.
inputImage = cat(3, inputImage, inputImage, inputImage);
end
outputImage = imresize(inputImage, [227, 227]);
% Save that array to the PNG output file
imwrite(outputImage, outputFullFileName);
end
message = sprintf('\nDone creating %d images in folder:\n%s.', numberOfImages, outputFolder);
fprintf('%s\n', message);
uiwait(helpdlg(message));
% Open the folder (Windows ONLY). Comment out for Mac.
winopen(outputFolder);

1 个评论

ssk
ssk 2019-2-17
编辑:ssk 2019-2-17
Thanks for your reply and sharing such a nice code! I already upvoted for you!

请先登录,再进行评论。

Image Analyst
Image Analyst 2019-2-16
编辑:Image Analyst 2019-2-16

1 个投票

Don't resize the third dimension. Don't try to do it all in one shot with imresize. Use imresize() to resize the lateral dimensions first to get a 227x227 gray scale image. Then use cat(3, grayscaleImage, grayscaleImage, grayscaleImage) to convert that image to RGB for AlexNet. At least that's how I'd do it.

3 个评论

Dear, Image Analyst
Thanks for your advice.
Since I'm very new to programming, would you give me more hint to imprement this method or show the exact source code?
Thanks for you in advance!
I wrrote my code as follows, however it still throws error..
Although I changed imds into img, it doesn't work well..
Error using imresize
Expected input number 1, A, to be one of these types:
single, double, int8, int16, int32, uint8, uint16, uint32, logical
Instead its type was matlab.io.datastore.ImageDatastore.
mdsResized = imresize(imds, [227 227]);
You cannot resize an imageDatastore -- I already told you that, and discussed readall() and cellfun() with you.

请先登录,再进行评论。

Anjali Acharya
Anjali Acharya 2019-3-2

0 个投票

Hello @Image Analyst
I have set my current directory as follows:
myFolder = 'D:\matlab\alexnet\myImages\'; % Current folder.
I have RGB images with different size which i wasn to resize to 227 for alexnet.
When I run the code I get
Undefined function or variable 'isfolder'. (line 16)
Isnt myFolder supposed to be myImages in my case?
Your response would be great help.

2 个评论

You probably have an old version of MATLAB. Use isdir() instead.
@Image Analyst
Thank you for your quick feedback.
I am using matlab 2017. isdir() works fine.

请先登录,再进行评论。

类别

帮助中心File Exchange 中查找有关 Deep Learning Toolbox 的更多信息

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by