How to save multiple data in one text file - matlab

I want to save height and width value from multiple objects in one text file, but it only saved the last processed image data. Here's my code:
contents = get(hObject,'Value')
pilih=guidata(gcbo);
theImage{1}=getImage(handles.axes1);
theImage{2}=getImage(handles.axes2);
theImage{3}=getImage(handles.axes3);
theImage{4}=getImage(handles.axes4);
theImage{5}=getImage(handles.axes5);
for z = 1:5;
Img = theImage{z};
abu=rgb2gray(Img);
cb=imclearborder(abu);
thresh=graythresh(cb);
b=im2bw(cb,thresh);
bw=bwareaopen(b,60);
bwfill=imfill(bw,'holes');
s=regionprops(bwfill,'BoundingBox');
objects=cell(numel(s),1);
for idx=1:numel(s)
bb=floor(s(idx).BoundingBox);
out=bsxfun(#times,Img,uint8(bwfill));
objects{idx}=out(bb(2):bb(2)+bb(4),bb(1):bb(1)+bb(3),:);
end
X = zeros(3, numel(objects));
for k = 1:numel(objects)
k1=objects{k};
c1=rgb2gray(k1);
t1=graythresh(c1);
biner1=im2bw(c1,t1);
[height,width]=size(biner1);
a1=bwarea(biner1);
X(:,k)=[height;width;a1];
end
end
save grading/datauji.txt X -ascii;
What should I do? Thank you very much. Here's my images. There are 5 of them, and I want to save all of the objects height and width data in one txt file.

Try this code,
code
numel = 100;
file = fopen('ans.txt','w');
testdata = rand(3, numel);
X = zeros(3, numel);
for i=1:numel
X(:,i) = testdata(:,i);
fprintf(file,'%ld %ld %ld\n', X(1,i), X(2,i), X(3,i));
end
fclose(file);
I have created a dummy number of data points i.e 100. I have created random data in variable in 'testdata', then I have iterated 'numel' and every time saved saved all 3 data in comma separated type
ans.txt
11.0 2.2 3.1
4.2 5.2 1.1
32.1 542 12.1
12. 12 23
Hope this works.

Related

Open specific file with the specific words (16 bits) structure

I have a specific binary? file format containing datas about the configuration used to take a picture with a custom camera. This file format is named DAI and contains for example values of offset/gain/etc...
I am using a black-box script in java to turn this file into a .csv and I want to perform the same thing in Matlab. I've got a config file describing in ascii format how this file is built (name of the field, type of the data, first_word, last_word, low_bit, high_bit). For example I know that the first field in the DAI file will be :
spare1; PCHAR; first_word=0; low_bit=0; high_bit=7
But right now I have no clue of how to use this information. My first thought were to fopen() the file and use fread() to read the binary data from the file and turn it into the format I want but I don't know how to use the values of "last_word,high_bit,..." to do so. I have a limited understanding of binary files.
To sum up everything :
file.dai contains datas /
file.cfg contains the structure :
mband_1_start_line; PCHAR; first_word=12; low_bit=6; high_bit=15
mband_1_length; PCHAR; first_word=12; low_bit=0; high_bit=5
mband_1_gain; PCHAR; first_word=13; low_bit=0; high_bit=7
mband_1_offset; PCHAR; first_word=13; low_bit=8; last_word=14; high_bit=7
and I want to recover the datas corresponding to the fields like mband_1_offset.
If someone can help me to figure the good way of doing that I will be very thankful !
[EDIT : SOLVED] So thanks to your very helpful help I've manage to get the values for each field even when the header changes !!
Here's the final code :
Here's the final code :
...code to retrieve the content of the .cfg file....
%% Open and read the DAI file
fid = fopen(dai_file,'r','l');
% First thing is to skip the header
% We read a first time the file
dat=fread(fid,inf,'*uint8');
% We search for the position of the end of the header : NUL NUL ETX
% In decimal it gives :
skip = findstr(dat',[000,000,003]);
% We define the wordsize : 2 bytes (2 words)
wordsize = 2;
% We rewind the file to start over to get the values for each field
frewind(fid);
% We initiate the structure camdat containing the datas of the camera
camdat=struct;
% We start the loop for each field of the layout config file
for ct = 1:length(layout)
% Defining the words/bits
first_word = layout{ct,3};
last_word = layout{ct,5};
low_bit = layout{ct,4};
high_bit = layout{ct,6};
% We position to the "skip value + the position of the first_word in bytes"
fseek(fid,skip+first_word*wordsize,-1);
% We compute the number of words (last - first +1)
datasize=last_word-first_word+1;
% We read the datas as uint16 (words are 16bits)
data=fread(fid,datasize,'*uint16');
% We convert it to bits
% Case of 1 word
bits=bitget(data(1),[1:16]);
% Case of 2 words
if length(data) > 1
bits=[bits,bitget(data(2),1:16)];
high_bit = high_bit+16;
end
% We take only the bits that define the field (between low_bit and
% high_bit)
bits_used = bits(low_bit+1:high_bit+1);
% We convert the bits to dec
data = sum(bits_used.*uint16(2).^uint16([0:length(bits_used)-1]));
% We store it in the camdat.field struct
camdat.(layout{ct,1})=data;
end
% We close the DAI file
fclose(fid);
% Displaying for test
camdat
My approach in this case is to find the part of the file that matches your data.
fid = fopen('dai_file.dai','r','l');
dat=fread(fid,inf,'*uint8');
findstr(dat',[74,210,129,93]);
>> 891 1159 1427 1695 ....
Strange enough this happens 100 times.
If byte 891 is right than bios_1 is NOT in the 4th word from bit 0 to 7, but in the 445th word bit 0 to 7.
Let's try
fid = fopen(dai_file,'r','l');
fseek(fid,445*2,-1)
data=fread(fid,1,'*uint16');
bits=bitget(data(1),[1:16]);
bits = bits(1:8);
data = sum(bits.*uint16(2).^uint16([0:7]))
>> data = 74
Yep, there it is. So I would suggest to add 441 to each word entry and see if it works.
Oke, so you get information about the layout of the file.
I would first store this in a more accessabel format
layout{1,1} = 'mband_1_start_line';
layout{1,2} = 'PCHAR';
layout{1,3} = 12;
layout{1,4} = 6;
layout{1,5} = 12;
layout{1,6} = 15;
Then you loop over the layout
wordsize = 2; %bytes / word
fid = fread(filename,'r','l')
camdat=struct;
for ct = 1:size(layout,1)
fseek(fid,-1,layout{1,3}/wordsize) %go to byte position
datsize=layout{1,5}-layout{1,3}+1; %number of words
data=fread(fid,datsize,'*uint16') %get words
bits=bitget(data(1),[1:16]); %convert to bits
for ct = 2:datasize
bits=[bits,bitget(data(ct),[1:16])];
end
bits = bits(layout{1,4}:(datasize-1)*16+layout{1,6};%get bits
data = sum(bits.*uint16(2).^uint16([0:(length(bits)-1)])) %convert back
camdat.(layout{1,1})=data; %store
end
fclose(fid)
There will be problems with values that are longer than 16 bits ofcourse.
If the wordsize is different, you can change it to 4 for 32 bit, or 8 for 64 bit, but then you have to also change that in the loop.
So I've been using your help to figure a way to do what I wanted.
The idea is to go to the bytes of the "first_word", take the bits between the first and last word (and low_bit and high_bit), turn them into decimals. With your code I've done the following that gives results but not the one I was waiting for (in the .csv) (attached file).
First I'm not sure I'm handling well the case where the last_word is not the same as the first_word.
Then I'm not sure that my fseek() sends me at the correct bytes of the file...
%% Name of the files
%% Open and read the .cfg file
%% Open and read the DAI file
...So here I've got my .cfg opened and store in layout{i,j}
wordsize = 2; %bytes / word
fid = fopen(dai_file,'r','l');
camdat=struct;
for ct = 1:length(layout)
first_word = layout{ct,3};
last_word = layout{ct,5};
low_bit = layout{ct,4};
high_bit = layout{ct,6};
fseek(fid,first_word*wordsize,-1); %go to bytes
datasize=last_word-first_word+1; %number of words
data=fread(fid,datasize,'*uint16'); %get words
bits=bitget(data(1),[1:16]); %convert to bits
if length(data) > 1 % case of 2 words
bits=[bits,bitget(data(2),1:16)];
high_bit = high_bit+16;
end
bits = bits(low_bit+1:high_bit+1);%get bits
data = sum(bits.*uint16(2).^uint16([0:length(bits)-1])); %convert back
camdat.(layout{ct,1})=data; %store
end
camdat
fclose(fid);
So if you have ideas of where I'm wrong, I'll be very grateful !!!!

How to import a sequence of Excel Files in matlab as a column vectors or as a cell array?

I want to import a sequence of excel files with a large amount of data in them. The problem that I have is I want to process the data in each file at a time and store the output from this into a variable, but each time I try to process a different file the variable gets overwritten in the variable workspace. Is there anyway I could store these files and process each file at a time?
numFiles = 1;
range = 'A2:Q21';
sheet = 1;
myData = cell(1,numFiles); % Importing data from Excel
for fileNum = 1:numFiles
fileName = sprintf('myfile%02d.xlsx',fileNum);
myData{fileNum} = importfile3(fileName,sheet,range);
end
data = cell2mat(myData);
The actual data import is performed by importfile3 which is, for the most part, a wrapper for the xlsread function that returns a matrix corresponding to the specified range of excel data.
function data = importfile3(workbookFile, sheetName, range)
% If no sheet is specified, read first sheet
if nargin == 1 || isempty(sheetName)
sheetName = 1;
end
% If no range is specified, read all data
if nargin <= 2 || isempty(range)
range = '';
end
%% Import the data
[~, ~, raw] = xlsread(workbookFile, sheetName, range);
%% Replace non-numeric cells with 0.0
R = cellfun(#(x) ~isnumeric(x) || isnan(x),raw); % Find non-numeric cells
raw(R) = {0.0}; % Replace non-numeric cells
%% Create output variable
data = cell2mat(raw);
The issue that you are running in to is a result of cell2mat concatenating all of the data in your cells in to one large 2-dimensional matrix. If you were to import two excel files with 20 rows and 17 columns, each, this would result in a 2-dimensional matrix of size [20 x 34]. The doc for cell2mat has a nice visual describing this.
I see that your importfile3 function returns a matrix, and based on your use of cell2mat in your final line of code, it looks like you would like to have your final result be in the form of a matrix. So I think the easiest way to go about this is to just bypass the intermediate myData cell array.
In the example code below, the resulting data is a 3-dimensional matrix. The 1st dimension indicates row number, 2nd dimension is column number, and 3rd dimension is file number. Cell arrays are very useful for "jagged" data, but based on the code you provided, each excel data set that you import will have the same number of rows and columns.
numFiles = 2;
range = 'A2:Q21';
sheet = 1;
% Number of rows and cols known before data import
numRows = 20;
numCols = 17;
data = zeros(numRows,numCols,numFiles);
for fileNum = 1:numFiles
fileName = sprintf('myfile%02d.xlsx',fileNum);
data(:,:,fileNum) = importfile3(fileName,sheet,range);
end
Accessing this data is now very straight-forward.
data(:,:,1) returns the data imported from your first excel file.
data(:,:,2) returns the data imported from your second excel file.
etc.

Load File in GUI GUIDE to Read 2 Columns in MATLAB

I've been at this for 3 hours -- so I need help.
I have a button on MATLAB's GUI GUIDE to load a text file to store 2
columns of data as x and y.
So x = [12, 12, 23];
textfile A is:
12 23
12 32
23 32
The code that is in the GUI GUIDE is under the pushbutton load_file as follows:
filename = uigetfile('*.txt')
loaddata = fullfile(pathname,filename)
load(loaddata)
A = filename(:,1)
B = filename(:,2)
handles.input1 = A;
handles.input2 = B;
axes(handles.axes1)
plot(handles.input1,handles,imput2)
load will load a text file, but it won't assign the contents to anything unless you explicitly specify an output.
%# load xy data from file
xy = load(loaddata,'-ascii')
%# assign columns to A and B, respectively
%# (why not x,y)?
A = xy(:,1)
B = xy(:,2)
The -ascii option of load is not necessary, but guarantees that the file is loaded as text, and will help you remember later that the data is supposed to be a text file.
Firstly, you might want to post your error message to make sure I'm reporting on the right problem, but I can see one problem right off:
the lines:
A = filename(:,1)
B = filename(:,2)
are only retrieving a string naming the file, not the actual data. So first, you have to know the name of the data that is being loaded, then change the load line to:
data = load(loaddata,'-ascii')
and now:
A = data(:,1)
B = data(:,2)

matlab averages of cell array

I have the following script for importing text files into matlab which include hourly data, where I am then trying to convert them into daily averages:
clear all
pathName = ...
TopFolder = pathName;
dirListing = dir(fullfile(TopFolder,'*.txt'));%Lists the folders in the directory specified by pathName.
for i = 1:length(dirListing);
SubFolder{i} = dirListing(i,1).name;%obtain the name of each folder in
%the specified path.
end
%import data
for i=1:length(SubFolder);
rawData1{i} = importdata(fullfile(pathName,SubFolder{i}));
end
%convert into daily averages
rawData2=cell2mat(rawData1);
%create one matrix for entire data set
altered=reshape(rawData2,24,(size(rawData2,2)*365));
%convert into daily values
altered=mean(altered)';
%take the average for each day
altered=reshape(altered,365,size(rawData2,2));
%convert back into original format
My problem lies in trying to convert the data back into the same format as 'rawData1' which was a cell for each variable (where each variable is denoted by 'SubFolder'. The reason for doing this is that all but one of the variables are vectors, where the remaining variable is a matrix (8760*11).
So, an example of this would be:
clear all
cell_1 = rand(8760,1);
cell_2 = rand(8760,1);
cell_3 = rand(8760,1);
cell_4 = rand(8760,1);
cell_5 = rand(8760,1);
cell_6 = rand(8760,11);
cell_7 = rand(8760,1);
cell_8 = rand(8760,1);
cell_9 = rand(8760,1);
data = {cell_1,cell_2,cell_3,cell_4,cell_5,cell_6,cell_7,cell_8,cell_9};
Where I need to convert each cell in 'data' from hourly values into daily averages (i.e. 365 rows).
Any advice would be much appreciated.
I think this does what you want.
data = cellfun(#(x) reshape(mean(reshape(x,24,[]))',365,[]),data,'uniformoutput',false);
However that is kind of confusing so I will explain a little.
This part mean(reshape(x,24,[]))' inside of the cellfun will reshape each cell in data into a 24 by 365, compute the mean, then turn it back into a single column. This works fine when the original data only has 1 column ... but for cell_6 with 11 columns it puts all the data end to end. So I added an addition reshape(...) wrapper around the mean(...) part to put it back into the original 11 columns ... or more precises N columns that are 365 rows in length.
Note: This is going to give you errors if you ever have data sets dimensions are not 8760 by X.

Problem with loop MATLAB

no time scores
1 10 123
2 11 22
3 12 22
4 50 55
5 60 22
6 70 66
. . .
. . .
n n n
Above a the content of my txt file (thousand of lines).
1st column - number of samples
2nd column - time (from beginning to end ->accumulated)
3rd column - scores
I wanted to create a new file which will be the total of every three sample of the scores divided by the time difference of the same sample.
e.g. (123+22+22)/ (12-10) = 167/2 = 83.5
(55+22+66)/(70-50) = 143/20 = 7.15
new txt file
83.5
7.15
.
.
.
n
so far I have this code:
fid=fopen('data.txt')
data = textscan(fid,'%*d %d %d')
time = (data{1})
score= (data{2})
for sample=1:length(score)
..... // I'm stucked here ..
end
....
If you are feeling adventurous, here's a vectorized one-line solution using ACCUMARRAY (assuming you already read the file in a matrix variable data like the others have shown):
NUM = 3;
result = accumarray(reshape(repmat(1:size(data,1)/NUM,NUM,1),[],1),data(:,3)) ...
./ (data(NUM:NUM:end,2)-data(1:NUM:end,2))
Note that here the number of samples NUM=3 is a parameter and can be substituted by any other value.
Also, reading your comment above, if the number of samples is not a multiple of this number (3), then simply discard the remaining samples by doing this beforehand:
data = data(1:fix(size(data,1)/NUM)*NUM,:);
Im sorry, here's a much simpler one :P
result = sum(reshape(data(:,3), NUM, []))' ./ (data(NUM:NUM:end,2)-data(1:NUM:end,2));
%# Easier to load with importdata
data = importdata('data.txt',' ',1);
%# Get the number of rows
n = size(data,1);
%# Column IDs
time = 2;score = 3;
%# The interval size (3 in your example)
interval = 3;
%# Pre-allocate space
new_data = zeros(numel(interval:interval:n),1);
%# For each new element in the new data
index = 1;
%# This will ignore elements past the closest (floor) multiple of 3 as requested
for i = interval:interval:n
%# First and last elements in a batch
a = i-interval+1;
b = i;
%# Compute the new data
new_data(index) = sum( data(a:b,score) )/(data(b,time)-data(a,time));
%# Increment
index = index+1;
end
For what it's worth, here is how you would go about to do that in Python. It is probably adaptable to Matlab.
import numpy
no, time, scores = numpy.loadtxt('data', skiprows=1).T
# here I assume that your n is a multiple of 3! otherwise you have to adjust
sums = scores[::3]+scores[1::3]+scores[2::3]
dt = time[2::3]-time[::3]
result = sums/dt
I suggest you use the importdata() function to get your data into your variable called data. Something like this:
data = importdata('data.txt',' ', 1)
replace ' ' by the delimiter your file uses, the 1 specifies that Matlab should ignore 1 header line. Then, to compute your results, try this statement:
(data(1:3:end,3)+data(2:3:end,3)+data(3:3:end,3))./(data(3:3:end,2)-data(1:3:end,2))
This worked on your sample data, should work on the real data you have. If you figure it out yourself you'll learn some useful Matlab.
Then use save() to write the results back to a file.
PS If you find yourself writing loops in Matlab you are probably doing something wrong.