How can I make my MATLAB simulation code run more efficiently? - performance

I am creating a simulation to model a robot moving through river currents. The more code I add, the slower the simulation gets. Sometimes, it runs so slow that the buttons don't work. Does anyone know how I might speed it up?
It is possible that it might be my computer. A few times, the simulation ran flawlessly.
Code:
function CleanRiverSolutionsSimulation
%Initialize Figure
f = figure('Visible','off','Position',[250,250,1000,500],'Name','Clean River Solutions Simulation');
%Initialize variables (when changing these, don't forget to change them in
%the stop button function)
robot_position = [0 0 0];
last_robot_position = [-1 0 0];
time_data = [0];
depth_data = robot_position(3);
simulation_mode = 'paused'; %options: 'paused' 'running' 'stopped'
river_depth = 10;
water_flow_rate = 1;
%Initializes Plots
main_plot = axes('Units','pixels','Position',[50,225,500,250]);
data_plot1 = axes('Units','pixels','Position',[625,350,200,100]);
%Initializes Sliders
water_flow_slider = uicontrol('style','slider','position',[50 175 200 20],'min',0,'max',2.5,'callback',#callback_waterflow,'value',water_flow_rate);
water_flow_text = uicontrol('Style','text','String','River Water Flow','Position',[30 140 200 30]);
water_flow_text.String = sprintf('River Water Flow: %f m/s',get(water_flow_slider,'value'));
river_depth_slider = uicontrol('style','slider','position',[50 125 200 20],'min',0,'max',10,'callback',#callback_riverdepth,'value',river_depth);
river_depth_text = uicontrol('Style','text','String','River Depth','Position',[30 90 200 30]);
river_depth_text.String = sprintf('River Depth: %f m',get(river_depth_slider,'value'));
%Initializes Push Buttons
run_button = uicontrol('Style','pushbutton','String','Run','Position',[300 175 50 20],'callback',#callback_runbutton);
pause_button = uicontrol('Style','pushbutton','String','Pause','Position',[360 175 50 20],'callback',#callback_pausebutton);
stop_button = uicontrol('Style','pushbutton','String','Stop','Position',[420 175 50 20],'callback',#callback_stopbutton);
status_text = uicontrol('Style','text','String','Status','Position',[300 140 150 30]);
status_text.String = sprintf('Status: %s','Paused');
%After setup, makes figure visible
f.Visible = 'on';
%Environment Settings
riv_length = 20;
riv_width = 20;
%River flow settings
flow_dots = 4;
%Initialize Main Plot (when changing these, don't forget to change them in
%the stop button function)
plot3(main_plot,robot_position(1),robot_position(2),robot_position(3),'Marker', 'o','Color','r')
main_plot.XLim = [-riv_length/2 riv_length/2];
main_plot.YLim = [-riv_width/2 riv_width/2];
main_plot.ZLim = [-1*river_depth 1];
main_plot.XGrid = 'on';
main_plot.YGrid = 'on';
main_plot.ZGrid = 'on';
%Initialize time sequence (when changing these, don't forget to change them in
%the stop button function)
time = clock;
pausedStartTime = time(6)+60*time(5)+3600*time(4);
startTime = pausedStartTime;
pausedTime = 0;
totalPausedTime = 0;
%MAIN SIMULATION LOOP
while ishandle(f)
switch simulation_mode
case 'running'
%TODO-add forces and have the positions depend on the forces
%creates a time t to use in simulated equations
time = clock;
t = ((time(6)+60*time(5)+3600*time(4))-startTime-totalPausedTime);
%X
last_robot_position(1) = robot_position(1);
robot_position(1) = 0;
%Y
last_robot_position(2) = robot_position(2);
robot_position(2) = 0;
%Z
last_robot_position(3) = robot_position(3);
robot_position(3) = -4+2*sin(2*t); %just did a sin wave to show movement
%UPDATE MAIN PLOT
%update robot position
plot3(main_plot,robot_position(1),robot_position(2),robot_position(3),'Marker','o','Color','r')
%update robot velocity vector?
forward_vector = [robot_position(1)-last_robot_position(1),...
robot_position(2)-last_robot_position(2),...
robot_position(3)-last_robot_position(3)];
forward_unit_vector = forward_vector./norm(forward_vector);
hold(main_plot,'on')
plot3(main_plot,[robot_position(1) (robot_position(1)+forward_unit_vector(1))],...
[robot_position(2) (robot_position(2)+forward_unit_vector(2))],...
[robot_position(3) (robot_position(3)+forward_unit_vector(3))]);
%update river flow dots
for dot = 1:flow_dots
plot3(main_plot,-riv_length/2+(dot-1)*(riv_length/flow_dots)+mod((t/water_flow_rate),(riv_length/flow_dots)),10,0,'Marker','o','Color','b')
end
%update plot settings
main_plot.XLim = [-riv_length/2 riv_length/2];
main_plot.YLim = [-riv_width/2 riv_width/2];
main_plot.ZLim = [-1*river_depth 1];
main_plot.XGrid = 'on';
main_plot.YGrid = 'on';
main_plot.ZGrid = 'on';
hold(main_plot,'off')
%Update Data Plot 1 (depth)
time = clock;
time_data = [time_data ((time(6)+60*time(5)+3600*time(4))-startTime-totalPausedTime)];
depth_data = [depth_data robot_position(3)];
plot(data_plot1,time_data,depth_data)
title('Robot Depth')
data_plot1.XLim = [max(0,(((time(6)+60*time(5)+3600*time(4))-startTime-totalPausedTime)-15)),...
max(0,(((time(6)+60*time(5)+3600*time(4))-startTime-totalPausedTime)-15)+20)];
data_plot1.YLim = [-1*river_depth 1];
pause(0.1); %anything lower and the simulation won't pause
case 'paused'
pause(0.01); %need this or the sim won't start
case 'stopped'
%so far, this line is never run
end
end
%executes callback for water flow slider
function callback_waterflow(source,eventdata)
water_flow_text.String = sprintf('River Water Flow: %f m/s',get(water_flow_slider,'value'));
water_flow_rate = get(water_flow_slider,'value');
end
%executes callback for river depth slider
function callback_riverdepth(source,eventdata)
river_depth_text.String = sprintf('River Depth: %f m',get(river_depth_slider,'value'));
river_depth = get(river_depth_slider,'value');
end
%executes callback for run button
function callback_runbutton(source,eventdata)
switch simulation_mode
case 'stopped'
%Reinitialize time sequence
time = clock;
startTime = time(6)+60*time(5)+3600*time(4);
pausedTime = 0;
totalpausedTime = 0;
case 'paused'
time = clock;
currentTime = time(6)+60*time(5)+3600*time(4);
pausedTime = currentTime-pausedStartTime;
totalPausedTime = totalPausedTime + pausedTime;
pausedTime = 0;
end
simulation_mode = 'running';
status_text.String = sprintf('Status: %s','Running');
end
%executes callback for run button
function callback_pausebutton(source,eventdata)
switch simulation_mode
case 'running'
status_text.String = sprintf('Status: %s','Paused');
time = clock;
pausedStartTime = time(6)+60*time(5)+3600*time(4);
end
simulation_mode = 'paused';
end
%executes callback for run button
function callback_stopbutton(source,eventdata)
simulation_mode = 'stopped';
status_text.String = sprintf('Status: %s','Stopping');
%Reset all simulation data
robot_position = [0 0 0];
time_data = [0];
depth_data = robot_position(3);
%Reinitialize time sequence
time = clock;
pausedStartTime = time(6)+60*time(5)+3600*time(4);
startTime = pausedStartTime;
pausedTime = 0;
totalPausedTime = 0;
%Reinitialize Plots
plot3(main_plot,robot_position(1),robot_position(2),robot_position(3),'Marker','o','Color','r')
main_plot.XLim = [-riv_length/2 riv_length/2];
main_plot.YLim = [-riv_width/2 riv_width/2];
main_plot.ZLim = [-river_depth 1];
plot(data_plot1,time_data,depth_data)
status_text.String = sprintf('Status: %s','Data is reset.');
simulation_mode = 'paused';
end
end

matlab provides you tools to do this - it is called a profiler. try this
profiler on;
your_script_name;
profiler viewer;
from the output, you can tell which lines or functions cost most of your run time. I use it every time I need to speed up my matlab code.

Related

Experimenting inverting pictures with Octave

First time using Octave to experiment inverting an image. My filename is LinearAlgebraLab1.m and after I run the file with Octave I get error "error: no such file, '/home/LinearAlgebraLab1.m'"
However, before this, I was getting an error that my .jpg file couldn't be found. What should I change to have Octave run my script correctly without any errors?
%% import image
C = imread('MonaLisa2.jpg');
%% set slopes and intercepts for color transformation
redSlope = 1;
redIntercept = -80;
greenSlope = -.75;
greenIntercept = 150;
blueSlope = -.50;
blueIntercept = 200;
%%redSlope = 1;
%%redIntercept = -80;
%%greenSlope = -.75;
%%greenIntercept = 150;
%%blueSlope = -.50;
%%blueIntercept = 200; redSlope = 1;
%% store RGB channels from image separately
R = C(:,:,1);
G = C(:,:,2);
B = C(:,:,3);
C2 = C;
S=size(C);
m=S(1,1);
n=S(1,2);
%h=S(1,3);
%% change red channel
M = R;
%%M2 = redSlope*cast(M,'double') + redIntercept*ones(786,579);
M2 = redSlope*cast(M,'double') + redIntercept*ones(m,n);
C2(:,:,1) = M2;
%% change green channel
M = G;
M2 = greenSlope*cast(M,'double') + greenIntercept*ones(m,n);
C2(:,:,2) = M2;
%% change blue channel
M = B;
M2 = blueSlope*cast(M,'double') + blueIntercept*ones(m,n);
C2(:,:,3) = M2;
%% visualize new image
image(C2)
axis equal tight off
set(gca,'position',[0 0 1 1],'units','normalized')

How to avoid overlapping between title and labels in Matlab's pie chart?

I'm using the next code to plot in a pie chart the percentage of values in a matrix that are greater/smaller than 1. The thing is that when I want to put the title above the graph, it overlaps with the label of one of the groups.
I tried replacing it with text() but it didn't worked, and Documentation on pie say nothing to this. How can I avoid this overlap?
eigen = []; % Modes array
c2 = 170; % Sound speed divided by 2
%% Room dimensions
lx = 5.74;
ly = 8.1;
lz = 4.66;
i = 1; % Index for modes array
for nz = 0:50
for ny = 0:50
for nx = 0:50
aux = c2 * sqrt((nx/lx)^2+(ny/ly)^2+(nz/lz)^2);
if aux < 400 %% If value is into our range of interest
eigen(i) = aux;
i=i+1;
end
end
end
end
eigen = round(sort(eigen'),1);
eigen
% dif = eigen(2:end)-eigen(1:end-1); % Distance between modes
x = 0; %% dif >= 1
y = 0; %% dif <= 1
dif = [];
for i=2:length(eigen)
if eigen(i)-eigen(i-1) >= 1
x = x+1;
else
y = y+1;
end
end
figure
dif = [x,y];
explode = [1 1];
graf = pie(dif,explode);
hText = findobj(graf,'Type','text');
percentValues = get(hText,'String');
txt = {'Smaller than 1 Hz: ';'Greater than 1 Hz: '};
combinedtxt = strcat(txt,percentValues);
oldExtents_cell = get(hText,'Extent');
oldExtents = cell2mat(oldExtents_cell);
hText(1).String = combinedtxt(1);
hText(2).String = combinedtxt(2);
title('Distance between modes')
You can rotate the pie chart so that the figure look better. Further, you can use position to allocate your text as follows,
figure
dif = [x,y];
explode = [1 1];
graf = pie(dif,explode);
hText = findobj(graf,'Type','text');
percentValues = get(hText,'String');
txt = {'Smaller than 1 Hz: ';'Greater than 1 Hz: '};
combinedtxt = strcat(txt,percentValues);
oldExtents_cell = get(hText,'Extent');
oldExtents = cell2mat(oldExtents_cell);
hText(1).String = combinedtxt(1);
hText(2).String = combinedtxt(2);
view([90 90]) % this is to rotate the chart
textPositions_cell = get(hText,{'Position'});
textPositions = cell2mat(textPositions_cell);
textPositions(:,1) = textPositions(:,1) + 0.2; % replace 0.2 with any offset value you want
hText(1).Position = textPositions(1,:);
hText(2).Position = textPositions(2,:);
title('Distance between modes')
You can change only the text position (without rotation) by deleting view command.

value in range for big datasets

I have a problem that I can't seem to solve. I want a query to determine whether a given value lies within a predefined range, but my loop is very slow for big datasets. Is there a more efficient way?
clear all
close all
Regression(1,1) = 1.001415645694801;
Regression(1,2) = 0.043822386790753;
FF_Value(:,1) = [24.24 30.77 31.37 29.05 29.20 29.53 29.67 27.78];
FF_Value(:,2) = [24.16 30.54 31.15 29.53 29.39 29.34 29.53 28.17];
FF_Distance = FF_Value(:,2)-(Regression(1,2)+Regression(1,1)*FF_Value(:,1));
FF_Distance_Positiv = sort(FF_Distance(FF_Distance > 0));
FF_Distance_Positiv(FF_Distance_Positiv == 0) = [];
FF_Distance_Negativ = sort(FF_Distance(FF_Distance < 0),'descend');
FF_Distance_Negativ(FF_Distance_Negativ == 0) = [];
A = repmat(FF_Distance_Positiv,length(FF_Distance_Negativ),1);
B = repmat(FF_Distance_Negativ',length(FF_Distance_Positiv),1);
C = reshape(B,[length(FF_Distance_Positiv)*length(FF_Distance_Negativ),1]);
Recognition(:,1) = A;
Recognition(:,2) = C;
FF_Recognition = zeros(length(FF_Value),1);
for i = 1:length(Recognition)
for j = 1:length(FF_Value)
if (Regression(1,2)+Recognition(i,1))+Regression(1,1)*FF_Value(j,1) >= FF_Value(j,2) &&...
(Regression(1,2)+Recognition(i,2))+Regression(1,1)*FF_Value(j,1) <= FF_Value(j,2)
FF_Recognition(j,1) = 1;
end
end
end
Welcome to the world of bsxfun's replacing your world of repmats -
%------------ Original code -----------------------------------------
FF_Distance = FF_Value(:,2)-(Regression(1,2)+Regression(1,1)*FF_Value(:,1));
FF_Distance_Positiv = sort(FF_Distance(FF_Distance > 0));
FF_Distance_Positiv(FF_Distance_Positiv == 0) = [];
%// Note for Performance: If number of elements satisfying `FF_Distance_Positiv == 0`
%// is a lot, consider doing this instead -
%// `FF_Distance_Positiv = FF_Distance_Positiv(FF_Distance_Positiv~=0)`.
%// Follow this strategy for `FF_Distance_Negativ` too.
FF_Distance_Negativ = sort(FF_Distance(FF_Distance < 0),'descend');
FF_Distance_Negativ(FF_Distance_Negativ == 0) = [];
%------- Added vectorization replacing `repmats` and nested loops ------------
mult = Regression(1,1)*FF_Value(:,1);
y1 = bsxfun(#plus,Regression(1,2),FF_Distance_Positiv);
y2 = bsxfun(#plus,y1.',mult); %//'
mc1 = bsxfun(#ge,y2,FF_Value(:,2));
z1 = bsxfun(#plus,Regression(1,2),FF_Distance_Negativ);
z2 = bsxfun(#plus,z1.',mult); %//'
mc2 = bsxfun(#le,z2,FF_Value(:,2));
FF_Recognition = all([any(mc1,2) any(mc2,2)],2);

I want to correct this code for images, what change need to do..?

Currently i am recognzing a face, means i have to find a face which we have to test is in training database or not..! So, i have to decide yes or no..
Yes means find image, and no means print message that NO IMAGE IN DATABASE. I have a program, Currently this program is finding a correct image correctly, but even when there is no image, even it shows other image which not matches.. Actually it should print NO IMAGE IN DATABASE.
So, How to do..?
Here is a Test and training images data on this link.
http://www.fileconvoy.com/dfl.php?id=g6e59fe8105a6e6389994740914b7b2fc99eb3e445
My Program is in terms of different four .m files, and it is here,we have to run only first code.. and remaining 3 are functions, it is also given here..**
clear all
clc
close all
TrainDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select training database path' );
TestDatabasePath = uigetdir('D:\Program Files\MATLAB\R2006a\work', 'Select test database path');
prompt = {'Enter test image name (a number between 1 to 10):'};
dlg_title = 'Input of PCA-Based Face Recognition System';
num_lines= 1;
def = {'1'};
TestImage = inputdlg(prompt,dlg_title,num_lines,def);
TestImage = strcat(TestDatabasePath,'\',char(TestImage),'.jpg');
im = imread(TestImage);
T = CreateDatabase(TrainDatabasePath);
[m, A, Eigenfaces] = EigenfaceCore(T);
OutputName = Recognition(TestImage, m, A, Eigenfaces);
SelectedImage = strcat(TrainDatabasePath,'\',OutputName);
SelectedImage = imread(SelectedImage);
imshow(im)
title('Test Image');
figure,imshow(SelectedImage);
title('Equivalent Image');
str = strcat('Matched image is : ',OutputName);
disp(str)
function T = CreateDatabase(TrainDatabasePath)
TrainFiles = dir(TrainDatabasePath);
Train_Number = 0;
for i = 1:size(TrainFiles,1)
if
not(strcmp(TrainFiles(i).name,'.')|strcmp(TrainFiles(i).name,'..')|strcmp(TrainFiles(i).name,'Thu mbs.db'))
Train_Number = Train_Number + 1; % Number of all images in the training database
end
end
T = [];
for i = 1 : Train_Number
str = int2str(i);
str = strcat('\',str,'.jpg');
str = strcat(TrainDatabasePath,str);
img = imread(str);
img = rgb2gray(img);
[irow icol] = size(img);
temp = reshape(img',irow*icol,1); % Reshaping 2D images into 1D image vectors
T = [T temp]; % 'T' grows after each turn
end
function [m, A, Eigenfaces] = EigenfaceCore(T)
m = mean(T,2); % Computing the average face image m = (1/P)*sum(Tj's) (j = 1 : P)
Train_Number = size(T,2);
A = [];
for i = 1 : Train_Number
temp = double(T(:,i)) - m;
Ai = Ti - m
A = [A temp]; % Merging all centered images
end
L = A'*A; % L is the surrogate of covariance matrix C=A*A'.
[V D] = eig(L); % Diagonal elements of D are the eigenvalues for both L=A'*A and C=A*A'.
L_eig_vec = [];
for i = 1 : size(V,2)
if( D(i,i)>1 )
L_eig_vec = [L_eig_vec V(:,i)];
end
end
Eigenfaces = A * L_eig_vec; % A: centered image vectors
function OutputName = Recognition(TestImage, m, A, Eigenfaces)
ProjectedImages = [];
Train_Number = size(Eigenfaces,2);
for i = 1 : Train_Number
temp = Eigenfaces'*A(:,i); % Projection of centered images into facespace
ProjectedImages = [ProjectedImages temp];
end
InputImage = imread(TestImage);
temp = InputImage(:,:,1);
[irow icol] = size(temp);
InImage = reshape(temp',irow*icol,1);
Difference = double(InImage)-m; % Centered test image
ProjectedTestImage = Eigenfaces'*Difference; % Test image feature vector
Euc_dist = [];
for i = 1 : Train_Number
q = ProjectedImages(:,i);
temp = ( norm( ProjectedTestImage - q ) )^2;
Euc_dist = [Euc_dist temp];
end
[Euc_dist_min , Recognized_index] = min(Euc_dist);
OutputName = strcat(int2str(Recognized_index),'.jpg');
So, how to generate error massege when no image matches..?
At the moment, your application appears to find the most similar image (you appear to be using Euclidean distance as you measure of similarity), and return it. There doesn't seem to be any concept of whether the image "matches" or not.
Define a threshold on similarity, and then determine whether your most similar image meets that threshold. If it does, return it, otherwise display an error message.

Matlab SVM for Image Classification

I am using SVM function of Matlab to classify images that are read from a folder. What I want to do is first read 20 images from the folder, then use these to train the SVM, and then give a new image as input to decide whether this input image falls into the same category of these 20 training images or not. If it is, then the classification result should give me 1, if not, then I expect to receive -1.
Up to now, my written code is as follows:
imagefiles = dir('*.jpg');
nfiles = 20;
for i = 1:nfiles
currentfilename = imagefiles(i).name;
currentimage = imread(currentfilename);
images{i} = currentimage;
images{i} = im2double(images{i});
images{i} = rgb2gray(images{i});
images{i} = imresize(images{i},[200 200]);
images{i} = reshape(images{i}', 1, size(images{i},1)*size(images{i},2));
end
trainData = zeros(nfiles, 40000);
for ii=1:nfiles
trainData(ii,:) = images{ii};
end
class = [1 1 1 1 1 1 1 1 -1 -1 -1 -1 -1 -1 1 1 1 1 1 1];
SVMStruct = svmtrain (trainData, class);
inputImg = imread('testImg.jpg');
inputImg = im2double(inputImg);
inputImg = rgb2gray(inputImg);
inputImg = imresize(inputImg, [200 200]);
inputImg = reshape (inputImg', 1, size(inputImg,1)*size(inputImg,2));
result = svmclassify(SVMStruct, inputImg);
Since the images are read by series from the folder, so camethe cell images. Then I converted them to grayscale as shown in the code, and resized them, since those images were NOT of same size. Thus after this step, I had 20 images, all of each with size 200x200. And at last, I gave these to serve as my training dataset, with 20 rows, and 200x200 columns. I checked all of these size results, and they seemed to work fine. But right now the only problem is, no matter what kind of input image I give it to predict, it always gives me a result as 1, even for those very different images. Seems like it is not working correctly. Could someone help me check out where should be the problem here? I couldn't find any explanation from the existing sources on the internet. Thanks in advance.
Here is a function to read all images that may help you
function X = ReadImgs(Folder,ImgType)
Imgs = dir(fullfile(Folder, ImgType));
NumImgs = size(Imgs,1);
image = double(imread(fullfile(Folder, Imgs(1).name)));
X = zeros([NumImgs size(image)]);
for i=1:NumImgs,
img = double(imread(fullfile(Folder, Imgs(i).name)));
if (size(image,3) == 1)
X(i,:,:) = img;
else
X(i,:,:,:) = img;
end
end
Source: http://computervisionblog.wordpress.com/2011/04/13/matlab-read-all-images-from-a-folder-everything-starts-here/
this is should be works in MATLAB
clear all;
clc;
folder = 'gambar 1';
dirImage = dir( folder );
numData = size(dirImage,1);
M ={} ;
% read image
for i=1:numData
nama = dirImage(i).name;
if regexp(nama, '(lion|tiger)-[0-9]{1,2}.jpg')
B = cell(1,2);
if regexp(nama, 'lion-[0-9]{1,2}.jpg')
B{1,1} = double(imread([folder, '/', nama]));
B{1,2} = 1;
elseif regexp(nama, 'tiger-[0-9]{1,2}.jpg')
B{1,1} = double(imread([folder, '/', nama]));
B{1,2} = -1;
end
M = cat(1,M,B);
end
end
% convert image holder from cell to array
numDataTrain = size(M,1);
class = zeros(numDataTrain,1);
arrayImage = zeros(numDataTrain, 300 * 300);
for i=1:numDataTrain
im = M{i,1} ;
im = rgb2gray(im);
im = imresize(im, [300 300]);
im = reshape(im', 1, 300*300);
arrayImage(i,:) = im;
class(i) = M{i,2};
end
SVMStruct = svmtrain(arrayImage, class);
% test for lion
lionTest = double(imread('gambar 1/lion-test.jpg' ));
lionTest = rgb2gray(lionTest);
lionTest = imresize(lionTest, [300 300]);
lionTest = reshape(lionTest',1, 300*300);
result = svmclassify(SVMStruct, lionTest);
result
https://github.com/gunungloli666/svm-test

Resources