How to save each row as image in MATLAB

Hello everyone, I hope you are doing well.
I have the following dataset which consists three class and dataset shape 3000x1000
first 1000x1000 belongs to class 1. next 1000x1000 belongs to class 2 and next 1000x1000 belongs to class 3 to make total of 3000x1000
i want so save each row as image form to train Resnet50 How can i do that?

 Accepted Answer

AndresVar
AndresVar on 9 Mar 2022
Edited: AndresVar on 10 Mar 2022
Edit: use rescale the entire dataset instead of each row.
Edit: note in the example I put padding on the data to shape it into a square, but you could just reshape rectangular and then resize to square.
clear;
load("Dataset1000x1000.mat")
[labelNums,~,labelIdx] = unique(labels1000,'rows');
labelStrs = strcat('Label_',strrep(cellstr(num2str(labelNums)),' ',''))
%% make the folders
for ii = 1:numel(labelStrs)
labelStr = labelStrs{ii};
if ~isfolder(labelStr)
mkdir(labelStr);
end
end
%% create RGB from data
% for example as in https://www.mathworks.com/help/wavelet/ug/classify-time-series-using-wavelet-analysis-and-deep-learning.html
[numImages, lenImage] = size(Dataset1000);
nextSquareLen = (floor(sqrt(lenImage))+1)^2;
squarePadLen = nextSquareLen-lenImage;
im_size = [224 224];
DataSet1000Scaled = rescale(Dataset1000);
for ii = 1:100:numImages
im_orig = DataSet1000Scaled(ii,:);
im_orig_pad = reshape(... % reshape to a square image
padarray(... % pad to a square length
im_orig,[0,squarePadLen],'post'),sqrt(nextSquareLen),[]);
im_rgb = imresize(... % resize for compatibility with NN
ind2rgb(... % make into RGB with a colormap
im2uint8(...
im_orig_pad),jet(255)),im_size);
folderName = labelStrs{labelIdx(ii)};
im_FullFilename = fullfile(folderName,sprintf('im_%06g.jpg',ii));
imwrite(im_rgb,im_FullFilename);
end
Edit: OR save patterns inferred from the data. Change loop conditions to get all images. Change SE size (instead of 16) to something smaller to your liking.
%% create grayscale shapes that resemble the data
[numImages, lenImage] = size(Dataset1000);
imSz = 1000; % assuming images are 1000x1000
imbg = true(imSz); % background "color"
imfg = ~imbg(1,1); % forground "color"
imSizeOut=[224 224]; % resize to 224 by 224
for imNum = 1:200:numImages
imData = Dataset1000(imNum,:); % get pattern
[~,Y] = meshgrid(1:imSz); % make a grid
% black and white image
BW = imbg;
BW(Y==imData)=imfg;
% make pattern thicker by eroding (helps during resizing)
SE=strel("disk",16); % adjust element size, 16 might be too big for cluttered patters
BW=imerode(BW,SE);
% resize (from 1000x1000 to 224x224)
BW=imbinarize(imresize(double(BW),imSizeOut));
% convert to uint8 (0 255)
im = im2uint8(BW);
% flip
im = flipud(im);
folderName = labelStrs{labelIdx(imNum)};
im_FullFilename = fullfile(folderName,sprintf('im_%06g.png',imNum));
imwrite(im,im_FullFilename);
end

24 Comments

@AndresVar its not working its save like the following image. but my each row has different shape
@AndresVar we can also generate binary image using this above data
@AndresVar There should be 1000 images for each class
Re: number of images per class
Change the for loop interation condition, I skipped every 100 for testing (1:100:numImages)
Re: image shape/not working
I don't know how to turn 1x1000 into your image. looking at the data it didn't seem like an image. But I just guessed that the array contains pixel intensity values so I just reshaped it into a 32x32 px image.
@AndresVar where you reshape 32x32 px image?
@AndresVar Is it possible we can convert image into binary/grayscale image
The RGB image does not contain the shape of every row
yes,sir, make 1*1000 vector as image,or use origin data to 4-D matrix,and train it
@yanqi liu how can i make 1x1000 vector as image?
@Med Future btw i editted the answer because I see now that the scaling should be relative to the whole dataset. That was causing all flat images (from class 1) to look the same.
Anyway, you want to have 1x1000 pixel images? You can use imwrite(A,filename). Since your data is bigger than uint8 you can try isomething like
% look at image #1500
im = Dataset1000(1500,:);
imagesc(im)
% save it
imwrite(uint16(im),'image_1500.tif');
Although it's strange to have images with this shape 1x1000, it will look like a black line to the naked eye.
Also resnet50 by default wants rgb images 224x224
Edit: the pattern is off, i'll try again later.
@Med Future i see, something like this maybe?
image 400: , image 2600:
clear;
load("Dataset1000x1000.mat")
imNum = 2600; % which image (row?)
imbg = true(1000); % background "color"
imfg = ~imbg(1,1); % forground "color"
imSizeOut=[224 224]; % resize to 224 by 224
imFullFilenameOut = sprintf('im%06g.png',imNum); % name the file im######.tif
imData = Dataset1000(imNum,:); % get pattern to paint
BW = imbg; % start blank
BW(imData,:)=imfg; % paint the pattern
BW = imbinarize(imresize(double(BW),imSizeOut)); % make smaller
imwrite(BW,imFullFilenameOut); % save image
@Med Future ok I think this should work
img 2200: img 2600:
clear;
load("Dataset1000x1000.mat")
imNum = 2600; % which image (row?)
imSz = 1000;
imbg = true(imSz); % background "color"
imfg = ~imbg(1,1); % forground "color"
imSizeOut=[224 224]; % resize to 224 by 224
imFullFilenameOut = sprintf('im%06g.png',imNum); % name the file im######.tif
imData = Dataset1000(imNum,:); % get pattern
[~,Y] = meshgrid(1:imSz);
BW = imbg; % start blank
BW(Y==imData)=imfg; % paint the pattern
BW = flipud(imbinarize(imresize(double(BW),imSizeOut))); % make smaller
imwrite(BW,imFullFilenameOut); % save image
@AndresVar Can you please modified it to run on all dataset and saved in folder with class label like you do in above code?
@AndresVar Why some line are more brighter then other? as seen in the picture?
@AndresVar grayscale image has intensity value between 0 255 but i can see in matrix it is only pixel intensity is 1 for shape
Re: loop
I edited my answer now. From what I can see the erosion size of 16 might be too big for class 2, you can play around with smaller sizes.
Re: 0 255 grayscale
im = im2uint8(BW);
Re: brighter lines
That's an issue with the resizing because the lines are so thin (1 pixel in a 1000x1000 image). You can skip resizing.
OR you can make the patterns thicker by applying erosion (see code below): Erode image - MATLAB imerode (mathworks.com). Here I use disk element, but you can try other square, line, etc.
Re: resizing and grayscale
Resizing binary image is tricky because you can loose data, so it's turned to double first (see code below): double->resize->binarize->uint8
The alternative is to simply: uint8->resize, but you will loose the high contrast.
clear;
load("Dataset1000x1000.mat")
imNum = 2600; % which image (row?)
imSz = 1000;
imbg = true(imSz); % background "color"
imfg = ~imbg(1,1); % forground "color"
imSizeOut=[224 224]; % resize to 224 by 224
imFullFilenameOut = sprintf('im%06g.png',imNum); % name the file im######.tif
imData = Dataset1000(imNum,:); % get pattern
[X,Y] = meshgrid(1:imSz);
% black and white image
BW = imbg;
BW(Y==imData)=imfg;
% make pattern thicker by eroding
SE=strel("disk",16);
BW=imerode(BW,SE);
% resize
BW=imbinarize(imresize(double(BW),imSizeOut));
% convert to uint8 (0 255)
im = im2uint8(BW);
% flip
im = flipud(im);
imwrite(im,imFullFilenameOut); % save image
@AndresVar i have accepted the answer but i have one question.
Did the unit8 conversion effect the pixel values? and why apply double before binarization?
@AndresVar How can i make the folder with class name How to change labelStrs
for example folder name have class name fixed,constant,variable.
AndresVar
AndresVar on 12 Mar 2022
Edited: AndresVar on 12 Mar 2022
Re: uint8/doble etc.
  • yes uint8 affects the pixels in the image. It was used on a binary image so the only effect is turning 1's into 255.
  • double helps during resizing. If the binary images has fine or small strcutures they will get lost during interpolation. But the erosion via imerode should help it also.
  • I think you have to experiment with what gives better results. Maybe don't use double and use im2uint8 without imbinarize at the end, etc. Resizing is probably what changes your data the most.
Re: labels
replace 4th line with labelStrs = {'fixed','constant','variable'}
Why you use flipud?
@Med Future that is just because image's matrix rows start at the top, but in your comments you posted images of plots in cartessian coordinates which start at bottom (y=0).
flipping is not that important i guess. in fact when you train you may want to randomly flip some images to synthetically "expand" your training set
when i create grid of 1000x1000. The X-axis start from 0 to 1000 but Y axis is upper side 0 to 1000 as you can see in the following image , but i want Y axis to be start from Lower 0 to 1000
That's the convention for matrixes and images - the y=1 value is at the top. If you want to reverse it use "axis xy" like
grayImage = imread('cameraman.tif');
[rows, columns, numberOfColorChannels] = size(grayImage);
subplot(2, 1, 1);
imshow(grayImage);
axis('on', 'xy');
subplot(2, 1, 2);
imshow(flipud(grayImage));
axis('on', 'xy');
@Image Analyst but [X,Y] = meshgrid(1:imSz); create the above image i have shared how can i change that?
@Image Analyst when i run this code above But when i saved my image the grid is shown as above but i want it to be in Y axis should be start from 0 -1000
clear;
load("Dataset1000x1000.mat")
imNum = 2600; % which image (row?)
imSz = 1000;
imbg = true(imSz); % background "color"
imfg = ~imbg(1,1); % forground "color"
imSizeOut=[1000 1000]; % resize to 224 by 224
imFullFilenameOut = sprintf('im%06g.png',imNum); % name the file im######.tif
imData = Dataset1000(imNum,:); % get pattern
[X,Y] = meshgrid(1:imSz);
% black and white image
BW = imbg;
BW(Y==imData)=imfg;
% make pattern thicker by eroding
SE=strel("disk",16);
BW=imerode(BW,SE);
% resize
BW=imbinarize(imresize(double(BW),imSizeOut));
% convert to uint8 (0 255)
im = im2uint8(BW);
imwrite(im,imFullFilenameOut);

Sign in to comment.

More Answers (0)

Products

Release

R2021b

Asked:

on 9 Mar 2022

Edited:

on 21 Mar 2022

Community Treasure Hunt

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

Start Hunting!