Using xlswrite to save numerical data - matlab

Hi I would like to save numerical data from an operation inside a loop. Lets see my segmentation example:
clear all, clc;
a=1:35;
A = arrayfun( #(x) sprintf( '%04d', x ), a, 'UniformOutput', false );
I = cellfun( #(b) imread( ['C:Teste/' b '/c1/' b '.png'] ), A, 'UniformOutput', false );
for i = a
% Gaussian Filter
W = fspecial('gaussian',[10,10],2);
J = imfilter(I,W);
% Finding Circular objects -- Houng Transform
[centers, radii, metric] = imfindcircles(J,[5 10], 'Sensitivity',0.93,'Edge',0.27);
idx_mask = ones(size(radii));
min_dist = 2; % relative value.
for i = 2:length(radii)
cur_cent = centers(i, :);
for j = 1:i-1
other_cent = centers(j,:);
x_dist = other_cent(1) - cur_cent(1);
y_dist = other_cent(2) - cur_cent(2);
if sqrt(x_dist^2+y_dist^2) < min_dist*(radii(i) + radii(j)) && idx_mask(j) == 1
idx_mask(i) = 0;
break
end
end
end
idx_mask = logical(idx_mask);
centers_use = centers(idx_mask, :);
radii_use = radii(idx_mask, :);
metric_use = metric(idx_mask, :);
viscircles(centers_use, radii_use,'EdgeColor','b');
a=length(centers_use)
end
So the point is to save the 35 results in one column of an xls file.
I was trying to do this but only the last element of the loop is printed in the exel file...
filename = 'testdata.xlsx';
A = vertcat('Test', 'Results', num2cell(a'));
sheet = 1;
xlRange = 'F03';
xlswrite(filename,A,sheet,xlRange)
Can please anyone help me out? I know there many questions related to this one but none of them covers my issue...
I will leave here one image for testing:
Thanks a lot in advance.
John

As #excaza said, you need to expand b
a=1:35;
for i = a
b=10+a;
end
filename = 'testdata.xlsx';
A = vertcat('Example', 'Results', num2cell(b'));
sheet = 1;
xlRange = 'B1';
xlswrite(filename,A,sheet,xlRange)

Related

How can I read specific images from TID2013 dataset in MATLAB?

How can I read specific images from TID2013 dataset in MATLAB? I written the following code but it start from first to end of the list. The images are in this format: ixx.yy.z.bmp means xx is the number of image, yy is the model of the noise and z is the level of the noise. I just want to work with models 1,2 in level 4,5 but I don't know how to do it. please someone help me! By the way there are 25 reference images, 24 models of noise and 5 level of each model of noise that I wrote them vertically in info1.txt , info2.txt , info3.txt respectively.
clc; clear; close all;
% read Original images
cd 'C:\Users\Desktop'
for NO1 = 1:25
in1 = fopen('info1.txt');
xx = fgets(in1);
A = imread(strcat('C:\Users\Desktop\reference_images\',xx,'.bmp'));
A = rgb2gray(A);
end
% read distorted images
for NO1 = 1:25
in1 = fopen('info1.txt');
xx = fgets(in1);
for NO2 = 1:24
in2 = fopen('info2.txt');
yy = fgets(in2);
for NO3 = 1:5
in3 = fopen('info3.txt');
z = fgets(in3);
B = imread(strcat('C:\Users\Desktop\distorted_images\',xx,yy,z,'.bmp'));
B = rgb2gray(B);
C = imadjust(B);
% Write restored images
imwrite(C,['C:\Users\Desktop\restored_images\','i',sprintf('%02d',NO1),'_',sprintf('%02d',NO2),'_',num2str(NO3),'.bmp']);
end
end
end
The only thing you need to do is to change values of your for loops. Note that in matlab, in contrast with most other languages, for-loops are not restricted to specific step length and can be any vectors.
imageNames = textread('info1.txt', '%s');
noiseModels = textread('info2.txt', '%s');
noiseLevels = textread('info3.txt', '%s');
imageIndices = 1:25;
modelIndices = [1, 2, 7:8];
levelindices = [4 5];
sourceDir = 'C:\Users\Desktop\distorted_images\';
destDir = 'C:\Users\Desktop\restored_images\';
for ii = imageIndices
name = imageNames{ii};
for jj = modelIndices
model = noiseModels{jj};
for kk = levelindices
level = noiseLevels{kk};
sourcePath = sprintf('%s%s%s%s.bmp', sourceDir, name, model, level)
destPath = sprintf('%si%02d_%02d_%02d.bmp', destDir, ii, jj, kk)
B = imread(sourcePath);
B = rgb2gray(B);
C = imadjust(B);
imwrite(C, destPath);
end
end
end

all possible combinations of a set in Matlab

I'm trying to find all possible combinations of a set but the order of the elements are also important for my problem.
For example for the set set={A, B, C}, the possible subsets are subsets={A},{B},{C},{A,B},{A,C},{B,A},{B,C},{C,A},{C,B},{A,B,C},{A,C,B},{B,A,C},{B,C,A},{C,A,B},{C,B,A}.
Are there any Matlab function to find that?
Thanks in advance.
I couldn't bear to see all those for loops in Tommaso's answer, so here's one with no loops:
a = {'A' 'B' 'C'};
% Build an array of binary vectors which we will use to select subsets of
% the array to be permuted
nGroups = 2^numel(a) - 1;
selector = dec2bin(1:nGroups) == '1'; % hack to convert numbers to binary vectors
selectVectors = arrayfun(#(x) selector(x,:), 1:size(selector, 1), 'UniformOutput', false);
% Get the permutations of each subset of the array
permsCell = cellfun(#(s) perms(a(s)), selectVectors, 'UniformOutput', false);
% Rearrange the permutations into a one-dimensional cell array with one
% permutation in each element
rowsAsCells = #(ca) arrayfun(#(x) ca(x,:), 1:size(ca,1), 'UniformOutput', false);
permsAsRows = cellfun(rowsAsCells, permsCell, 'UniformOutput', false);
result = cat(2, permsAsRows{:});
This returns a cell array with one permutation in each element, like Tommaso's second solution.
Whether this version is preferable is a matter of taste ;-)
a = {'A' 'B' 'C'};
a_len = numel(a);
res_len = 0;
for i = 1:a_len
res_len = res_len + (factorial(a_len) / factorial(a_len - i));
end
res = cell(res_len,a_len);
res_off = 1;
for i = 1:a_len
bin = nchoosek(a,i);
for j = 1:size(bin,1)
bin_j = bin(j,:);
per = perms(bin_j);
per_hei = size(per,1);
res_ran = res_off + per_hei - 1;
res(res_off:res_ran,:) = [per repmat({''},size(per,1),a_len - i)];
res_off = res_off + per_hei;
end
end
Alternatively, if you don't want results organized into equally sized columns, but rather inserted into a single vector with variable length:
a = {'A' 'B' 'C'};
a_len = numel(a);
res_len = 0;
for i = 1:a_len
res_len = res_len + (factorial(a_len) / factorial(a_len - i));
end
res = cell(res_len,1);
res_off = 1;
for i = 1:numel(a)
bin = nchoosek(a,i);
for j = 1:size(bin,1)
bin_j = bin(j,:);
per = perms(bin_j);
for y = 1:size(per,1)
res{res_off,1} = {per{y,:}};
res_off = res_off + 1;
end
end
end

What is the fastest way of appending an element to an array?

This is a follow-up question to How to append an element to an array in MATLAB? That question addressed how to append an element to an array. Two approaches are discussed there:
A = [A elem] % for a row array
A = [A; elem] % for a column array
and
A(end+1) = elem;
The second approach has the obvious advantage of being compatible with both row and column arrays.
However, this question is: which of the two approaches is fastest? My intuition tells me that the second one is, but I'd like some evidence for or against that. Any idea?
The second approach (A(end+1) = elem) is faster
According to the benchmarks below (run with the timeit benchmarking function from File Exchange), the second approach (A(end+1) = elem) is faster and should therefore be preferred.
Interestingly, though, the performance gap between the two approaches is much narrower in older versions of MATLAB than it is in more recent versions.
R2008a
R2013a
Benchmark code
function benchmark
n = logspace(2, 5, 40);
% n = logspace(2, 4, 40);
tf = zeros(size(n));
tg = tf;
for k = 1 : numel(n)
x = rand(round(n(k)), 1);
f = #() append(x);
tf(k) = timeit(f);
g = #() addtoend(x);
tg(k) = timeit(g);
end
figure
hold on
plot(n, tf, 'bo')
plot(n, tg, 'ro')
hold off
xlabel('input size')
ylabel('time (s)')
leg = legend('y = [y, x(k)]', 'y(end + 1) = x(k)');
set(leg, 'Location', 'NorthWest');
end
% Approach 1: y = [y, x(k)];
function y = append(x)
y = [];
for k = 1 : numel(x);
y = [y, x(k)];
end
end
% Approach 2: y(end + 1) = x(k);
function y = addtoend(x)
y = [];
for k = 1 : numel(x);
y(end + 1) = x(k);
end
end
How about this?
function somescript
RStime = timeit(#RowSlow)
CStime = timeit(#ColSlow)
RFtime = timeit(#RowFast)
CFtime = timeit(#ColFast)
function RowSlow
rng(1)
A = zeros(1,2);
for i = 1:1e5
A = [A rand(1,1)];
end
end
function ColSlow
rng(1)
A = zeros(2,1);
for i = 1:1e5
A = [A; rand(1,1)];
end
end
function RowFast
rng(1)
A = zeros(1,2);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
function ColFast
rng(1)
A = zeros(2,1);
for i = 1:1e5
A(end+1) = rand(1,1);
end
end
end
For my machine, this yields the following timings:
RStime =
30.4064
CStime =
29.1075
RFtime =
0.3318
CFtime =
0.3351
The orientation of the vector does not seem to matter that much, but the second approach is about a factor 100 faster on my machine.
In addition to the fast growing method pointing out above (i.e., A(k+1)), you can also get a speed increase from increasing the array size by some multiple, so that allocations become less as the size increases.
On my laptop using R2014b, a conditional doubling of size results in about a factor of 6 speed increase:
>> SO
GATime =
0.0288
DWNTime =
0.0048
In a real application, the size of A would needed to be limited to the needed size or the unfilled results filtered out in some way.
The Code for the SO function is below. I note that I switched to cos(k) since, for some unknown reason, there is a large difference in performance between rand() and rand(1,1) on my machine. But I don't think this affects the outcome too much.
function [] = SO()
GATime = timeit(#GrowAlways)
DWNTime = timeit(#DoubleWhenNeeded)
end
function [] = DoubleWhenNeeded()
A = 0;
sizeA = 1;
for k = 1:1E5
if ((k+1) > sizeA)
A(2*sizeA) = 0;
sizeA = 2*sizeA;
end
A(k+1) = cos(k);
end
end
function [] = GrowAlways()
A = 0;
for k = 1:1E5
A(k+1) = cos(k);
end
end

randperm of multiple columns

on a previous question here Sampling the answer given for sample on the last line of code only returns 1000x1 rather than 1000x6?
%%
normIdx = strmatch('normal.', Book2);
normalSubset = fulldata(normIdx, :);
normal = randperm(size(normalSubset , 1));
p = normal(1:750)-1;
%
smurfIdx = strmatch('smurf.', Book2);
smurfSubset = fulldata(smurfIdx, :);
smurf = randperm(size(smurfSubset , 1));
a = smurf(1:250)-1;
%
normalSample = normalSubset (p, :);
smurfSample = smurfSubset (a, :);
%
sample = [normalSample ; smurfSubset]
%
sample = sample(randperm(1000)); % this line
I tried:
sample = randperm( size(sample, 1));
This outputs 28 thousand records on one line, obviously not what I want. I then tried:
rows = 1000;
columns = 6;
%# pick random columns
indY = randperm( size(sample,2) );
indY = indY(1:columns);
%# pick random rows
indX = randperm( size(sample,1) );
indX = indX(1:rows)';
%# filter data
sample = [indX ; indY];
But I couldnt concatenate the last line? This was only an attempt to try fix the 1000x6 problem, if anyone could come up with a better way "a working way".
how about
sample = sample(randperm(1000),:);

Average filter in matlab

I'm trying to compute the average of every pixel with just the left and right neighbors but at the end of my processing I get only a white image, I can't find where my error. Here's my code
imageIn = imread('Prueba.jpg');
imageIn = rgb2gray(imageIn);
imageOut = zeros(size(imageIn));
ny = size(imageIn, 1);
nx = size(imageIn, 2);
imshow(imageIn);
u = [];
v = [];
tic
for i = 1:ny
u = imageIn(i,:);
v = zeros(1, ny);
for k = 2:ny-1
v(k) = (uint32(u(k-1))+uint32(u(k))+uint32(u(k+1)))/3;
end
%Special cases first and last pixel
v(1) = (uint32(u(2))+uint32(u(1))+uint32(u(2)))/3;
v(ny) = (uint32(u(ny-1))+uint32(u(ny))+uint32(u(ny-1)))/3;
imageOut(i,:) = v;
end
toc
imshow(imageOut);
Any ideas?
Change the last line of your code to imagesc(imageOut) and you'll see that the image is not in fact white.
Your code is fine; the reason the image appears white using the imshow() function is because after applying your local average the range of pixel intensities is considerably smaller and the default scaling used by imshow() is insufficient to bring out the contrast of the image.
Read about the difference b/t imshow() and imagesc() and you'll see the confusion.
Why not just create a 2nd matrix which is a clone of the first, shift it over and then averate the two matrices?
imIn = imread('Prueba.jpg');
nx = size(d,1);
ny = size(d,2);
% Create temporary matrices padded with nan
tmp1 = [nan(ny,2), d];
tmp2 = [d, nan(ny,2)];
imOut = tmp1;
imOut(:,:,2) = tmp2;
% use nanmean so the mean is just the value of the 1 column
imOut = nanmean(imOut,3);
out = imOut(2:end-1,:);
Try to use this
imageIn = imread('Prueba.jpg');
imageIn = rgb2gray(imageIn);
imageOut = zeros(size(imageIn));
ny = size(imageIn, 1);
nx = size(imageIn, 2);
imshow(imageIn);
u = [];
v = [];
tic
for i = 1:ny
u = imageIn(i,:);
v = zeros(1, ny);
for k = 2:ny-1
v(k) = (uint32(u(k-1))+uint32(u(k))+uint32(u(k+1)))/3;
end
%Special cases first and last pixel
v(1) = (uint32(u(2))+uint32(u(1))+uint32(u(2)))/3;
v(ny) = (uint32(u(ny-1))+uint32(u(ny))+uint32(u(ny-1)))/3;
imageOut(i,:) = v;
end
toc
imshow(imageOut);