Vectorization of MATLAB code to optimize speed - matlab

Hey fellow MATLAB users. The following code is meant to analyze motion in films. However, when I run the script on a film, it takes almost 14 hours for MATLAB to run the code. I have heard that you can optimize running speed by vectorizing your code; however, I have no idea how to go about this with the code below, since I am far from a programmer.
Can anyone help me out, or point me in the right direction?
Thanks a lot – the m.code is as follows:
%calculates correlations in sequences of film shots 22 May 2014
%t = input vector of initial frames of all shots in the film
prompt1 = 'movie file = ';
movieavi = input(prompt1,'s');
mov = VideoReader(movieavi);
nshots = length(t)-1;
for n = 1:nshots
first = t(n);
last = t(n+1)-2;
slength = last - first + 1;
tempcor = 0;
for k = 1:(slength-1)
im1 = read(mov,first+k-1); %read the image
im2 = read(mov,first+k+1);
im1 = rgb2gray(im1); %convert to grayscale
im2 = rgb2gray(im2);
tmp = corr2(im1,im2);
if(isnan(tmp) == 1)
tmp = .9999;
end
tempcor = tempcor + tmp;
end
dataout(n,3) = tempcor/(slength-1); %mean Lag 1 correlation within a shot
dataout(n,1) = uint32(first/100); %frame in hundreds. Can't export 6 digit integer
dataout(n,2) = mod(first,100); %modolus 100, to be combined with above
cycle = t(n)
end;
xlswrite('dataout.xls', dataout) %this file appears in matlab folder and must
save dataout; %the Matlab version of same

Related

How to add standrad deviation and moving average

What I want to is:
I got folder with 32 txt files and 1 excle file, each file contain some data in two columns: time, level.
I already managed to pull the data from the folder and open each file in Matlab and get the data from it. What I need to do is create plot for each data file.
each of the 32 plots should have:
Change in average over time
Standard deviation
With both of this things I am straggling can't make it work.
also I need to make another plot this time the plot should have the average over each minute from all the 32 files.
here is my code until now:
clc,clear;
myDir = 'my path';
dirInfo = dir([myDir,'*.txt']);
filenames = {dirInfo.name};
N = numel(filenames);
data=cell(N,1);
for i=1:N
fid = fopen([myDir,filenames{i}] );
data{i} = textscan(fid,'%f %f','headerlines',2);
fclose(fid);
temp1=data{i,1};
time=temp1{1};
level=temp1{2};
Average(i)=mean(level(1:find(time>60)));
AverageVec=ones(length(time),1).*Average(i);
Standard=std(level);
figure(i);
plot(time,level);
xlim([0 60]);
hold on
plot(time, AverageVec);
hold on
plot(time, Standard);
legend('Level','Average','Standard Deviation')
end
the main problam with this code is that i get only average over all the 60 sec not moving average, and the standard deviation returns nothing.
few things you need to know:
*temp1 is 1x2 cell
*time and level are 22973x1 double.
Apperently you need an alternative to movmean and movstd since they where introduced in 2016a. I combined the suggestion from #bla with two loops that correct for the edge effects.
function [movmean,movstd] = moving_ms(vec,k)
if mod(k,2)==0,k=k+1;end
L = length(vec);
movmean=conv(vec,ones(k,1)./k,'same');
% correct edges
n=(k-1)/2;
movmean(1) = mean(vec(1:n+1));
N=n;
for ct = 2:n
movmean(ct) = movmean(ct-1) + (vec(ct+n) - movmean(ct-1))/N;
N=N+1;
end
movmean(L) = mean(vec((L-n):L));
N=n;
for ct = (L-1):-1:(L-n)
movmean(ct) = movmean(ct+1) + (vec(ct-n) - movmean(ct+1))/N;
N=N+1;
end
%mov variance
movstd = nan(size(vec));
for ct = 1:n
movstd(ct) = sum((vec(1:n+ct)-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(n+ct-1);
end
for ct = n+1:(L-n)
movstd(ct) = sum((vec((ct-n):(ct+n))-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(k-1);
end
for ct = (L-n):L
movstd(ct) = sum((vec((ct-n):L)-movmean(ct)).^2);
movstd(ct) = movstd(ct)/(L-ct+n);
end
movstd=sqrt(movstd);
Someone with matlab >=2016a can compare them using:
v=rand(1,1E3);m1 = movmean(v,101);s1=movstd(v,101);
[m2,s2] = moving_ms(v,101);
x=1:1E3;figure(1);clf;
subplot(1,2,1);plot(x,m1,x,m2);
subplot(1,2,2);plot(x,s1,x,s2);
It should show a single red line since the blue line is overlapped.

Matlab: Working for-loop breaks in parfor while fitting curves

Hoping you may be able to assist me with this error. I am running some code to fit curves to ages using a cross validation regime. I iterate the curve fitting 1000 times to assess the best fit.
I define my models as:
linear_ft = fittype({'x', '1'});
monotonic_ft= fittype({'-1/x', '1'});
quadratic_ft = fittype('poly2');
I then run the following to iterate through different selections of data splitting, recording the residuals following the curve fit...
Data = randn(4,300,10,10);
Ages = randn(300,1);
for thisDim1 = 1:4
for thisDim2 = 1:10
for thisDim3 = 1:10
for nIts = 1:1000
RandomOrder = randperm(300,300);
Fit_Subs = RandomOrder(1:length(Ages)/2); % Take random subs to fit to
Test_Subs = RandomOrder(length(Ages)/2+1:300); % Take random subs to test fit to
Fit_Data = squeeze(Data(thisDim1,Fit_Subs,thisDim2,thisDim3)); % Take data to fit to
Test_Data = squeeze(Data(thisDim1,Test_Subs,thisDim2,thisDim3)); % Take data to test fit
Fit_Ages = Ages;
Fit_Ages(Fit_Subs) = []; %Take ages of Fit Subs only
Test_Ages = Ages;
Test_Ages(Test_Subs) = []; % Take ages of Test Subs only
Nsubs = (length(Ages)/2);
% Model Data using Curves
fFit_Lin = fit(Fit_Ages,Fit_Data',linear_ft);
fFit_Mon = fit(Fit_Ages,Fit_Data',monotonic_ft);
fFit_Quad = fit(Fit_Ages,Fit_Data',quadratic_ft);
% Fit Modelled Data to Test Data
tFit_Lin = fFit_Lin(Test_Ages);
tFit_Mon = fFit_Mon(Test_Ages);
tFit_Quad = fFit_Quad(Test_Ages);
% Calculate Median Residual
Lin_Med_Resid(nIts) = median(tFit_Lin - Test_Data');
Mon_Med_Resid(nIts) = median(tFit_Mon - Test_Data');
Quad_Med_Resid(nIts) = median(tFit_Quad - Test_Data');
end
end
end
end
If you run this with the fourth loop (nIts) as a for-loop it will run. If you run it as a parfor-loop it won't stating the error:
Error using fit>iFit (line 264)
The name 'lower' is not an accessible property for an instance of class
'llsqoptions'.
Error in fit (line 108) [fitobj, goodness, output, convmsg] = iFit(
xdatain, ydatain, fittypeobj, ...
Does anyone have any idea how to fix this? I would be most grateful for any advice!!
Thanks,
Ben
Try restarting MATLAB or typing clear all to see if it clears things up for you.
Your code works for me, but the parallel toolbox can be a bit finicky in my experience.

MSR Daily Activity 3D dataset matlab source code

I am searching for any matlab code that reads the skeleton text files from the dataset (MSR Daily Activity 3D). I can't figure how to understand how the files are written and what they represent ? Also, don't know how to parse them to extract the features.
this is the matlab code which read the depth sequences.
in each loop of 'for ei = 1:2',it read all the depth data to depth(a 3D matrix) from a bin file.
clear;close all;clc;
binPath = 'MSR Daily Activity 3D dataset\Depth';
for ai = 1:16
for si = 1:10
for ei = 1:2
%%%%%%%%%%%%%
%%%%%%%%%%%%%
[acsr,susr,exsr]=getsr(ai,si,ei);
%%%%%% getsr(ai,si,ei) convert ai,si,ei to double bits
%%%%%% for example, if ai=3, acsr is 03
%%%%%%%%%%%
binfile = [binPath,'\a',acsr,'_s',susr,'_e',exsr,'_depth.bin'];
if ~exist(binfile,'file');
disp('error');
continue;
end;
disp(binfile);
fileread = fopen(binfile);
if fileread<0
disp('no such file.');
return;
end
header = fread(fileread,3,'uint=>uint');
nnof = header(1); ncols = header(2); nrows = header(3);
depths = zeros(ncols, nrows, nnof);
for f = 1:nnof
frame = zeros( ncols, nrows);
for row = 1:nrows
tempRow = fread(fileread, ncols, 'uint=>uint');
tempRowID = fread(fileread, ncols, 'uint8');%%%%%
frame(:,row) = tempRow;
end
depth(:,:,f) = frame;
clear tempRow tempRowID;
end
fclose(fileread);
end
end
end
The site http://research.microsoft.com/en-us/um/people/zliu/ActionRecoRsrc/ tells you exactly how they're organised. They also provide some C++ example loaders.
"The format of the skeleton file is as follows. The first integer is the number of frames. The second integer is the number of joints which is always 20. For each frame, the first integer is the number of rows. This integer is 40 when there is exactly one skeleton being detected in this frame. It is zero when no skeleton is detected. It is 80 when two skeletons are detected (in that case which is rare, we simply use the first skeleton in our experiments). For most of the frames, the number of rows is 40. Each joint corresponds to two rows. The first row is its real world coordinates (x,y,z) and the second row is its screen coordinates plus depth (u, v, depth) where u and v are normalized to be within [0,1]. For each row, the integer at the end is supposed to be the confidence value, but it is not useful."
Hope this helps.

Dimensions issus

Finding maximum values of wave heights and wave lengths
dwcL01 though dwcL10 is arrays of <3001x2 double> with output from a numerical wave model.
Part of my script:
%% Plotting results from SWASH
% Examination of phase velocity on deep water with different number of layers
% Wave height 3 meters, wave peroid 8 sec on a depth of 30 meters
clear all; close all; clc;
T=8;
L0=1.56*T^2;
%% Loading results tabels.
load dwcL01.tbl; load dwcL02.tbl; load dwcL03.tbl; load dwcL04.tbl;
load dwcL05.tbl; load dwcL06.tbl; load dwcL07.tbl; load dwcL08.tbl;
load dwcL09.tbl; load dwcL10.tbl;
M(:,:,1) = dwcL01; M(:,:,2) = dwcL02; M(:,:,3) = dwcL03; M(:,:,4) = dwcL04;
M(:,:,5) = dwcL05; M(:,:,6) = dwcL06; M(:,:,7) = dwcL07; M(:,:,8) = dwcL08;
M(:,:,9) = dwcL09; M(:,:,10) = dwcL10;
%% Finding position of wave crest using diff and sign.
for ii=1:10
Tp(:,1,ii) = diff(sign(diff([M(1,2,ii);M(:,2,ii)]))) < 0;
Wc(:,:,ii) = M(Tp,1,ii);
L(:,ii) = diff(Wc(:,1,ii))
end
The loop
for ii=1:10
Tp(:,1,ii) = diff(sign(diff([M(1,2,ii);M(:,2,ii)]))) < 0;
Wc(:,:,ii) = M(Tp,1,ii);
L(:,ii) = diff(Wc(:,1,ii))
end
Works fine for ii = 1 Getting the following error for ii = 2
Index exceeds matrix dimensions.
Error in mkPlot (line 19)
Wc(:,:,i) = M(Tp,:,i);
Don't have the same number of wave crests for the different set ups, naturally M(Tp,1,ii) will have different dimensions. How do I work around this issue? Can it be done in a for loop? please feel free to email me or other wise ask for further information.
The problem is that Tp is a three dimensional array. I need to call the Tp(:,:,ii) corresponding to the present scenario. Together with this and defining Wc as a cell I solve my issue.
for ii = 1:10
Tp(:,1,ii) = diff(sign(diff([M(1,2,ii);M(:,2,ii)]))) < 0;
Wc{:,:,ii} = M(Tp(:,:,ii),1,ii);
L{:,ii} = diff(cell2mat(Wc(ii)));
end

Rolling window for averaging using MATLAB

I have the following code, pasted below. I would like to change it to only average the 10 most recently filtered images and not the entire group of filtered images. The line I think I need to change is: Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;, but how do I do it?
j=1;
K = 1:3600;
window = zeros(1,10);
Yout = zeros(10,column,row);
figure;
y = 0; %# Preallocate memory for output
%Load one image
for i = 1:length(K)
disp(i)
str = int2str(i);
str1 = strcat(str,'.mat');
load(str1);
D{i}(:,:) = A(:,:);
%Go through the columns and rows
for p = 1:column
for q = 1:row
if(mean2(D{i}(p,q))==0)
x = 0;
else
if(i == 1)
meanvalue = mean2(D{i}(p,q));
end
%Calculate the temporal mean value based on previous ones.
meanvalue = (meanvalue+D{i}(p,q))/2;
x = double(D{i}(p,q)/meanvalue);
end
%Filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
end
end
end
% for k = 2:10
% subplot(5,2,k)
% subimage(Yout(k)*5000, [0 100]);
% colormap jet
% end
% pause(0.01);
end
disp('Done Loading...')
The best way to do this (in my opinion) would be to use a circular-buffer to store your images. In a circular-, or ring-buffer, the oldest data element in the array is overwritten by the newest element pushed in to the array. The basics of making such a structure are described in the short Mathworks video Implementing a simple circular buffer.
For each iteration of you main loop that deals with a single image, just load a new image into the circular-buffer and then use MATLAB's built in mean function to take the average efficiently.
If you need to apply a window function to the data, then make a temporary copy of the frames multiplied by the window function and take the average of the copy at each iteration of the loop.
The line
Yout(k,p,q) = (Yout(k,p,q) + (y.^2))/2;
calculates a kind of Moving Average for each of the 10 bands over all your images.
This line calculates a moving average of meanvalue over your images:
meanvalue=(meanvalue+D{i}(p,q))/2;
For both you will want to add a buffer structure that keeps only the last 10 images.
To simplify it, you can also just keep all in memory. Here is an example for Yout:
Change this line: (Add one dimension)
Yout = zeros(3600,10,column,row);
And change this:
for q = 1:row
[...]
%filtering for 10 bands, based on the previous state
for k = 1:10
[y, ZState{k}] = filter(bCoeff{k},aCoeff{k},x,ZState{k});
Yout(i,k,p,q) = y.^2;
end
YoutAvg = zeros(10,column,row);
start = max(0, i-10+1);
for avgImg = start:i
YoutAvg(k,p,q) = (YoutAvg(k,p,q) + Yout(avgImg,k,p,q))/2;
end
end
Then to display use
subimage(Yout(k)*5000, [0 100]);
You would do sth. similar for meanvalue