%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % This script runs the clean versions of the movie analysis functions. % Input and output are described for each function separately for ease of use. % Functions can be run individually from separate cells for parameter tuning/problem-solving %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%% Instructions/Notes %%%%%%%%%% % 1) Make sure that all movie files to consider are backed up separately, as most of the functions overwrite to save space. % 2) Make sure that all files (the functions references here, as well as the movies) are in the same folder. % 3) Run the functions below. The organization is currently such that one task (e.g. cropping) is % performed for all movies (can be set to specific movies by overriding defaults), then the next task is started. %%%%%%%%%% WARNING %%%%%%%%%% % MANY OF THE FUNCTIONS (SUCH AS CROPPING) OVERWRITE THE ORIGINAL MOVIE. % THE SCRIPT BELOW IS SET BY DEFAULT TO LOOK FOR ALL MOVIE FILES IN THE PRESCRIBED FOLDER. % PLEASE PUT ORIGINAL MOVIES IN A SEPARATE FOLDER. %% %%%%%%%%%% Cropping By Time %%%%%%%%%% %%% INPUT %%% % movName % Full movie name or {'All'} % numSecsToKeep % Number of seconds at the end of the movie to keep (the rest gets deleted) %%% OUTPUT %%% % Movie is overwritten with cropped movie. % Function leaves last few seconds of the movie, the rest gets removed %%% INPUT %%% movieNames = {'All'}; % specific example: {'MovieName.avi'}; numSecondsToLeave = 4; if isequal(movieNames{1},'All') movieNames = {}; MovieFilesInOriginalFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInOriginalFolder' movieNames = [movieNames movfile.name]; %#ok<*AGROW> end end % Run Cropping By Time Function for movNameCell = movieNames movName = movNameCell{1}; RemoveBeginningFramesByTimeFunction(movName,numSecondsToLeave); end %% %%%%%%%%%% Cropping By Frame %%%%%%%%%% %%% INPUT %%% % movName % Full movie name or {'All'} % removeCornersFlag % 'y' = remove (black) corners from image (these may arise in zoomed out imaging) % removeEdgesFlag % 'y' = remove (black) pixels from image connected to edge (these may arise in zoomed out imaging) %%% OUTPUT %%% % Movie is overwritten with cropped movie. %%% INPUT %%% movieNames = {'All'}; % {'MovieName.avi'}; removeCornersFlag = 'y'; removeEdgesFlag = 'y'; if isequal(movieNames{1},'All') movieNames = {}; MovieFilesInOriginalFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInOriginalFolder' movieNames = [movieNames movfile.name]; end end % Run Cropping Function for movNameCell = movieNames movName = movNameCell{1}; RemoveFramesFunction(movName,removeCornersFlag,removeEdgesFlag); close end %% %%%%%%%%%% Automatic Tracking %%%%%%%%%% %%% INPUT %%% % MovieNamesOriginals % list of full names of movie files to consider. If "All" is selected, it will run for all % movie files in the folder % EXAMPLE: {'movie1,avi','movie2.avi','movie3.avi'} % EXAMPLE: {'All'} % methodFlag % 1 = new method (constrained region based), 2 = old method (global distance based) % NOTE: Most function inputs are defaults. See function help for detailed explanation of all inputs. %%% OUTPUT %%% % Leg Endpoints Array (.mat file) % pixels (i,j) for each frame representing leg endpoints % Flags Array (.mat file) % vector of integer flags (one for each frame) which indicate "high confidence", "lower confidence", and % "human intervention required" % Saves (not output of function): vector of frame flags, array of leg endpoints, matrix of centroid coordinates, % matrix of head direction coordinates %%% INPUT %%% movieNames = {'All'}; % {'MovieName.avi'}; methodFlag = 1; % 1 = primary method, 2 = alternate method (see code for more details) removeCornersFlag = 'y'; % 'y' means ignore corners of frame d = 'default'; % default is accepted into almost all function arguments (except first two) thresholdingFactorForCentroid = d; % IF THERE IS AN ERROR, VIDEO IS PROBABLY TOO DARK! Set this parameter low (e.g. 0.3) and try again for that movie. pixelAcceptanceModifierThresholding = d; smallComponentSizeForCentroid = d; minDistanceThresholdFactor = d; thresholdingFactorForTracking = d; lowConfidenceQuantile = d; lowConfidenceCutoffDistance = d; targetNumLegs = d; showMovieFlag = d; moviePauseTime = 0.1; %%%%%%%%%%%%% % Find All Original Movies To Consider if isequal(movieNames{1},'All') movieNames = {}; MovieFilesInOriginalFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInOriginalFolder' movieNames = [movieNames movfile.name]; end end % Run Automatic Tracking for movNameCell = movieNames movName = movNameCell{1}; disp([movName,': AUTOMATIC TRACKING: STARTED']) AutomaticTrackingFunction(movName,methodFlag,... thresholdingFactorForCentroid, pixelAcceptanceModifierThresholding, smallComponentSizeForCentroid,... minDistanceThresholdFactor, thresholdingFactorForTracking, lowConfidenceQuantile,lowConfidenceCutoffDistance,targetNumLegs,... 'y',moviePauseTime); close disp([movName,': AUTOMATIC TRACKING: DONE']) end %% %%%%%%%%%% Error Correction %%%%%%%%%%% %%% INPUT %%% % MovieNamesAutoTracked % list of full names of movie files to consider. If "All" is selected, it will run for all % movie files in the folder % EXAMPLE: {'movie1,avi','movie2.avi','movie3.avi'} % EXAMPLE: {'All'} % finalMoviePauseTime % pause time between frames for final movie (showing ordered legs tracked after user % correction). Default is .03. %%% OUTPUT %%% % Leg Endpoints Array (.mat file) % pixels (i,j) for each frame representing leg endpoints % NOTE: the array is returned ordered by (front left, middle left, bottom left, front right, middle right, botton right) % if all frame flags are 10 (all frames accepted or fixed by user). Otherwise, it gives unordered ones. % frameFlags % these flags overwrite the previous ones in the Automatically Tracked Movies folder. A % frame flag of 10 means the frame was accepted by user, while a frame flag of -10 means the % frame was rejected by user. 0,1,2 correspond to confidence levels in auto tracking % (frames not yet checked by user). % NOTE: % Movie (.avi file) % final movie with leg endpoint positions corrected by humans. This is currently not explicitly % returned by the function. The movie gets saved and is only placed in the % Final Tracked Videos folder if all frame flags are 10 (completely corrected by hand). % The saved movie (when all frame flags at 10) includes the actual tracked leg positions, with % legs color-coded % Saves (not output of function): movie with corrected leg tracking, vector of frame flags, array of leg endpoints (sorted % (front left, middle left, bottom left, front right, middle right, bottom right) if % all frame flags = 10, otherwise overwriting old ones if function is % left prematurely). An entry of (-1,-1) means the leg is missing. Note that a FRONT leg is % presumed missing if there are only 5 target legs. % NOTE: tight_subplot is a user-contributed functions from Matlab Central %%% INPUT %%% movieNames = {'All'}; d = 'default'; overWriteFlag = d; targetNumLegs = d; finalMoviePauseTime = 0.0001; %%%%%%%%%%%%% % Find All Original Movies To Consider if isequal(movieNames{1},'All') movieNames = {}; MovieFilesInOriginalFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInOriginalFolder' movieNames = [movieNames movfile.name]; end end % Run Error Checking for movNameCell = movieNames movName = movNameCell{1}; disp([movName,': ERROR CORRECTION: STARTED']) movName = movNameCell{1}; % cell to string ErrorCorrectionFunction(movName,overWriteFlag,targetNumLegs,finalMoviePauseTime); disp([movName,': ERROR CORRECTION: DONE']) end %% %%%%%%%%%% Motion Detection %%%%%%%%%% %%% INPUT %%% % MovieNamesFinal % list of full names of movie files to consider. If "All" is selected, it will run for all % movie files in the folder % EXAMPLE: {'movie1,avi','movie2.avi','movie3.avi'} % EXAMPLE: {'All'} % distanceThreshold % threshold between difference in leg position between subsequent frames that determines whether % a leg is in motion. The distance counted will be parallel to the body axis (so pixel movements % up and down the leg due to prior thresholding effects/user error will be ignored). %%% OUTPUT %%% % Leg Motion Array (.mat file) % Array which indicates which legs are "moving" and which are "stationary" % Note the ordering: (FL, ML, BL, FR, MR, BR) and that a missing leg has coordinate (-1,-1) % in the original legEndpointsStore array. % Movie with legs "about to move" marked %%% INPUT %%% MovieNamesFinal = {'All'}; d = 'default'; distanceThreshold = 8; %%%%%%%%%%%%% if isequal(MovieNamesFinal{1},'All') MovieNamesFinal = {}; MovieFilesInFinalMoviesFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInFinalMoviesFolder' MovieNamesFinal = [MovieNamesFinal, movfile.name]; end end % Run Motion Detection for movNameCell = MovieNamesFinal movName = movNameCell{1}; disp([movName,': MOTION DETECTION: STARTED']) movName = movNameCell{1}; [~,projectedDistMatrix] = MotionDetectionFunction(movName,distanceThreshold); hist(projectedDistMatrix,20) title(movName,'Interpreter','none') xlabel('Projected distance') ylabel('Number of times leg moved that far') % pause disp([movName,': MOTION DETECTION: DONE']) end %% %%%%%%%%%% Show Current Movie %%%%%%%%%% %%% INPUT %%% % movName % Name of movie to show % finalMoviePauseTime % pause length between frames OR "default". Default is 0.03. % MovieNamesFinalToShow % List of names of final movies to show OR {"All"}. If {"All"} is selected, it will run for each movie file in % the final tracked movie folder. %%% OUTPUT %%% % Nothing is saved. Final movie with tracked and sorted legs is shown. clear %%% INPUT %%% MovieNamesFinalToShow = {'All'}; finalMoviePauseTime = .3; %%%%%%%%%%%%% if isequal(MovieNamesFinalToShow{1},'All') MovieNamesFinalToShow = {}; MovieFilesInFinalMoviesFolder = dir([pwd,'/*.avi']); for movfile = MovieFilesInFinalMoviesFolder' MovieNamesFinalToShow = [MovieNamesFinalToShow, movfile.name]; end end % Show movie for movNameCell = MovieNamesFinalToShow movName = movNameCell{1}; disp(['Showing: ',movName]) movName = movNameCell{1}; ShowFinalMovieFunction(movName,finalMoviePauseTime); pause(.1) close end