displacement of particles in a video
7 views (last 30 days)
Show older comments
In my code, it reads a video and converts it to a number of instantaneous frames. Then it binaries the balls and finds the centroids of each of the points. I have two columns vector with all the coordinates (x and y) for time t.
I now need to do this from the following frame and create a second set of columns vectors with the locations at t + 1 to find the centroids displaced in time. I want to eventually find the displacement to compute particle velocity.
I am struggling to work out how to create the second column vector for the next time step to see displacement. Would anybody be able to point me in the right direction?
%% Get video into MATLAB
%Input video using videoreader and name it 'obj'
obj = VideoReader('highamballvideo.mov')
%% Read the frames in the video
%Define the frames in the video which you want MATLAB to read, in this case 20-34
frames_no = [20:34];
%Tell it to read the frames in the video (obj) where 20 is start and 34 finish
vidFrames = read(obj,[20 34]);
%Tell it to get the number of individual frames in the whole video
numFrames = size(vidFrames,4);
%Get individual frames
%Colormap is a table of colors used for index color videos
%c.data is an image sequence matrix
%How many times you repeat a function in a loop is defined by 'k'
%k = the range of values the for loop will run through before ending.
for k = 1: numFrames
mov(k).cdata = vidFrames(:,:,:,k); %for all rows and columns in k
mov(k).colormap = []; %create an empty matrix
end
%Watch the video
figure(1), movie(mov, 1, obj.FrameRate), title('Original movie');
%Show all frames in a montaged figure
figure(2), montage(vidFrames(:,:,:,1:15)),title('Montage of frames 20 to 34');
%% Track particle centroids in video
%Jonny's script
%Define the frames between which particles are going to be tracked
start_frame = 10;
end_frame = 100;
%Define the radii of the circles to get MATLAB to search for
min_radius = 4;
max_radius = 20;
quality = .9;
%Binarize, identify circles, plot centroids in all the specified frames for time 't'
for loop = start_frame:end_frame; %for all frames in the range defined
clf %clear current figure
%binarize the frames
frame = rgb2gray(read(obj,loop)); %turn all stated frames in the video from color to greyscale
%find circles within the frames with radii between 4-20 (line 47-50)
centres=imfindcircles(frame,[min_radius,max_radius],'Sensitivity',quality,'Method','TwoStage')
%display image with scaled colors
imagesc(frame);
hold on
%here we get two vectors of the centroids (coordinates) and plot them through each frame
xs = centres(:,1); %first column of the vector is x-coordinates
ys = centres(:,2); %second column of the vector is y-coordinates
scatter(xs,ys,'r') % plot these coordinates as a scatter, on top of the image, in red
%Use drawnow to display the changes on the screen after each iteration through the loop.
drawnow
end
2 Comments
Guillaume
on 2 Apr 2020
It's not clear what size of particles (in pixels) you are tracking, nor how many there are. If the particles are sufficiently small have you looked into well established Particle Tracking Velocimetry (PTV) algorithms (for small number of particles) and Particle Image Velocimetry (PIV) algorithms (for large number).
There's even an unofficial toolbox for it somewhere on the Net.
Accepted Answer
Ameer Hamza
on 2 Apr 2020
There are two points to consider
- Since the number of circles can change between frames.
- The imfindcircles circles can give the circles in an arbitrary order. A circle that appears at the top for 1st frame may appear somewhere else.
For the first issue, you will need to save the centers if circles in a cell array. They can handle matrices of varying sizes.
%Binarize, identify circles, plot centroids in all the specified frames for time 't'
centres = cell(size(start_frame:end_frame));
count = 1;
for loop = start_frame:end_frame; %for all frames in the range defined
clf %clear current figure
%binarize the frames
frame = rgb2gray(read(obj,loop)); %turn all stated frames in the video from color to greyscale
%find circles within the frames with radii between 4-20 (line 47-50)
centres{count}=imfindcircles(frame,[min_radius,max_radius],'Sensitivity',quality,'Method','TwoStage')
%display image with scaled colors
imagesc(frame);
hold on
%here we get two vectors of the centroids (coordinates) and plot them through each frame
xs = centres{count}(:,1); %first column of the vector is x-coordinates
ys = centres{count}(:,2); %second column of the vector is y-coordinates
scatter(xs,ys,'r') % plot these coordinates as a scatter, on top of the image, in red
%Use drawnow to display the changes on the screen after each iteration through the loop.
drawnow
count = count + 1;
end
variable centres contains center locations for each frame.
For the second, I suggest using pdist2() function to find the distance between circle centers in frame t and the circle centers in frame t+1. Two circles that have the least distance will correspond to each other.
4 Comments
Ameer Hamza
on 3 Apr 2020
Edited: Ameer Hamza
on 3 Apr 2020
This shows how to match corresponding circles between two frames
% in first frame, the circles are detected in this order
centres1 = [10 12; % circle 1
15 20; % circle 2
5 15; % circle 3
20 20]; % circle 4
% in second frame, the circles are detected in a different order
centres2 = [16 22; % circle 2
18 23; % circle 4
13 13; % circle 1
3 18]; % circle 3
% here we know the which circles are same, but suppose we didn't know, then
% we can find the corresponding circles like this
Dist = pdist2(centres1, centres2);
[~, idx] = min(Dist, [], 2);
centres2 = centres2(idx, :);
After this, the rows of centres1 and centres2 corresponds to the same circle.
More Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!