Matlab imwrite - a filename must be supplied - matlab

I have an image in the directory:
C:\Users\me\folder\A1B1\A\0001.bmp
I have multiple directories ('A1B1\A', 'A1B1\B', 'A3B1\A', ...). After reading in that image and modifying it, I store the image under the variable I. I tried to save that modified image as 0001_1.bmp using
a = 'C:\Users\me\folder'
b= 'A1B1'
c = 'A'
img = '0001.bmp'
sp=strsplit(img(1), '.');
full = fullfile(a, b, c);
scat=strcat(full, '\', sp(1), '_1.bmp');
imwrite(I,scat);
but I get
Error using imwrite>parse_inputs (line 523)
A filename must be supplied.
How can I resolve this?

Your current code produces a cell (not a character array) containing the following file name:
C:\Users\me\folder\A1B1\A\0_1.bmp
which seems to diverge from the desired output:
C:\Users\me\folder\A1B1\A\0001_1.bmp
This should fix your problem:
a = 'C:\Users\me\folder';
b = 'A1B1';
c = 'A';
img = '0001.bmp';
sp = strrep(img, '.', '_1.');
full = fullfile(a,b,c,sp);
imwrite(I,full);

Related

Converting all images in a certain folder from .tiff to .jpg using MATLAB

I am trying to convert all .tiff-files inside a certain folder to .jpg.
I have tried executing
ReadImgs('home/luisa/misc','*.tiff');
using the following function:
function X = ReadImgs(Folder,ImgType)
Imgs = dir([Folder '/' ImgType]);
NumImgs = size(Imgs,1);
image = double(imread([Folder '/' Imgs(1).name]));
for i=1:NumImgs,
[pathstr,name,ext] = fileparts(Imgs(i).name);
concatena=strcat(name,'.jpg');
imwrite(y,concatena);
end
end
But I get this error:
>> codigoPruebas
Index exceeds matrix dimensions.
Error in ReadImgs (line 4)
image = double(imread([Folder '/' Imgs(1).name]));
Error in codigoPruebas (line 7)
ReadImgs('home/luisa/misc','*.tiff');
How can I resolve this?
Check the output of dir, it does return an empty struct. That's because you passed an invalid path. It's /home/luisa/misc not home/luisa/misc. Absolute path start with / relative path not.
Some additional advices in writing robust code:
Instead of [Folder '/' ImgType] use fullfile(Folder,ImgType). It's more robust (avoids duplicate file separators) and os independent.
Use im2double instead of double to convert images. This automatically scales to 0...1
There are multiple things wrong with your solution:
The error you are getting is because you are trying to access Imgs(1), even though it is empty. This is because you supplied a wrong file path: home/luisa/misc instead of /home/luisa/misc
You only read the first image, as image = double(imread([Folder '/' Imgs(1).name])); is not inside the for-loop. (And only accesses Imgs(1) instead of Imgs(i))
imwrite(y,concatena); should use image instead of y, as y is never defined.
Implementing these changes will result in:
function convertAllToJpg(Folder,ImgType)
Imgs = dir(fullfile(Folder,ImgType));
for i=1:numel(Imgs)
oldFilename = fullfile(Folder, Imgs(i).name);
[~,name,~] = fileparts(Imgs(i).name);
newFilename = fullfile(Folder, strcat(name, '.jpg'));
imwrite(imread(oldFilename), newFilename);
end
end
This is my answer, you can use it in your Matlab as a function
suppose oldFolder is store your origin image type
newFolder is store your change image type
ImgType is your origin image type
and you can change jpg whatever you want.
function convertAllToJpg(oldFolder,newFolder,ImgType)
Imgs = dir(fullfile(oldFolder,ImgType));
for i=1:numel(Imgs)
oldFilename = fullfile(oldFolder, Imgs(i).name);
[~,name,~] = fileparts(Imgs(i).name);
newFilename = fullfile(newFolder, strcat(name, '.jpg'));
imwrite(imread(oldFilename), newFilename);
end
end

Reconstruct directories from file MATLAB

Thanks for your help.
The problem is:
I need the user to select a file based on an extension lets say .tif. I used the standard method, i.e.
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
But I need to fetch other image files from other subdirectories. Say the directory name returned to locn is: /user/blade/checklist/exp1/trial_1/run_1/exp001.tif. Image goes to exp100.tif.
I want to access:
/user/blade/checklist/exp1/trial_1/run_2/exp001.tif.
Also access:
/user/blade/checklist/exp1/trial_2/run_2/exp001.tif.
Up to trial_n
But if I list directory in /user/blade/checklist/exp1/, I get all folders therein from where I can reconstruct the right path. The naming structure is orderly.
My current solution is
[flnm,locn]=uigetfile({'*.tif','Image files'}, 'Select an image');
ext = '.tif';
parts = strsplit(locn, '/');
f = fullfile(((parts{end-5}),(parts{end-4}),(parts{end-3}),(parts{end-2}),(parts{end-1}));
Which is really ugly and I also lose the first /. Any help is appreciated.
Thanks!
First, get the file location as you did; note a small change I've made to make use of the variable ext.
ext = '.txt';
[flnm,locn]=uigetfile({['*',ext]}, 'Select an image');
parts = strsplit(locn,'/');
root = parts(1:end-4);
parts has 2 information - 1) path of the selected file; 2) path of your working folder, checklist, which you need. So root has the working folder.
Then, list out all the files you wanted, and put them in a cell array.
The file names should contain partial (subfolder) paths; it's not difficult to follow the pattern.
flist = {'trial_1/run_1/exp001.tif', ...
'trial_1/run_1/exp002.tif', ...
'trial_1/run_2/exp001.tif', ...
'trial_2/run_1/exp001.tif', ...
'trial_2/run_2/exp001.tif'};
I just enumerated a few; you can use a for loop to automatically generate trial_n and expxxx.tif. An example code to generate the complete file list (but not "full paths") -
flist = cell(10*2*100,1);
for ii = 1:10
for jj = 1:2
for kk = 1:100
flist{sub2ind([10,2,100],ii,jj,kk)} = ...
sprintf('trial_%d/run_%d/exp%03d%s', ii,...
jj, kk, ext);
end
end
end
Finally, use strjoin to concatenate the first part (your working folder) and second part (needed files in subfolders). Use cellfun to call strjoin for each cell in the file list cell array, so for every file you want you get a full path.
full_flist = cellfun(#(x) strjoin([root, x],'/'), ...
flist, 'UniformOutput', false);
Example output -
>> locn
locn =
/home/user/Downloads/exp1/trial_1/run_1/
>> for ii = 1:5
full_flist{ii}
end
ans =
/home/user/Downloads/trial_1/run_1/exp001.tif
ans =
/home/user/Downloads/trial_1/run_1/exp002.tif
ans =
/home/user/Downloads/trial_1/run_2/exp001.tif
ans =
/home/user/Downloads/trial_2/run_1/exp001.tif
ans =
/home/user/Downloads/trial_2/run_2/exp001.tif
>>
Note: You can either use
strjoin(str1, str2, '/')
or
sprintf('%s/%s', str1, str2)
They are equivalent.

Error: Cell contents reference from a non-cell array object

when I run the code below, I got the following error :
Cell contents reference from a non-cell array object.
folder can take 1 or several folders
for x=1:numel(folder)
y{x} = fullfile(folder{x},'Status.xml');
getFile = fileread(char(y{x}));
content{x} = strtok(getFile ,';');
end
>>whos folder
Name Size Bytes Class Attributes
folder 1x1 941 struct
>> numel(folder)
ans=
1
Assuming folder is a cell array, I believe this should work:
y = cell(numel(folder), 1);
for x=1:numel(folder)
y{x} = fullfile(folder{x},'Status');
getFile = fileread(char(y{x}));
content{x} = strtok(getFile ,';');
end
Your error is most likely with y{ii}. I guess y is not pre-defined.
Also: you use ii as index in y, whereas you use x in the loop.
In case folder is a normal matrix, have you tried using just folder(x)?
UPDATE:
I see from your updated question that folder is a struct, not a cell. Try the following, where you substitute .field with whatever you name your entries in folder.
y = cell(numel(folder), 1);
content = cell(numel(folder), 1);
for x=1:numel(folder)
y{x} = fullfile(folder(x).field,'Status');
getFile = fileread(char(y{x}));
content{x} = strtok(getFile ,';');
end

How to read a lot of DICOM files with Matlab?

I am using a script which generate a collection of strings in a loop:
'folder1/im1'
'folder1/im2'
...
'folder1/im3'
I assign the string to a variable, when I try to execute the img = dicomread(file); function I get the following error:
Error using dicomread>newDicomread (line 164)
The first input argument must be a filename or DICOM info struct.
Error in dicomread (line 80)
[X, map, alpha, overlays] = newDicomread(msgname, frames);
Error in time (line 14)
img = dicomread(file);
However, using the command line I don't get errors: img = dicomread('folder1/im1').
The code is the next:
for i=1:6 %six cases
nameDir = strcat('folder', int2str(i));
dirData = dir(nameDir);
dirIndex = [dirData.isdir];
fileList = {dirData(~dirIndex).name}; % list of files for each directory
n = size(fileList);
cd(nameDir);
for x = 1:n(2)
img = dicomread(strcat(pwd(), '/', fileList(x)));
end
cd('..');
end
What could be the error?
You've figured it out by now, haven't you.
Based on what you've written, you test
img = dicomread('folder1/im1');
when what you are having trouble with is
img = dicomread(file);
You need to actually test the line you are having trouble with. I would recommend:
putting a break point in test.m a the line img = dicomread(file). When you get to that line you can see what file is equal to. Also do whos file to make sure it is of class char and not a cell array or something random.
If you still want help, edit your original post and show the code where you assign those strings to file and tell us what happens when you type img = dicomread(file) at the command prompt.

Matlab: pass 'who' output on as argument

I have written a function that takes the names and values of the input variables and writes them to a file. eg.
a = 10;
b = 100;
writevars('file.txt',a,b);
gives me a file file.txt that contains:
\def\a{\num{10}}
\def\b{\num{100}}
It would now like to be able to pass on all variables that are found using the who command. Eg if who returns:
a b z
I would like to be able to use writevars as if I called writers('file.txt', a, b, z).
The main problem I have is that writevars makes use of inputname... (temporary variables won't work e.g. writevars('file.txt', 100) doesn't work since there is no name to be given in the file).
ANSWER
var_names = who;
for i = 1 : length(var_names)
evalin('caller',['writevars(''file.txt'', ' char(var_names(i)) ' )']);
end
You can use EVALIN to run who from within writevars, e.g.
function writevars(filename,varargin)
%# get a list of variable names in the calling workspace and read their values
if isempty(varargin)
listOfVars = evalin('caller','who');
values = cell(size(listOfVars));
for i=1:length(listOfVars)
values{i} = evalin('caller',listOfVars{i});
end
else
%# use inputname to read the variable names into listOfVars
end
%# --- rest of writevars is here ---
It can be used by using the return value of whos command:
function GetAllVars
a = 45;
x = 67;
ff = 156;
z = who();
for i=1:numel(z)
if ~isequal(z{i},'z')
fprintf(1,'%s = %f\n',z{i},eval(z{i}));
end
end