Векторизация кода Matlab для более быстрого выполнения

Мой код работает следующим образом:

1. Во-первых, он получает несколько изображений из обучающей выборки.

2. После загрузки этих изображений мы находим нормализованные лица, среднее лицо и выполняем несколько расчетов.

3.Далее мы спрашиваем имя изображения, которое мы хотим распознать

4. Затем мы проецируем входное изображение в собственное пространство и, основываясь на отличии от собственных граней, принимаем решение.

5. В зависимости от вектора собственного веса для каждого входного изображения мы делаем кластеры с помощью команды kmeans.

Исходный код, который я пробовал:

clear all
close all
clc
% number of images on your training set.
M=1200;

%Chosen std and mean. 
%It can be any number that it is close to the std and mean of most of the images.
um=60;
ustd=32;

%read and show images(bmp);
S=[];   %img matrix

for i=1:M
    str=strcat(int2str(i),'.jpg');   %concatenates two strings that form the name of the image
    eval('img=imread(str);');


       [irow icol d]=size(img); % get the number of rows (N1) and columns (N2)
       temp=reshape(permute(img,[2,1,3]),[irow*icol,d]);     %creates a (N1*N2)x1 matrix
    S=[S temp];         %X is a N1*N2xM matrix after finishing the sequence
                        %this is our S
end


%Here we change the mean and std of all images. We normalize all images.
%This is done to reduce the error due to lighting conditions.
for i=1:size(S,2)
    temp=double(S(:,i));
    m=mean(temp);
    st=std(temp);
    S(:,i)=(temp-m)*ustd/st+um;
end

%show normalized images

for i=1:M
    str=strcat(int2str(i),'.jpg');
    img=reshape(S(:,i),icol,irow);
    img=img';

end


%mean image;
m=mean(S,2);   %obtains the mean of each row instead of each column
tmimg=uint8(m);   %converts to unsigned 8-bit integer. Values range from 0 to 255
img=reshape(tmimg,icol,irow);    %takes the N1*N2x1 vector and creates a N2xN1 matrix
img=img';       %creates a N1xN2 matrix by transposing the image.

% Change image for manipulation
dbx=[];   % A matrix
for i=1:M
    temp=double(S(:,i));
    dbx=[dbx temp];
end

%Covariance matrix C=A'A, L=AA'
A=dbx';
L=A*A';
% vv are the eigenvector for L
% dd are the eigenvalue for both L=dbx'*dbx and C=dbx*dbx';
[vv dd]=eig(L);
% Sort and eliminate those whose eigenvalue is zero
v=[];
d=[];
for i=1:size(vv,2)
    if(dd(i,i)>1e-4)
        v=[v vv(:,i)];
        d=[d dd(i,i)];
    end
 end

 %sort,  will return an ascending sequence
 [B index]=sort(d);
 ind=zeros(size(index));
 dtemp=zeros(size(index));
 vtemp=zeros(size(v));
 len=length(index);
 for i=1:len
    dtemp(i)=B(len+1-i);
    ind(i)=len+1-index(i);
    vtemp(:,ind(i))=v(:,i);
 end
 d=dtemp;
 v=vtemp;


%Normalization of eigenvectors
 for i=1:size(v,2)       %access each column
   kk=v(:,i);
   temp=sqrt(sum(kk.^2));
   v(:,i)=v(:,i)./temp;
end

%Eigenvectors of C matrix
u=[];
for i=1:size(v,2)
    temp=sqrt(d(i));
    u=[u (dbx*v(:,i))./temp];
end

%Normalization of eigenvectors
for i=1:size(u,2)
   kk=u(:,i);
   temp=sqrt(sum(kk.^2));
    u(:,i)=u(:,i)./temp;
end


% show eigenfaces;

for i=1:size(u,2)
    img=reshape(u(:,i),icol,irow);
    img=img';
    img=histeq(img,255);

end


% Find the weight of each face in the training set.
omega = [];
for h=1:size(dbx,2)
    WW=[];    
    for i=1:size(u,2)
        t = u(:,i)';    
        WeightOfImage = dot(t,dbx(:,h)');
        WW = [WW; WeightOfImage];
    end
    omega = [omega WW];
end


% Acquire new image
% Note: the input image must have a bmp or jpg extension. 
%       It should have the same size as the ones in your training set. 
%       It should be placed on your desktop
ed_min=[];

srcFiles = dir('G:\newdatabase\*.jpg');  % the folder in which ur images exists
for b = 1 : length(srcFiles)
    filename = strcat('G:\newdatabase\',srcFiles(b).name);
    Imgdata = imread(filename);

        InputImage=Imgdata;

InImage=reshape(permute((double(InputImage)),[2,1,3]),[irow*icol,1]);
temp=InImage;
me=mean(temp);
st=std(temp);
temp=(temp-me)*ustd/st+um;
NormImage = temp;
Difference = temp-m;

p = [];
aa=size(u,2);
for i = 1:aa
    pare = dot(NormImage,u(:,i));
    p = [p; pare];
end


InImWeight = [];
for i=1:size(u,2)
    t = u(:,i)';
    WeightOfInputImage = dot(t,Difference');
    InImWeight = [InImWeight; WeightOfInputImage];
end
noe=numel(InImWeight);


% Find Euclidean distance
e=[];
for i=1:size(omega,2)
    q = omega(:,i);
    DiffWeight = InImWeight-q;
    mag = norm(DiffWeight);
    e = [e mag];

end

ed_min=[ed_min MinimumValue];

theta=6.0e+03;
%disp(e)

z(b,:)=InImWeight;

end


IDX = kmeans(z,5);
clustercount=accumarray(IDX, ones(size(IDX)));

disp(clustercount);

Время выполнения для 100 изображений: Истекшее время составляет 103,947573 секунды.

ВОПРОСЫ:

1. Он работает нормально для M = 50 (т.е. тренировочный набор содержит 50 изображений), но не для M = 1200 (т. е. тренировочный набор содержит 1200 изображений). Он не показывает никаких ошибок. Нет вывода. Я ждал 10 минут. до сих пор нет выхода. В чем проблема? Где я ошибся?


person prashanth    schedule 31.05.2014    source источник
comment
Можете быть более конкретными? Что вы подразумеваете под не работает нормально? Какие ошибки вы получаете? Чтобы ответить на ваш второй вопрос, вы можете сохранить переменную S в файл с помощью команды save. Таким образом, все, что вам нужно сделать, это загрузить его с помощью load перед тем, как начать анализ.   -  person rayryeng    schedule 31.05.2014
comment
@rayryeng Это не показывает никаких ошибок. Нет вывода. Я ждал 10 минут, но вывода нет. Я думаю, что это бесконечный цикл. В чем проблема? Где я ошибся?   -  person prashanth    schedule 31.05.2014
comment
Это не ошибка. Это просто означает, что ваш код слишком долго вычисляется. Нужно ли нажимать Ctrl+C/Command+C, чтобы выйти из кода?   -  person rayryeng    schedule 31.05.2014
comment
Да, я использую Ctrl+C для остановки. Как можно ускорить выполнение?   -  person prashanth    schedule 31.05.2014
comment
Вы не можете ускорить первый цикл for, так как вам нужно последовательно читать все изображения по одному. Вы можете определенно ускорить второй цикл for. Замените свой цикл for на этот: tempS = double(S); meanS = mean(S,1); stdS = std(S,0,1); S = (tempS - meanS) ./ stdS; Это векторизует этот цикл, так что вы стандартно нормализуете свои строки S, а не выполняете цикл по каждому столбцу по одному. Вы можете применить тот же принцип в других областях вашего кода.   -  person rayryeng    schedule 31.05.2014
comment
@rayryeng У меня всего 2989 изображений в моей базе данных. Поэтому мне нужно использовать 40% от общего количества изображений, то есть 1200 изображений в тренировочном наборе. Есть ли какое-нибудь решение для этого?   -  person prashanth    schedule 31.05.2014
comment
Как я уже сказал, вам нужно просмотреть области вашего кода, которые нуждаются в векторизации. Я сделаю ответ, который изменит области вашего кода, которые определенно могут быть векторизованы.   -  person rayryeng    schedule 31.05.2014
comment
@rayryeng Я жду твоего ответа.   -  person prashanth    schedule 01.06.2014
comment
Извини за это. Я забыл вернуться во время сбоя StackOverflow. Просмотр этого кода.... это не стоит моего времени и усилий. слишком нужно изменить. Что я оставлю вам, так это просмотреть код, как это сделал я, и изменить его, используя те же принципы, которые я упомянул ранее. Удачи.   -  person rayryeng    schedule 01.06.2014
comment
@rayryeng tempS = двойной (S); среднее S = среднее (S, 1); стандартное S = стандартное (S, 0, 1); S = (tempS - среднее S)./ stdS; Я попробовал этот код, что вы сказали? Но я получаю сообщение об ошибке. Ошибка, которую я получил: y = sqrt (var (varargin {:}));   -  person prashanth    schedule 02.06.2014
comment
Эта ошибка не имеет ничего общего с моим кодом. Пишет, что ошибка в функции sqrt. Я не вызывал эту функцию в коде, который написал.   -  person rayryeng    schedule 02.06.2014


Ответы (1)


Чтобы ответить на ваш второй вопрос, вы можете просто «сохранить» любую сгенерированную переменную в виде файла .mat в своем рабочем каталоге (текущая папка), к которому можно будет получить доступ позже. Итак, в вашем коде, если «обучающие собственные лица» задаются переменной «u», вы можете использовать следующее:

save('eigenface.mat','u')

Это создает файл .mat с именем eigenface.mat, который содержит переменную 'u', собственные грани. Обратите внимание, что эта переменная сохраняется в вашей текущей папке.

В более позднем случае, когда вы пробуете свои тестовые данные, вы можете просто «загрузить» эту переменную:

load('eigenface.mat')

Это автоматически загружает 'u' в вашу рабочую область. Вы также можете сохранить дополнительные переменные в том же файле .mat, если это необходимо.

save('eigenface.mat','u','v'...)

Ответ на первый вопрос заключается в том, что код просто еще не запущен. Векторизация кода (вместо использования цикла for), как это было предложено в разделе комментариев выше, может значительно повысить скорость.

[ИЗМЕНИТЬ]

Так как изображения не очень большие, первый цикл for существенно не замедляет код. Вы можете улучшить производительность остального кода, векторизовав код. Векторизованные операции выполняются быстрее, чем циклы for. Эта ссылка может быть полезна для понимания векторизации:

http://www.mathworks.com/help/matlab/matlab_prog/vectorization.html

Например, второй цикл for можно заменить следующей векторизованной формой, как это предлагается в комментариях.

tempS = double(S); 
meanS = mean(S,1); 
stdS = std(S,0,1); 
S = (tempS - meanS) ./ stdS;

Используйте функции таймера MATLAB tic и toc, чтобы узнать, сколько времени требуется для выполнения первого цикла for. Добавьте tic перед циклом for и toc после него. Если время, необходимое для 50 изображений, составляет около 104 секунд, то оно будет значительно больше для 1200 изображений.

person Adarsh Chavakula    schedule 02.06.2014
comment
Спасибо за ваш ответ. Мне нужен ответ на 1-й вопрос. Пожалуйста, помогите мне. - person prashanth; 03.06.2014
comment
Каковы типичные размеры ваших изображений? Если они очень большие, то самому вашему imread потребуется много времени, чтобы прочитать столько больших изображений... - person Adarsh Chavakula; 03.06.2014
comment
@ Адарш Чавакула Размер файла изображения 946 байт. Высота и ширина изображения 50x50 пикселей. - person prashanth; 03.06.2014
comment
Кто-нибудь хорошо знает Matlab, пожалуйста, помогите мне. Поскольку я новичок в Matlab, я не знаю, как это сделать. - person prashanth; 03.06.2014