%This code is written based on the Matlab's built in script, Motion-Based Multiple Object Tracking function tracks = mytrackingrefresh() myDir = uigetdir;%Get the directory of the video myFiles = dir(fullfile(myDir,'*.avi')); %gets all mp4 files in struct for N = 1:length(myFiles)%Loop through every file in the directory disp(myFiles(N).name); fname = strcat(myFiles(N).name,'.mat'); obj = setupSystemObjects(); tracks = initializeTracks(); % Create an empty array of tracks. nextId = 1; % ID of the next track disp('Total number of frames'); disp(obj.reader2.NumberOfFrames); totalframenum = obj.reader2.NumberOfFrames; wholepos = zeros(totalframenum,2);%Declare a array for hodling the positions for k = 1: totalframenum % Loop through every frame in the video if (k < 30) frame = deleteframe(); else frame = readFrames(); [centroids, bboxes, mask] = detectObjects(frame); predictNewLocationsOfTracks(); [assignments, unassignedTracks, unassignedDetections] = ... detectionToTrackAssignment(); if isempty(tracks)%Only create tracks when it is empty, therefore only creating one createNewTracks(); end updateAssignedTracks(); updateUnassignedTracks(); displayTrackingResults(); end end disp(wholepos); save(fname,'wholepos'); end % After processing the video, ask the user whether to save the .m file function obj = setupSystemObjects() % Create a video file reader. obj.reader = VideoReader(myFiles(N).name); obj.reader2 = VideoReader(myFiles(N).name);%This is for reading total video frames totalframe = obj.reader2.NumberOfFrames; obj.videoPlayer = vision.VideoPlayer('Position', [20, 200, 600, 600]); obj.maskPlayer = vision.VideoPlayer('Position', [740, 200, 600, 600]) obj.detector = vision.ForegroundDetector('NumGaussians', 3, ... 'NumTrainingFrames', 70, 'MinimumBackgroundRatio', 0.7,'LearningRate',0.00005); %default is 3, 105, 0.7, 0.000005 obj.blobAnalyser = vision.BlobAnalysis('BoundingBoxOutputPort', true, ... 'AreaOutputPort', true, 'CentroidOutputPort', true, 'LabelMatrixOutputPort', true , 'MinimumBlobArea', 60, 'ExtentOutputPort',true ,'MaximumCount', 1, ... 'MajorAxisLengthOutputPort',true,'MinorAxisLengthOutputPort',true,'OrientationOutputPort',true); end function tracks = initializeTracks() % create an empty array of tracks % Tracks obj includes various features such as the following tracks = struct(... 'id', {}, ... 'bbox', {}, ... 'kalmanFilter', {}, ... 'age', {}, ... 'totalVisibleCount', {}, ... 'consecutiveInvisibleCount', {} ,... 'active',{}); end function frame = deleteframe() frame = readFrame(obj.reader); frame = []; end function frame = readFrames() frame = readFrame(obj.reader); end function [centroids, bboxes, mask] = detectObjects(frame) % Detect foreground. mask = obj.detector.step(frame); mask = imopen(mask, strel('square', 5)); mask = imclose(mask, strel('rectangle', [15,15])); mask = imfill(mask, 'holes'); [ ~,centroids, bboxes ] = obj.blobAnalyser.step(mask); % Perform blob analysis to find connected components. end function predictNewLocationsOfTracks() for i = 1:length(tracks) bbox = tracks(i).bbox; % Predict the current location of the track. predictedCentroid = predict(tracks(i).kalmanFilter); % Shift the bounding box so that its center is at % the predicted location. predictedCentroid = int32(predictedCentroid) - bbox(3:4) / 2; tracks(i).bbox = [predictedCentroid, bbox(3:4)]; end end function [assignments, unassignedTracks, unassignedDetections] = ... detectionToTrackAssignment() nTracks = length(tracks); nDetections = size(centroids, 1); % Compute the cost of assigning each detection to each track. cost = zeros(nTracks, nDetections); for i = 1:nTracks cost(i, :) = distance(tracks(i).kalmanFilter, centroids); end % Solve the assignment problem. costOfNonAssignment = 20; [assignments, unassignedTracks, unassignedDetections] = ... assignDetectionsToTracks(cost, costOfNonAssignment); end function updateAssignedTracks() numAssignedTracks = size(assignments, 1); for i = 1:numAssignedTracks trackIdx = assignments(i, 1); detectionIdx = assignments(i, 2); centroid = centroids(detectionIdx, :); bbox = bboxes(detectionIdx, :); correct(tracks(trackIdx).kalmanFilter, centroid); tracks(trackIdx).bbox = bbox; tracks(trackIdx).age = tracks(trackIdx).age + 1; tracks(trackIdx).totalVisibleCount = ... tracks(trackIdx).totalVisibleCount + 1; tracks(trackIdx).consecutiveInvisibleCount = 0; end end function updateUnassignedTracks() for i = 1:length(unassignedTracks) ind = unassignedTracks(i); tracks(ind).age = tracks(ind).age + 1; tracks(ind).consecutiveInvisibleCount = ... tracks(ind).consecutiveInvisibleCount + 1; end end function createNewTracks() centroids = centroids(unassignedDetections, :); bboxes = bboxes(unassignedDetections, :); for i = 1:size(centroids, 1) centroid = centroids(i,:); bbox = bboxes(i, :); % Create a Kalman filter object. kalmanFilter = configureKalmanFilter('ConstantVelocity', ... centroid, [200, 50], [100, 25], 50); newTrack = struct(... 'id', nextId, ... 'bbox', bbox, ... 'kalmanFilter', kalmanFilter, ... 'age', 1, ... 'totalVisibleCount', 1, ... 'consecutiveInvisibleCount', 0,... 'active',true); % Add it to the array of tracks. tracks(end + 1) = newTrack; % Increment the next id. nextId = nextId + 1; end end function displayTrackingResults() % Convert the frame and the mask to uint8 RGB. frame = im2uint8(frame); mask = uint8(repmat(mask, [1, 1, 3])) .* 255; mask = insertShape(mask,'circle',[260 260 250],'LineWidth', 5); % Set the center of the dish. Default was 1024 1024 450 frame = insertShape(frame, 'circle', [260 260 1], 'LineWidth', 5); % Set the center of the dish. Default was 1024 1024 1 minVisibleCount = 20; if ~isempty(tracks) reliableTrackInds = ... [tracks(:).totalVisibleCount] > minVisibleCount & [tracks(:).active]; reliableTracks = tracks(reliableTrackInds); % Display the objects. If an object has not been detected % in this frame, display its predicted bounding box. if ~isempty(reliableTracks) % Get bounding boxes. bboxes = cat(1, reliableTracks.bbox); % x = double(bboxes(:,1)+bboxes(:,3)/2); y = double(bboxes(:,2)+bboxes(:,4)/2); wholepos(k,1) = x; wholepos(k,2) = y; % Get ids. ids = int32([reliableTracks(:).id]); % Create labels for objects indicating the ones for % which we display the predicted rather than the actual % location. labels = cellstr(int2str(ids')); predictedTrackInds = ... [reliableTracks(:).consecutiveInvisibleCount] > 0; isPredicted = cell(size(labels)); isPredicted(predictedTrackInds) = {'predicted'}; labels = strcat(labels, isPredicted); % Draw the objects on the frame. frame = insertObjectAnnotation(frame, 'rectangle', bboxes, labels,'Color','cyan'); % Draw the objects on the mask. mask = insertObjectAnnotation(mask, 'rectangle', bboxes, labels); % Extracting centroid position for ii=1:length(reliableTracks) trackage = tracks(:).age; end end % Display the mask and the frame. obj.maskPlayer.step(mask); obj.videoPlayer.step(frame); end end end