FLYTRACKER Usage: [x, y, orientation] = FlyTracker(filename, FrameRange, ... NBackFrames, opt1, sqrsize,... alpha, ellipse) This function takes an input filename for a movie and tracks the position of a fly from StartFrame to EndFrame. The movie can be in any format (.avi, .mpg, .mp2, etc.). The following are a list of input parameters and output variables. Input: filename: must be the complete string of the movie filename FrameRange: range of frames to examine NBackFrames: number of frames in static background, used only to find fly in first frame opt1: 'neg' or 'pos'. This multiplies the frame data by a negative sign ('neg') or not ('pos'). FindFly needs the fly to be a bright spot, so the choice of this depends on the origional image. If the original image is RGB, chances are that 'neg' needs to be selected. sqrsize: This is half the length of the sides of the square around the brightest spot to be used in the CM calculation and the orientation calculation. alpha: This is the weighting parameter for the running background. It must be close to 1 for best results. 0.9 seems like a good value for this, anything less seems to degrade SNR. But for generalities sake, it is still a user input parameter. ellipse: parameters of the elliptical area that will be tracked Output: x,y: The x and y locations of the fly in each frame orientation: A matrix containing the UHP and LHP body axis orientation angles for each frame. UHP are in the first row, LHP are in the second row. See FlyOrient and FindFly for more details.
0001 function [x, y, orientation] = FlyTracker(filename, FrameRange,... 0002 NBackFrames, opt1, sqrsize,... 0003 alpha, ellipse) 0004 0005 %FLYTRACKER 0006 % Usage: 0007 % [x, y, orientation] = FlyTracker(filename, FrameRange, ... 0008 % NBackFrames, opt1, sqrsize,... 0009 % alpha, ellipse) 0010 % 0011 % This function takes an input filename for a movie and tracks the position 0012 % of a fly from StartFrame to EndFrame. The movie can be in any format 0013 % (.avi, .mpg, .mp2, etc.). The following are a list of input parameters 0014 % and output variables. 0015 % 0016 % Input: 0017 % filename: must be the complete string of the movie filename 0018 % FrameRange: range of frames to examine 0019 % NBackFrames: number of frames in static background, used only to 0020 % find fly in first frame 0021 % opt1: 'neg' or 'pos'. This multiplies the frame data by a 0022 % negative sign ('neg') or not ('pos'). FindFly needs the 0023 % fly to be a bright spot, so the choice of this depends on 0024 % the origional image. If the original image is RGB, chances 0025 % are that 'neg' needs to be selected. 0026 % sqrsize: This is half the length of the sides of the square 0027 % around the brightest spot to be used in the CM calculation 0028 % and the orientation calculation. 0029 % alpha: This is the weighting parameter for the running 0030 % background. It must be close to 1 for best results. 0031 % 0.9 seems like a good value for this, anything less 0032 % seems to degrade SNR. But for generalities sake, it 0033 % is still a user input parameter. 0034 % ellipse: parameters of the elliptical area that will be tracked 0035 % 0036 % Output: 0037 % x,y: The x and y locations of the fly in each frame 0038 % orientation: A matrix containing the UHP and LHP body axis orientation 0039 % angles for each frame. UHP are in the first row, LHP are in 0040 % the second row. See FlyOrient and FindFly for more 0041 % details. 0042 0043 % This function uses the videoReader function to input the video file into a Matlab object. 0044 % Usage on videoReader and other functions in the videoIO toolbox can be 0045 % found in the videoIO documentation. 0046 0047 %Written by Dan Valente 8/8/07 0048 0049 %Please note: Video indexes start at frame 0 0050 StartFrame = FrameRange(1); 0051 EndFrame = FrameRange(end); 0052 NFrames = EndFrame-StartFrame+1; 0053 0054 %If NBackFrames is smaller than the number of frames we want to look at, 0055 % we'll just take a smaller background average using all the frames of 0056 % interest. 0057 if (NBackFrames >= NFrames) 0058 NBackFrames = NFrames; 0059 end 0060 0061 %initialize some variables 0062 x = []; 0063 y = []; 0064 orientUHP=[]; 0065 orientLHP=[]; 0066 0067 %load in video object using videoReader 0068 video = videoReader(filename); 0069 info = getinfo(video); 0070 width = info.width; 0071 height = info.height; 0072 0073 %just prevents error if user wants to track to end, but enters the 0074 % incorrect EndFrame (recall frame index starts at 0). 0075 if (info.numFrames == EndFrame) 0076 EndFrame = EndFrame-1; 0077 elseif (info.numFrames < EndFrame) 0078 EndFrame = info.numFrames-1; 0079 end 0080 0081 %seek to StartFrame for initial background calculation 0082 seek(video, StartFrame); 0083 0084 mask = ellipse.mask; 0085 0086 disp('Calculating background...') 0087 background = zeros(height, width); 0088 for bframe = 1:NBackFrames; 0089 img = getframe(video); 0090 current = mask.*double(img(:,:,1)); %just take first color matrix and mask out unwanted portions 0091 background = background + current/NBackFrames ; 0092 next(video); 0093 end 0094 flipper = 256*ones(height, width).*mask; 0095 if (strcmp(opt1,'neg') == 1) %make sure our fly will be a bright spot 0096 background = -background+flipper; 0097 end 0098 0099 0100 %seek to StartFrame for tracking 0101 seek(video,StartFrame); 0102 disp('Beginning tracking...') 0103 tic 0104 0105 for frame = StartFrame:EndFrame 0106 disp(num2str(frame)) 0107 img = getframe(video); 0108 img = mask.*double(img(:,:,1)); %just take first color matrix 0109 0110 %make sure our fly will be a bright spot 0111 if (strcmp(opt1,'neg') == 1) 0112 img = -img+flipper; 0113 elseif (strcmp(opt1,'pos') == 1) 0114 img = img; 0115 end 0116 0117 % Calculate square of difference image (to reduce noise) and track 0118 temp = (img-background).^2; 0119 0120 [x_raw y_raw bodyline sqr]=FindFly(temp,sqrsize); 0121 0122 0123 %Just in case of a false track due to objects in the video that are 0124 %brighter than fly and vary over time. We assume that these are 0125 %very far away from the fly. One may want to change the threshold 0126 %from 100 pixels to something smaller, if need be. Any reasonably 0127 %large number should do, and if you choose an incorrect threshold, 0128 %you can use the CleanData function to fix this. 0129 if (frame~=StartFrame) 0130 if (sqrt((x_raw-x(end))^2+(y_raw-y(end))^2) >= 100) 0131 x_raw = x(end); 0132 y_raw = y(end); 0133 end 0134 end 0135 0136 x = [x x_raw]; 0137 y = [y y_raw]; 0138 orientUHP = [orientUHP bodyline(1)]; 0139 orientLHP = [orientLHP bodyline(2)]; 0140 % % 0141 % figure(2) 0142 % imagesc(img) 0143 % colormap gray 0144 % hold on 0145 % plot(x_raw,y_raw, '.r') 0146 % % 0147 % 0148 %grab whatever the background was before the fly got there. 0149 temp = background(sqr(1):sqr(2),sqr(3):sqr(4)); 0150 %update 0151 background = alpha*background+(1-alpha)*img; 0152 %make sure we only update image outside of fly 0153 background(sqr(1):sqr(2),sqr(3):sqr(4)) = temp; 0154 0155 worked = next(video); 0156 if (worked == 0) 0157 break 0158 end 0159 end 0160 disp('Finished tracking.') 0161 disp('Have a lovely day.') 0162 toc 0163 0164 %Now we have to make sure that the y vector is based on a coordinate 0165 %system with the origin in the lower left hand corner of the square, 0166 %for plotting purposes. 0167 y = height-y; 0168 0169 orientation = [orientUHP;orientLHP]; 0170 0171 return; 0172