I am running a script to create masks of 41 Controls, both Positive and Negative, for a total of 82 images. I don't know how to save the masks with names similar to the original .png files, such as "Masked Control_1 Positive", "Masked Control_1 Negative", etc to Control_41. I also don't know how to save these to a separate folder within my current folder. Thank you!
I have also included a screenshot of the current directory.
% GlassBrains_Controls2Mask.m
clear;
Files = dir('Control_*');
Controls_Results_Structure = struct('BW',[],'maskedRGBImage',[]);
for i = 1:length(Files)
RGB = imread(Files(i).name);
[Output_BW, Output_maskedRGBImage] = GlassBrainMask(RGB);
Controls_Results_Structure(i).BW = Output_BW;
Controls_Results_Structure(i).maskedRGBImage = Output_maskedRGBImage;
end
save("Controls_Results_Structure")
% Save the results
mkdir "Masked Glass Brains (Controls)"
for i = 1:length(Files)
Image_Number = i;
save(Controls_Results_Structure(Image_Number).BW);
end
Please notice that save() stores workspace variables in MAT files, which are generally meant to be opened with MATLAB only, not with image viewers and such. PNG files like those you are reading with imread() can be created with imwrite():
% Save the results
outdir='./Masked Glass Brains (Controls)';
[mkdir_status,~,~]=mkdir(outdir);
assert(mkdir_status,'Error creating output folder.');
clear mkdir_status;
for i=1:length(Files)
imwrite( Controls_Results_Structure(i).BW, ...
sprintf('%s/Masked %s',outdir,Files(i).name) ... %alternative: [outdir '/Masked ' Files(i).name]
);
end
To customize the image file that imwrite() creates from the output of GlassBrainMask(), see: https://www.mathworks.com/help/matlab/ref/imwrite.html
Related
I am stuck on something that is supposed to be so simple.
I have a folder, say main_folder with four sub folders, say sub1, sub2, sub3 and sub4 each containing over 100 images. Now am trying to read and store them in an array. I have looked all over the internet and some MATLAB docs:
here, here and even the official doc.
My code is like this:
folder = 'main_folder/**'; %path containing all the training images
dirImage = dir('main_folder/**/*.jpg');%rdir(fullfile(folder,'*.jpg')); %reading the contents of directory
numData = size(dirImage,1); %no. of samples
arrayImage = zeros(numData, 133183); % zeros matrix for storing the extracted features from images
for i=1:numData
ifile = dirImage(i).name;
% ifolder = dirImage(i).folder;
I=imread([folder, '/', ifile]); %%%% read the image %%%%%
I=imresize(I,[128 128]);
...
If I try the code in the above snippet, the images are not read.
But if I replace the first two lines with something like:
folder = 'main_folder/'; %path containing all the training images
dirImage = dir('main_folder/sub1/*.jpg'); %rdir(fullfile(folder,'*.jpg'));
then all images in sub1 are read. How can I fix this? Any help will be highly appreciated. I want to read all the images in the four sub folders at once.
I am using MATLAB R2015a.
I believe you will need to use genpath to get all sub-folders, and then loop through each of them, like:
dirs = genpath('main_folder/'); % all folders recursively
dirs = regexp(dirs, pathsep, 'split'); % split into cellstr
for i = 1:numel(dirs)
dirImage = dir([dirs{i} '/*.jpg']); % jpg in one sub-folder
for j = 1:numel(dirImage)
img = imread([dirs{i} '/' dirImage(j).name]);
% process img using your code
end
end
I am following up on my own question. By using:
excelWorkbook.SaveAs('figtest.xlsx');
I am overwriting the existing excel. I have created a function which uses the code to save two images to excel. Now I want to iterate over a number of images, process each image and then save the result alongside the original image to an excel. Obviously calling the function each iteration is a bad idea since, each iteration is deleting the results of former iterations.
How can I add the current data to the excel file without deleting any former data?
Is there a better way to do this?
Note that the data is images and not simple numeric data.
Create a COM server once, iterate over the images and place them in the desired cells, quit the server and then delete the server object.
Building from my previous answer, here is a working example with 5 of many built-in images:
%Some sample images
im{1}=imread('peppers.png');
im{2}=imread('cameraman.tif');
im{3}=imread('pears.png');
im{4}=imread('greens.jpg');
im{5}=imread('bag.png');
excel = actxserver('Excel.Application'); % Create server object
excelWorkbook = excel.Workbooks.Add(1); % Add a workbook
excelSheet = excel.ActiveSheet; % Get the active sheet
f = figure('visible','off'); % To not show the images in MATLAB
dpi = get(groot, 'ScreenPixelsPerInch'); % Get screen dpi
for k=1:5
imshow(im{k});
print(gcf, sprintf('-r%d', dpi), ... % Print the figure at the screen resolution
'-clipboard', '-dbitmap'); % to the clipboard as a bitmap
%Adjust the cell names where you want to paste the images as desired
excelSheet.Range(['B',num2str(k)]).PasteSpecial();
%Unlocking aspect ratio to adjust height and width of the image according to the cell
excelSheet.Shapes.Item(k).LockAspectRatio='msoFalse';
excelSheet.Shapes.Item(k).Width=excelSheet.Range(['B',num2str(k)]).Width;
excelSheet.Shapes.Item(k).Height=excelSheet.Range(['B',num2str(k)]).Height;
end
excelWorkbook.SaveAs('figtest.xlsx'); % Save workbook to a file
excelWorkbook.Close(); % Close workbook
excel.Quit(); % Quit server
excel.delete(); % Delete server object
which gives:
One approach is to place each set of images in its own sheet, creating new sheets in the Excel file as needed. Here's some sample code, modified from my previous answer:
% Start COM server:
excel = actxserver('Excel.Application');
excelWorkbook = excel.Workbooks.Add(1);
excelWorksheets = excelWorkbook.Worksheets;
% Initializations:
dpi = get(groot, 'ScreenPixelsPerInch');
for iSheet = 1:nIterations % Based on how many image sets you process
% Get a blank sheet:
if (iSheet == 1)
excelSheet = excel.ActiveSheet;
else
excelSheet = excelWorksheets.Add([], excel.ActiveSheet, 1);
end
% Load, process, and plot your images here:
...
% Paste image into sheet and adjust cell size:
print(hFigure, sprintf('-r%d', dpi), '-clipboard', '-dbitmap');
excelSheet.Range('B2').PasteSpecial();
excelSheet.Range('B2').RowHeight = excelSheet.Shapes.Item(1).Height;
widthScale = excelSheet.Range('B2').ColumnWidth./...
excelSheet.Range('B2').Width;
excelSheet.Range('B2').ColumnWidth = excelSheet.Shapes.Item(1).Width.*widthScale;
end
% Save and close workbook and stop COM server:
excelWorkbook.SaveAs('figtest.xlsx');
excelWorkbook.Close();
excel.Quit();
excel.delete();
Adding data to an excel file is not well defined: creating new sheets or adding data to an existing one?
Therefore, you probably need the following methodology:
Open the existing excel file (to which you want to add data)
Add the new data to the opened excel file
Save this edited excel file
Just found this here:
xlApp = actxserver('Excel.Application');
xlApp.visible = 1;
%Open the the spreadsheet
xlworkbook = xlApp.Workbooks.Open('figtest.xlsx');
xlsheet = xlworkbook.ActiveSheet;
mydata=randn(1,3);
data=xlsread('figtest.xlsx');
%Determine last row
last=size(data,1);
newRange=last+1;
xlCurrRange = xlsheet.Range(['A', num2str(newRange),':C', num2str(newRange)]);
xlCurrRange.Value2 = mydata;
%Save and Close the Excel File
invoke(xlworkbook,'Save');
invoke(excelApp,'Quit');
delete(excelApp);
Also, you may want to try this script from the File Exchange.
The bellow matlab code is to read 6 images from folder and save them in mat file
then return to read the mat file and check the images inside it
the problem is that
just the last images stores in mat file
the problem is in save function::
what should I edit to make save function store all images that stored in result cell into mat file
%Generate mat file
srcFile = dir('C:\Users\Desktop\images\*.jpg');
result = cell(1,length(srcFile));
for i = 1 : length(srcFile)
filename = strcat('C:\Users\Desktop\images\',srcFile(i).name);
I = imread(filename);
%figure, imshow(I);
I = imresize(I,[128 128]);
result{i} = I;
figure, imshow(result{i});
end
save images, result;
%Read mat file
for j =1 :length(srcFile)
filename = strcat('C:\Users\Desktop\images\',srcFile(j).name);
I = imread(filename);
a='I';
input = load('images.mat',a);
figure, imshow(input.(a));
end
Your first loop, up to the save, is fine.
When you load the data, use load('images.mat') before the second loop. Then, you have back the result variable in your workspace and you iterate on it:
load('images.mat')
for j = 1:length(srcFile)
figure, imshow(result{j});
end
What you have to remember is that your .mat file only contains the variables you saved, but you can't access them directly with load. You first load them, and then access the loaded variables (which have a different name from the file, usually).
Finally, if you want to check this code, you need to clear the workspace after the save, otherwise you may not notice that some of the variables you use are not there anymore (like the error you have got with I).
I have certain images in a directory and I want to load all those images to do some processing. I tried using the load function.
imagefiles = dir('F:\SIFT_Yantao\demo-data\*.jpg');
nfiles = length(imagefiles); % Number of files found
for i=1:nfiles
currentfilename=imagefiles(i).name;
I2 = imread(currentfilename);
[pathstr, name, ext] = fileparts(currentfilename);
textfilename = [name '.mat'];
fulltxtfilename = [pathstr textfilename];
load(fulltxtfilename);
descr2 = des2;
frames2 = loc2;
do_match(I1, descr1, frames1, I2, descr2, frames2) ;
end
I am getting an error as unable to read xyz.jpg no such file or directory found, where xyz is my first image in that directory.
I also want to load all formats of images from the directory instead of just jpg...how can i do that?
You can easily load multiple images with same type as follows:
function Seq = loadImages(imgPath, imgType)
%imgPath = 'path/to/images/folder/';
%imgType = '*.png'; % change based on image type
images = dir([imgPath imgType]);
N = length(images);
% check images
if( ~exist(imgPath, 'dir') || N<1 )
display('Directory not found or no matching images found.');
end
% preallocate cell
Seq{N,1} = []
for idx = 1:N
Seq{d} = imread([imgPath images(idx).name]);
end
end
I believe you want the imread function, not load. See the documentation.
The full path (inc. directory) is not held in imgfiles.name, just the file name, so it can't find the file because you haven't told it where to look. If you don't want to change directories, use fullfile again when reading the file.
You're also using the wrong function for reading the images - try imread.
Other notes: it's best not to use i for variables, and your loop is overwriting I2 at every step, so you will end up with only one image, not four.
You can use the imageSet object in the Computer Vision System Toolbox. It loads image file names from a given directory, and gives you the ability to read the images sequentially. It also gives you the option to recurse into subdirectories.
So I just started with image processing/computer vision in MATLAB.
So my first task is to convert a series of images(frames) into a video. So I went through online sources (MATLAB website more specifically) to get a way to do it.
So the one that I implemented is http://www.mathworks.com/help/matlab/examples/convert-between-image-sequences-and-video.html which solved the problem for me.
However, when I play it, the video seems jumpy in some places. Like it would bring a different frame in the middle and make the whole video jumpy for that split second. It happens a couple of places in the video.
Any anyone knows why this happens?
Thanks
PS below is the code I use:
myFolder = 'C:\Users\owner\Desktop\MATLAB GUI\Color\Color'; %Specify Directory
filePattern = fullfile(myFolder, '*.jpg') %identify jpg files
jpegFiles = dir(filePattern) %use dir to list jpg files
size = length(jpegFiles); % length of the size of the file
outputVideo = VideoWriter(fullfile(myFolder,'video1.avi'));
outputVideo.FrameRate = 30;
open(outputVideo);
for i = 1:length(jpegFiles) %load all the files in the directory
j = i; %%accumulating the number of jpegfiles into handles.j
baseFileName = jpegFiles(i).name;
fullFileName = fullfile(myFolder, baseFileName);
%fprintf(1, 'Now reading %s\n', fullFileName); %filename of image
imageArray = imread(fullFileName); %image being read
%imageArray = rgb2gray(imageArray);
imagecell{i} = imageArray; %storing the images in imagecells
writeVideo(outputVideo,imagecell{i});
end
close(outputVideo);
video1 = VideoReader(fullfile(myFolder,'video1.avi'));
mov(video1.NumberOfFrames) = struct('cdata',[],'colormap',[]);
for ii = 1:video1.NumberOfFrames
mov(ii) = im2frame(read(video1,ii));
end
set(gcf,'position', [150 150 video1.Width video1.Height])
set(gca,'units','pixels');
set(gca,'position',[0 0 video1.Width video1.Height])
image(mov(1).cdata,'Parent',gca);
axis off;
movie(mov,1,video1.FrameRate);
Given that there may be too many files to be renamed (padded with zeros) here is a quick function that will do it for you: you just need to provide the directory/folder where the images are stored, the padding (if less 100 files, then padding can be 2; if less than 1000 files, then padding can be 3; etc.), and a common pattern. The code assumes that there is a common pattern in each file (like 'frame' or 'image') that when removed, leaves just the number:
renameFiles(directory,padSize,fileNamePattern)
filePattern = fullfile(directory, '*.jpg') %identify jpg files
jpegFiles = dir(filePattern) %use dir to list jpg files
for k=1:size(jpegFiles)
% get the source file that will be moved/renamed
fileSrc = jpegFiles(k).name;
% get the parts of the file
[path,name,ext] = fileparts(fileSrc);
% where does the pattern fit in the name?
idx = strfind(name,fileNamePattern);
% remove the pattern from the name
if idx==0
% pattern does not exist in file so skip it
continue;
elseif idx==1
% pattern is at the beginning of name so remove it
frameNumberStr = name(length(fileNamePattern)+1:end);
else
% pattern is at the end of name so remove it
frameNumberStr = name(1:idx-1);
end
% get the number of digits
numDigits = length(frameNumberStr);
% create the new file name
paddedName = [fileNamePattern repmat('0',1,padSize-numDigits) frameNumberStr];
fprintf('%s\n',paddedName);
% only move if the destination is different
if strcmp(paddedName,name) ~= 1
% set the destination file
fileDest = fullfile(directory,[paddedName ext]);
% move the file
movefile(fileSrc, fileDest,'f');
end
end
end
An example - if all files have the common pattern of 'frame' and there are less than 1000 files, then run this function as
rename(pwd,3,'frame')
All files that were named as frame1.jpg or frame99.jpg are now named as frame001.jpg and frame099.jpg.
Hope this helps!
If you have the Computer Vision System Toolbox you can use the vision.VideoFileWriter object. You can simply feed images into its step() method one at a time, and they will be written to the video file as video frames. Note that the images must all be the same size and have the same data type.