1

I am currently coding a program to keep track of a running fly in a small chamber, what I want is XY-coordinates of the center of the fly. For this I first filter each frame with a Gaussian filter using fspecial('gaussian',[30 30],100) and imfilter to get a white "cloud" where the fly is. I need this to reduce noise of the center of the fly. I convert the outcome into a binary image using im2bw with a certain threshold to get a white blob from the aforementioned cloud. To get the coordinates, I use regionprops that finds the centroid of the white blob. It already works fine, but it takes ages - roughly 6 hours for 30 minutes of video; the framerate is 100 fps, though.

I have figured out that the Gaussian filtering takes up most of the time - can I tweak this process somehow? I read about conv2, which is said to be faster but it does not work on binary images, does it? And converting my binary images to single or double messes them up.

I already worked on the code's performance on other levels, like adjusting the search window etc., so the filtering is what is left as far as I can assess.

Thanks in advance

Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
user3459888
  • 53
  • 1
  • 7

1 Answers1

0

It might be that the smoothing part is unnecessary, a simple thresholding of your image leads to a pretty clear identification of the fly:

f=rgb2gray(imread('frame.png'));
BW=f>30;
props=regionprops(BW, 'BoundingBox');
imshow(f)
rectangle('Position',props.BoundingBox, 'LineWidth',2, 'EdgeColor','b');

Result:

detected fly

To answer your question about fast smoothing, you could use FFT-based low-pass filtering instead of a moving gaussian to smoothen your frames much faster. Example for one frame (the mask needs only to be done once):

f=rgb2gray(imread('frame.png'));
D=30;
[x,y]=size(f);

%Generating a disc-shaped binary mask with radius D:

Mask = fspecial('disk',D)==0;
Mask = ~imresize(padarray(Mask, [floor((x/2)-D) floor((y/2)-D)], 1, 'both'), [x y]);

% (Apply this to all the frames:)

MaskedFFT=fftshift(fft2(f));.*Mask;
Filteredf=abs(ifft2(MaskedFFT));

Result:

Original (f)

original pic Filtered (Filteredf)

smoothened

Cape Code
  • 3,584
  • 3
  • 24
  • 45
  • Here's an example image: http://i.imgur.com/7YlMKpz.png And this is what double(image) does: http://i.imgur.com/7kctYTs.png – user3459888 Mar 25 '14 at 14:34
  • Your first image does not look binary to me, more like a gray scale. – Cape Code Mar 25 '14 at 14:44
  • @user3459888 What you see in your second image is the noise being highlighted by the range conversion. It is also present in your original image. Use thresholding to get rid of it (see my edits). – Cape Code Mar 25 '14 at 15:09
  • 1) Of course you're right, it's grayscale; I mixed things up in my mind...I'm relatively new to Matlab so that happens... 2) The identification of the fly is not the problem, but the noise - I also want to filter out small movements of the fly because the research is aimed at locomotion. – user3459888 Mar 26 '14 at 10:24
  • 3) I now convert the original frame to binary with im2bw using a certain threshold, "blur" that image using conv2 to get a white cloud and use im2bw again with a different threshold to get a more or less round white blob. This is approximately 30% faster than using 2xim2bw + imfilter, which is acceptable. I will experiment with the FFT-based filter and see if that's even faster. Thank you VERY much for your effort! – user3459888 Mar 26 '14 at 10:24
  • @user3459888 you're welcome. I think the advantage of `conv2` over `imfilter` is that it reshapes the input image and performs column-wise processing. Anyway, it sound like you found a way to get rid of your noise, which was probably your main issue. – Cape Code Mar 26 '14 at 10:57
  • Don't forget to take the fftshift also when you do the backtransform in ifft2 – Xander Dec 16 '22 at 17:21