0

hello im working on FAST method using Matlab and it's run so slow in my notebook. this is the theory of my code FAST Detector. I know my code is ineffective and not good enough especially in the array part and loop. this is my code :

EDIT : I remove the circshift() because it makes the code run 5 minutes longer. i tried using this code(using pos as @Oleg suggested) and its still running slow, it runs about 1 minute.

clc
clear all
close all
[file path]=uigetfile('*.jpg','Select Input');
im=imread([path file]);
gray=rgb2gray(im);

% function [bestpoint, sortedR] = FASTdetector2(gray)

[r c] = size(gray);

thres = std(double(gray(:)));
% thres = 50;
C = [];

for b = 19:r-19
    for k = 19:c-19
        p = gray(b,k);
        p1 = gray(b-3,k);
        p2 = gray(b-3,k+1);
        p3 = gray(b-2,k+2);
        p4 = gray(b-1,k+3);
        p5 = gray(b,k+3);
        p6 = gray(b+1,k+3);
        p7 = gray(b+2,k+2);
        p8 = gray(b+3,k+1);
        p9 = gray(b+3,k);
        p10 = gray(b+3,k-1);
        p11 = gray(b+2,k-2);
        p12 = gray(b+1,k-3);
        p13 = gray(b,k-3);
        p14 = gray(b+1,k-3);
        p15 = gray(b+2,k-2);
        p16 = gray(b+3,k-1);
        arrayK = [p1 p2 p3 p4 p5 p6 p7 p8 p9 p10 p11 p12 p13 p14 p15 p16];
        pos = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8];

        plus = p + thres;
        min = p - thres;
        count = 0;
        Ar = size(arrayK,2);

            for i = 1:Ar+8
                if arrayK(pos(i)) > plus
                   count = count + 1;
                    if count >= 9
                       C = [C; [b k]];
                       break
                    end
                else 
                   count = 0;
                   continue
                end
            end

            for i = 1:Ar+8
                if arrayK(pos(i)) < min
                   count = count + 1;
                    if count >= 9
                       C = [C; [b k]];
                       break
                    end
                else 
                   count = 0;
                   continue
                end
            end
   end
end

x = C(:,1);
y = C(:,2);
R = HarrisMeasure(x,y);
absR = abs(R);
[val, index] = sort(absR,'descend');
sortedC = C(index,:);
Nindex = size(x,1);
if Nindex < 50   
    bestpoint = sortedC(1:Nindex,:);
    sortedR = val(1:Nindex);
else
    bestpoint = sortedC(1:50,:);
    sortedR = val(1:50);
end

imshow(gray); hold on
plot(bestpoint(:,2),bestpoint(:,1),'r*')

% end

this code runs about 5 minutes for each image :( can anyone help me with alternative code for this? or maybe shorted the code of p1 - p16 part to be array?

did anyone know which parts makes the code run so slow?

thank you everyone.

mumir
  • 1
  • 4
  • Exactly, your code is inefficient since it grows `C` (something that Mlint already warned you about). Consider preallocating. Also, without knowung what you want to achieve, is hard to refactor your code. Try to explain in words. – Oleg Oct 09 '14 at 07:52
  • 1
    Please refer code on [this](http://www.edwardrosten.com/work/fast.html) webpage. – Autonomous Oct 09 '14 at 08:00
  • @OlegKomarov i just knowing that mlint exist to check the code XD is that mean my code slow because the `C` only? what i want to achieve is to make this code faster, because to be honest i dont know which part in my codes that makes it so slow to run. my expectation is in the loop and mlint said so. is there any other way to save C (coordinates)? @ParagS.Chandakkar yes, i refer to that webpage :) – mumir Oct 09 '14 at 08:09
  • You can [profile](http://www.mathworks.co.uk/help/matlab/matlab_prog/profiling-for-improving-performance.html) your code to check for bottlenecks. Try `profile viewer`. – Oleg Oct 09 '14 at 08:14
  • @ParagS.Chandakkar i download the Matlab code from that webpage, and it is machine generated, im so confuse trying to understand the code – mumir Oct 09 '14 at 08:16
  • @OlegKomarov thank you, i tried using profile viewer and it seems that circshift is the problem here, 90% of the Total time is from circshift function itself. i google it and it seems that circshift is doing some error checking and make this code very slow. now the problem is how can i change my circshift with a similar loop so my code doesnt changed and it runs faster hmm – mumir Oct 09 '14 at 08:48
  • Instead of using `circshift()` you can create an array pointing to the circshifted positions in `arrayK` and index that with `i`. So the index will be something like `pos = [1 Ar:-1:1, mod(Ar,9):-1:1]`. Then the test will be `arrayK(pos(i)) > plus` etc... – Oleg Oct 09 '14 at 09:44
  • @OlegKomarov thanks but i dont think that `pos` is right, i tried to get `pos = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8]` so i did it manually like that, without `circshift()` my code is faster but it's still slow and run about 1 minute. i'll edit my code above as the new one :) – mumir Oct 10 '14 at 08:09

2 Answers2

1

Code Cleanup

You are declaring pos in every iteration of the loops. If pos is a constant, declare it at the top of the function so that it doesn't get redefined in every loop.

I don't expect this to speed things up much, but you can also replace p1 to p16 with arrayK(1) to arrayK(16), such as...

arrayK(1) = gray(b-3,k);

instead of

p1 = gray(b-3,k);

Preallocation

It is good practice to preallocate arrays, so if the line

C = [C; [b k]];

Is taking a long time, you should preallocate C to a long array at the beginning of the function and then assign b and k to specific locations in C.

C = ones(10000,2);
idx = 0;
... 
inside the loop
...
idx = idx + 1;
C(idx,:) = [b k];
...
at the end
...
C = C(1:idx,:);
Trogdor
  • 1,346
  • 9
  • 16
  • Steffen's suggestion to vectorize the loops would also help a lot. – Trogdor Oct 10 '14 at 12:45
  • thanks for the suggestion, i appreciate it. i think the **Preallocation** part is very good, **Code Cleanup** also but its only save my 2 sec from 1 minutes :( i dont know why this code is so slow. – mumir Oct 10 '14 at 18:48
  • Unfortunately MATLAB is simply slow when it comes to some operations like `for` loops with lots of iterations. It's possible that it can't be sped up very much. Perhaps there's a way to vectorize similarly to what Steffen suggested without using `conv`. But in the end, looping lots of times just takes a while – Trogdor Oct 13 '14 at 13:46
0

You could start with vectorizing both inner for loops.

What you basically do is test if the first 9 elements in your array .

With bigger = arrayK > plus; all values bigger than plus are identified.

By using convolution, sequences can be detected:

sequences = conv(double([bigger(end-4:end),bigger,bigger(1:4)]),ones(1,9),'same');

If there is a value equal or bigger 9, then you can attach it to your result:

idx = find(sequences==9,1);
if(~isempty(idx))
    C =[C; [b,k]]; 
end

The same can be done with the second for loop...

Steffen
  • 2,381
  • 4
  • 20
  • 33
  • thank you for giving me a solution, i really appreciate it. but i tried using the code above and it runs very slow, almost like when i using circshift. the `conv` part really takes a long time. – mumir Oct 10 '14 at 18:45