MATLAB Answers

Can this function work any faster?

5 views (last 30 days)
Hello All, Well I'm making a function that takes about 0.022 seconds to complete, I need to try to make it even less time then that, just getting peoples opinions. The end result needs to run at 120 Hz, I have tried most matlab built in functions, but there too slow for what I need, I know because I've tried. This is designed to be used for an accelerator beam image, it is just a "spot" on the screen and the image coming in has about 606x1182 pixels in it. The inputs are an image and a threshold(which is usually == 0). I pretty much have striped down to bare essentials for this code, however hope there was something I missed that will make it faster. I was just hoping for peoples comments or options about any way to make this code faster(or if there is a better way):
function [clipedImg,tfr,tfc] = ImageClipper(useImg,threshold)
useImg = double(useImg); %????????????????????????
mx = max(useImg);
my = max(useImg,[],2);
sorted=sort(my(:));
dist=diff([sorted; sorted(end)-1]);
idx=find(dist);
num=[idx(1); diff(idx)];
n=max(num);
ty=sorted(idx(num==n));
v = mx > ty;
na = length(v);
b = [1 -1];
[k,zf] = filter(b, 1, v);
k(na+1:na+2-1) = zf;
P = find(k==1);
L = find(k==-1)-P;
LP = [max(L) P(L==max(L))];
tfc = [false(1,LP(1,2)-threshold) true(1,LP(1,1)+2*threshold) false(1,length(mx)-sum(LP)-threshold)];
v = my > ty;
na = length(v);
b = [1 -1];
[k,zf] = filter(b, 1, v);
k(na+1:na+2-1) = zf;
P = find(k==1);
L = find(k==-1)-P;
LP = [max(L) P(L==max(L))];
tfr = [false(1,LP(1,2)-threshold) true(1,LP(1,1)+2*threshold) false(1,length(my)-sum(LP)-threshold)];
clipedImg = useImg(tfr,tfc);
Thanks!
  11 Comments

Sign in to comment.

Accepted Answer

Sean de Wolski
Sean de Wolski on 14 Aug 2013
Edited: Sean de Wolski on 14 Aug 2013
Another husky!
You could avoid the max operation here as well:
[L posP]= max(find(k==-1)-P);
Instead:
find(k==-1,1,'last')-P
Now it only needs to find the first occurence of a -1 and not all of them allowing it to stop prematurely.
Avoid operations like the following that change the size or class of an array:
P = P(posP);
Also, to address DPB's point: do you have MATLAB Coder? If so, you could try generating code from this and then compiling it into a MEX file that might run faster.

More Answers (1)

dpb
dpb on 14 Aug 2013
Edited: dpb on 14 Aug 2013
My simple-minded solution -- undoubtedly will need some robustness added, but try adding sophistication to something as trivial as the following for a first cut...
[mx,imx]=max(image(:)); % find the max point as center
[i,j]=sub2ind(size(useImg),imx); % turn into row, column
lvl=0.05*mx; % a cutoff threshold
% left/right and upper/lower bounds enclosing that level around max
L=find(useImg(i,1:j)>lvl,1,'first');R=find(useImg(i,j:end)<lvl,1,'first')+j;
U=find(useImg(1:i,j)>lvl,1,'first');B=find(useImg(i:end,j)<lvl,1,'first')+i;
imClip=useImg(U:B,L:R); % the bounded image
image(imClip)
As my previous suggestion, I would think that even if take more sophistication the first time, after that if the beam can't be just anywhere you could limit the area over which you have to do the max to a fairly small region and thereby make it quite a lot smaller area for the search and thus be able to add more robustness over a smaller area to gain compute speed.
Then again, if the signal is pretty robust, maybe something as trivial as just doing the bounding on a strip P pixels wide centered on the max location instead of a single row/column as here would do it. Again, I'm no ImageAnalyst by any stretch...
  2 Comments
dpb
dpb on 15 Aug 2013
If the size of the beam image is relatively constant I'd think you could take the overall max, then look at an area around it of fixed size and pick a group of points within some relatively small tolerance of that value. From those you ought to be able to get a band in each direction from which you can do the bounding instead of the single line as I illustrated. Overall, however, this could be only a very small fraction of the overall image size which has to help speed.
Then, one thing you might note -- if you do use the diff() approach, it works well if you first subtract a threshold between the noise levels of the min and max and use sign() on that result. Then diff(sign(x-th)) leaves you w/ +/-2 at the zero crossings.

Sign in to comment.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!