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
Chris E.
Chris E. on 14 Aug 2013
Hello dpb,
Well as for the centroid, it changes depending on where "more" of the beam will be, it is sometimes lopsided or overpowered in one particular area. As for the "jitter" of the beam, it will move, but usually in a smaller area. It usually has some kind of movement from frame to frame, but usually is small. I think there is a way to cut the image to an area of interest if needed and I'm looking it to that. The bounding box just needs to enclose the 95% of the beam, a Gaussian distribution in 2d usually is a good mimic of how the beam looks and acts. Thank you for the thoughts I will defiantly think of implementing them to see how it goes. I did try mex and found it made things faster, as for the faster processor, I'm kind of limited to my machinery I need to use, however it will be the only thing that runs on it. Please if you have any more questions I would love to answer them. Any speed increase is going to be helpful.

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
Chris E.
Chris E. on 14 Aug 2013
Thank you for helping, this could be a possible solution and I do think it may help. I have used the simple version, i think your right in terms of robustness, however if I take a few of the max points and then try it out (so the max and then 2nd place and 3 rd place) it should be a decent and fast way of doing this. I will look into it for sure! Thanks
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.

Categories

Find more on Image Processing and Computer Vision in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!