Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

pixelLabelDatastore from loaded image in workspace

I have multiple small *.mat files, each containing 4 input images (template{1:4} and a second channel template2{1:4}) and 4 output images (region_of_interests{1:4}), a binarized ('mask') image to train a deep neural network.

I basically followed an example on Mathworks and it suggests to use a function (in this example @matreader) to read in custom file formats.

However ...

  1. It seems impossible to load multiple images from one *.mat file using any load function as it only allows one output, and imageDatastore doen't seem to allow loading data from workspace. How could this be achieved?
  2. Similarly, it seems impossible to load a pixelLabelDatastore from a workspace variable. As a workaround I ended up saving the contents of my *.mat file to an image (using imwrite, saving to save_dir), and re-loading it from there (in this case, the function doesn't even allow to load *.mat files.). (How) can this be achieved without re-saving the file as image?

Here my failed attempt to do so:


%main script
image_dir = pwd; %location of *.mat files
save_dir  = [pwd '/a/']; %location of saved output masks
imds = imageDatastore(image_dir,'FileExtensions','.mat','ReadFcn',@matreader); %load template (input) images
pxds = pixelLabelDatastore(save_dir,{'nothing','something'},[0 255]);%load region_of_interests (output) image

%etc, etc, go on to train network

%matreader function, save as separate file
function data=matreader(filename)
  in=1; %give up the 3 other images stored in template{1:4}
  load(filename); %loads template and template2, containing 4x input images each
  data=cat(3,template{in},template2{in}); %concatinate 2 template input images in 3rd dimension
end

%generate example data for this question, will save into a file 'example.mat' in workspace
for ind=1:4
  template{ind}=rand([200,400]);
  template2{ind}=rand([200,400]);
  region_of_interests{ind}=rand([200,400])>.5;
end
save('example','template','template2','output')
like image 371
user2305193 Avatar asked Nov 30 '18 12:11

user2305193


1 Answers

You should be able to achieve this using the standard load and save function. Have a look at this code:

image_dir = pwd;
save_dir = pwd;

imds = imageDatastore(image_dir,'FileExtensions',{'.jpg','.tif'});
pxds = pixelLabelDatastore(save_dir,{'nothing','something'},[0 255]);
save('images.mat','imds', 'pxds')

clear
load('images.mat')  % gives you the variable "imds" and "pxds" directly -> might override previous variables
tmp = load('images.mat'); % saves all variables in a struct, access it via tmp.imds and tmp.pxds

If you only want to select the variables you want to load use:

load('images.mat','imds')        % loads "imds" variable
load('images.mat','pxds')        % loads "pxds" variable
load('images.mat','imds','pxds') % loads both variables

EDIT

Now I get the problem, but I fear this is not how it is going to work. The Idea behind the Datastore objects is, that it is used if the data is too big to fit in memory as a whole, but every little piece is small enough to fit in memory. You can use the Datastore object than to easily process and read multiple files on a disk. This means for you: Simply save your images not as one big *mat file but as multiple small *.mat files that only contain one image.

EDIT 2

Is it strictly necessary to use an imageDatastore for this task? If not you can use something like the following:

image_dir = pwd;
matFiles = dir([image_dir '*.mat']);
for i=1:length(matFiles)
    data = load(matFiles(i).name);
    img = convertMatToImage(data); % write custom function which converts the mat input to your image
    % or something like this:
    % for j=1:4
        % img(:,:,j) = cat(3,template{j},template2{j});
    % end

    % process image
end

another alternative would be to create a "image" in your 'matreader' which does not only have 2 bands but to simply put all bands (all templates) on top of each other providing a "datacube" and then in an second step after iterating over all small mat files and reading them splitting the single images out of the one bigger datacube.

would look something like this:

function data=matreader(filename)
load(filename);
for in=1:4
    data=cat(3,template{in},template2{in}); 
end
end

and in your main file, you have to simply split the data into 4 pieces.

I have never tested it but maybe it is possible to return a cell instead of a matrix?

function data=matreader(filename)
load(filename);
data = cell(1,4)
for in=1:4
    data{in}=cat(3,template{in},template2{in}); 
end
end

Not sure if this would work.

However, the right way to go forward from here really depends on how you plan to use the images from imds and if it is really necessary to use a imageDatastore.

like image 194
user7431005 Avatar answered Oct 25 '22 04:10

user7431005