Returning a 4D array from a function in MATLAB - image

I am trying to return a 4D array of image data from a function call in MATLAB. I'm not very advanced in MATLAB and I don't know what type of data I have to return from the function. Here is my function:
function classimg = loadImages(classdir,ext)
% create array of all images in directory
neg = dir([classdir ext]);
% get size of array (to loop through images)
numFileNeg = max(size(neg));
% create a 4D array to store our images
classimg = zeros(51,51,3,numFileNeg);
% loop through directory
for i=1:numFileNeg
classimg(:,:,:,i) = imread([myDir neg(i).name]);
end
end
Here is the function call:
negativeImgs = loadImages("C:\Users\example\Documents\TrainingImages\negatives\","*.jpg");
I cannot find any online documentation for the return type? Does anyone know what this would be? classimg is populated correctly so the code inner works.

You initialize classimg to be a 51x51x3xnumFileNeg matrix of zeros. You use the zeros function, so the datatype is double. To see this clearly, call your function from the command window, and then type "whos" to see both the size and datatype of classimg.

As Mike correctly points out, since you initialize classimg using zeros, and the default data type is double, your image data will be converted to double from whatever data type imread returns (often uint8).
If you would like classimg to be the same data type as your images (which I'm assuming all have the same type), you can load one image, get its class, and initialize classimg with that specific class. Here's how you could rewrite your function:
function classimg = loadImages(classdir, ext)
neg = dir(fullfile(classdir, ext));
numFileNeg = numel(neg);
tempImage = imread(fullfile(classdir, neg(1).name));
classimg = zeros(51, 51, 3, numFileNeg, class(tempImage));
classimg(:, :, :, 1) = tempImage;
for i = 2:numFileNeg
classimg(:, :, :, i) = imread(fullfile(classdir, neg(i).name));
end
end
Note that I made a couple of other changes. I used fullfile instead of concatenation of the directory and file names, since it handles any issues with file separators for you. I also used numel to get the number of files as Justin suggested in a comment.

Related

How do I create a function that takes a .mat file and saves a pngs for each of the arrays?

I want to automate the imwrite function so that I can automatically create 184 pngs from my .mat data. I want to make a loop so that for each loop, the mat array increases in time by 1, and the save name increases by 1.
The inputs should look like this:
imwrite(stim_windows(:,:,1), 'C:\Users\mattmd\Downloads\Retinotopy-master\Retinotopy-master\Presentation\subjects\0007\pRF\221117\run49.1.png')
imwrite(stim_windows(:,:,2), 'C:\Users\mattmd\Downloads\Retinotopy-master\Retinotopy-master\Presentation\subjects\0007\pRF\221117\run49.2.png')
etc.
I tried making this function here:
function wewrite = wewrite(mypath, number_of_files)
global imwrite()
s = 1;
while s < number_of_files
filename = [mypath,(s),'.png'];
imwrite(:,:,s), filename;
s=s+1;
end
When I try inputting:
wewrite('C:\Users\mattmd\Downloads\Retinotopy-master\Retinotopy-master\Presentation\subjects\0007\pRF\221117\0007_stimulus_window_bar_run_49.mat',184)
It tells me that it's an invalid expression.
Any help is greatly appreciated!!

How to rename many images after processing with different parameters

Hello dear programmers,
I have a sequence of images and I would like to perform dilation on each of them with different dilation parameters. Then, I would like to save the processed images with new name including both the old name and the corresponding dilation parameter. My codes are as follows.
Input_folder =
Output_folder =
D = dir([Input_folder '*.jpg']);
Inputs = {D.name}';
Outputs = Inputs; % preallocate
%print(length(Inputs));
for k = 1:length(Inputs)
X = imread([Input_folder Inputs{k}]);
dotLocations = find(Inputs{k} == '.');
name_img = Inputs{k}(1:dotLocations(1)-1);
image1=im2bw(X);
vec = [3;6;10];
vec_l = length(vec);
for i = 1:vec_l
%se = strel('disk',2);
fprintf(num2str(vec(i)));
se = strel('diamond',vec(i)); %imdilate
im = imdilate(image1,se);
image2 = im - image1;
Outputs{k} = regexprep(Outputs{k}, name_img, strcat(name_img,'_', num2str(vec(i))));
imwrite(image2, [Output_folder Outputs{k}])
end
end
As it can be seen, I would like to apply dilation with parameters 3,6 and 10. Let us assume that an image has as name "image1", after processing it, I would like to have "image1_3", "image1_6" and "image1_10". However, I am getting as results "image1_3", "image1_6_3" and "image1_10_6_3". Please, how can I modify my codes to fix this problem?
This is because you rewrite each item of the Outputs variable three times, each time using the previous value to create a new value. Instead, you should use the values stored in Inputs new names. Another mistake in your code is that the size of Inputs and Outputs are equal, while for every file in the input folder, three files must be stored in the output folder.
I also suggest using fileparts function, instead of string processing, to get different parts of a file path.
vec = [3;6;10];
vec_l = length(vec);
Outputs = cell(size(Inputs, 1)*vec_l, 1); % preallocate
for k = 1:length(Inputs)
[~,name,ext] = fileparts([Input_folder Inputs{k}]);
% load image
for i = 1:vec_l
% modify image
newName = sprintf('%s_%d%s', name, vec(i), ext);
Outputs{(k-1)*vec_l+i} = newName;
imwrite(image2, [Output_folder newName])
end
end

How to setup my function with blockproc to process the image in parts?

I have an image:
I want to divide this image into 3 equal parts and calculate the SIFT for each part individually and then concatenate the results.
I found out that Matlab's blockproc does just that, but I do not know how to get it to work with my function. Here is what I have:
[r c] = size(image);
c_new = floor(c/3); %round it
B = blockproc(image, [r c_new], #block_fun)
So according to Matlabs documentation the function, block_fun will be applied to the original image in blocks of size r and c_new.
this is what I wrote as block_fun
function feats = block_fun(img)
[keypoints, descriptors] = vl_sift(single(img));
feats = descriptors;
end
So, my matrix B should be a concatenation of the SIFT descriptors of all three parts of the same image? right?
But the error that I get when I run the command:
B = blockproc(image, [r c_new], #block_fun)
Function BLOCKPROC encountered an error while evaluating the user
supplied function handle, FUN.
The cause of the error was:
Error using single Conversion to single from struct is not possible.
For your custom function, blockproc sends in a structure where the image data is stored in a field called data. As such, you simply need to change your function so that it accesses the data field in the input. Like so:
function feats = block_fun(block_struct) %// Change
[keypoints, descriptors] = vl_sift(single(block_struct.data)); %// Change
feats = descriptors;
end
This error is caused by the fact that the function that is called via its handle by blockproc expects a block struct.
The real problem is that blockproc will attempt to concatenate all results and you will have a different set of 128xN feature vectors for each block, which blockproc doesn't allow.
I think that using im2col and reshape would be much more simple.

Why does the result being so different

I was new to Matlab,and this time I want to create a function for its image process.
Firstly, I download a picture from the Internet.Then I named it "map.jpg",and copy to my workspace.latter,I create a M_files and type the code into the files.
for example:
function y=mean_data(gray)
s=size(gray);
sum=0;
for i=1:s(1)
for j=1:s(2)
sum=sum+gray(i,j);
end
end
y=sum/(s(1)*s(2));
Finally,the difference happenend:
if I call the function in this way:
I=imread('map.jpg');
J=rgb2gray(I);
mean=mean_data(double(J))
the result will be OK.
However if I call in this way:
I=imread('map.jpg');
J=rgb2gray(I);
mean=mean_data(J)
the result will be zero.
So why does the result being so different?And thank you for helping me!!!
This is becuase the default output format of the data read by imread
is uint8 that is - 8 bit per R/G/B. With 8 bit you can't get any integer
higher than 255. Take a look:
>> uint8(250) + uint8(5)
ans =
255
>> uint8(250) + uint8(6)
ans =
255
So then, during division in your function this thing happens:
>> uint8(255) / 12345
ans =
0
However, when you use double() you change the representation of
your data to 64 bit floating point - a lot more room for representing big
numbers.
Instead of using your loop function you can use matlab's mean
function - it works well with uint8 format:
>> mean(uint8([255, 231]))
ans =
243
So you can use:
mean_dat = mean(mean(J));
% it is also not a good idea to name a variable 'mean'
% if you are going to use the mean function so I renamed
% your variable to mean_dat

Inserting multiple links into an image in Matlab?

This question is built off of this previous question 'here' I want to make 256 points on the image that all lead to different pdf documents based on the location of the *. I dont want to have to code in 256 separate filepaths. I have attempted some code below and have not been having any luck so far.
for i = 1:256
text(x(i),y(i),'*', 'ButtonDownFcn',['open(''' file ''');']);
end
function [filePath] = file()
%h = impoint;
%position = getPosition(h);
filePath = strcat('C:\Documents and Settings\Sentinelle\Desktop\LCModel\sl5_knt1\sl5_',x(1),'-',y(i),'.pdf');
end
It seems to me that your code is wrong in several places:
the file() function doesn't know the values of x and y
the file() function doesn't use the current value of i
the file path uses x(1) idependently of the value of i
You probably want
for i = 1:256
text(x(i), y(i), '*', 'ButtonDownFcn', ['open(''' file(x(i),y(i)) ''');']);
end
function [filePath] = file( x, y )
filePath = strcat('C:\Documents and Settings\Sentinelle\Desktop\LCModel\sl5_knt1\sl5_',x,'-',y,'.pdf');
end
Assuming x(i) and y(i) are integers, this should work:
prefix = 'C:\Documents and Settings\Sentinelle\Desktop\LCModel\sl5_knt1\sl5_'
for i = 1:256
filePath = [prefix num2str(x(i)) '-' num2str(y(i)) '.pdf'];
text(x(i),y(i),'*', 'ButtonDownFcn',['open(''' filePath ''');']);
end
If they aren't integers, you need to specify how the floating point number will be converted to a string. You can do that with the second argument of num2str, type:
help num2str
for details and browse from there.

Resources