assigning centroids to xy coordinates

I have identified the centroids of a series of circles on 2 frames of a video.
I have tried to compute the distance between these centroids and then assign these to x and y coordinates for each frame, however the centroids do not match up the the locations; they are supposed to be on the black spots on the ball.
Could anybody help?
%% Crop the images to only 1 ball per image and compute pentagon velocity
r = 21; %radius of whole ball
thresholdvalue = 13; %use as threshold when binarizing
for k = 1:numFrames
%subimage the balls in frames 1 and 2 by shrinking them to the coordinates of the balls
%should produce a series of images, where each image only shows 1 ball,for all the balls in the video
subframe1 = frame_1(round(yb_1{k})-r:round(yb_1{k})+r, round(xb_1{k})-r:round(xb_1{k})+r);
subframe2 = frame_2(round(yb_2{k})-r:round(yb_2{k})+r, round(xb_2{k})-r:round(xb_2{k})+r);
figure(4)
subplot(2,1,1)
imshow(subframe1)
subplot(2,1,2)
imshow(subframe2)
end
for k = 1:numFrames
%identify the circles in frames 1 and 2 with radii between the defined min and max
%imfindcircles is a function in matlab that finds circles between a
%radius range
pentagons_1 = subframe1 < thresholdvalue; % if thresholdvalue = <, searches for dark objects in the video frames, > searches for light objects
pentagons_2 = subframe2 < thresholdvalue;
figure(5)
imshow(pentagons_1)
pentagons_1 = imclearborder(pentagons_1); % get rid of black background in video frames
pentagons_2 = imclearborder(pentagons_2);
pentagons_1 = bwareafilt(pentagons_1, [5, inf]); % find blobs >5 pixels (i.e. pentagons on the balls)
pentagons_2 = bwareafilt(pentagons_2, [5, inf]);
props_1 = regionprops(pentagons_1, 'Centroid'); % get the centroids of the pentagons in frame 1
props_2 = regionprops(pentagons_2, 'Centroid'); % get the centroids of the pentagons in frame 2
centroids_1 = cat(1,props_1.Centroid); %store the centroid of each blob
centroids_2 = cat(1,props_2.Centroid);
%check centroids in both subframes
figure(6)
subplot(2,1,1)
imshow(pentagons_1)
hold on
plot(centroids_1(:,1),centroids_1(:,2),'b*')
hold off
subplot(2,1,2)
imshow(pentagons_2)
hold on
plot(centroids_2(:,1),centroids_2(:,2),'r*')
%identify where each circle has moved between frames 1 and 2
%returns the distance from each point in centres_2 to the corresponding point in centres_1
[indexp,distp] = dsearchn(centroids_2,centroids_1);
%here we have the distances not in order
%assign the circles from frames 1 and 2 to x and y coordinate variables
xp_1{k} = centroids_1(:,1);
xp_2{k} = centroids_2(:,1);
yp_1{k} = centroids_1(:,2);
yp_2{k} = centroids_2(:,2);
%check its worked
figure(7)
subplot(2,1,1)
imshow(frame_1)
hold on
scatter(xp_1{k},yp_1{k},'r*')
subplot(2,1,2)
imshow(frame_2)
hold on
scatter(xp_2{k},yp_2{k},'b*')
end

Respuestas (1)

Image Analyst
Image Analyst el 21 de Mayo de 2020

0 votos

You need to combine those two for loops into one. Otherwise subframe1 and subframe2 are only the very last ones from your first loop.

8 comentarios

C.G.
C.G. el 21 de Mayo de 2020
I have combined these so it is all in one for-end loop, however the issue of the centroid coordinates not matching the correct points on the football still occurs
Image Analyst
Image Analyst el 21 de Mayo de 2020
Attach the two frames in question as PNG images.
C.G.
C.G. el 21 de Mayo de 2020
Editada: C.G. el 21 de Mayo de 2020
The frames should be attached here
Image Analyst
Image Analyst el 21 de Mayo de 2020
How are you getting the yb_1{k} and yb_2{k}?
C.G.
C.G. el 21 de Mayo de 2020
Sorry i had only attached a portion of my code. Here is it from start to finish:
%% Input video
%Input video using videoreader command and name it 'obj'
obj = VideoReader('2D_football_video.mp4')
%% Define the start and end frames for all the tracking runs
%Define the frames between which particles are going to be tracked
start_frame = 1; %which frame of the video do you want it to start from
numFrames = 10; %which frame of the video do you want it to end on
%% Identify the whole ball in frames 1 and 2 track these through each video frame
%Define the radii of the circles to get MATLAB to search for
min_radiusball = 15;
max_radiusball = 25;
quality = .9; %quality is a number between 0-1 to see how strong a circle must be in order to be found. Values of 1 discard no circles
t = 0.1; % t is the frame rate, used as time in the velocity calculation
% Grid coarseness
n = 5; %spacing in the grid
% Here I am going to do all the same steps but in one move, this will be much more memory efficient.
tmpframe = read(obj,1); %read only the first frame from the video
% Meshgrid creates 2D grid coordinates with x and y coordinates defined by the length of the two inputted vectors
% Grids going from 1 to the length of tmpframe, in spacings of 5 (n)
[X,Y]=meshgrid(1:n:size(tmpframe,2),1:n:size(tmpframe,1));
%Track the whole balls and plot velocity for frames 1 and 2
for k = 1:numFrames;
%binarize frames 1 and 2 from the video (using rgb2gray)
frame_1 = rgb2gray(read(obj,k+start_frame-1));
frame_2 = rgb2gray(read(obj,k+start_frame));
%identify the circles in frames 1 and 2 with radii between the defined min and max
%imfindcircles is a function in matlab that finds circles between a radius range
ballcentres_1 =imfindcircles(frame_1,[min_radiusball,max_radiusball],'Sensitivity',quality,'Method','TwoStage');
ballcentres_2 =imfindcircles(frame_2,[min_radiusball,max_radiusball],'Sensitivity',quality,'Method','TwoStage');
%identify where each circle has moved between frames 1 and 2
%returns the distance from each point in centres_2 to the corresponding point in centres_1
%indexb = indicies returned as a column vector containing the indicies
%of the data points closest to the query points
%distb = distance, returned as a column vector containing the euclidean
%distance between each query point and the closest input point
[indexb,distb] = dsearchn(ballcentres_2,ballcentres_1);
% here we have the distances not in order
% assign the circles from frames 1 and 2 to x and y coordinate variables
xb_1{k} = ballcentres_1(:,1);
xb_2{k} = ballcentres_2(indexb,1);
yb_1{k} = ballcentres_1(:,2);
yb_2{k} = ballcentres_2(indexb,2);
%show
subplot(2,1,1)
imshow(frame_1)
hold on
scatter(xb_1{k},yb_1{k},'r*')
subplot(2,1,2)
imshow(frame_2)
hold on
scatter(xb_2{k},yb_2{k},'b*')
% now we compute the translational velocity of each ball as v = d/t
velb_x{k} = (xb_2{k}-xb_1{k})/t; % x velocity using frame 2 - frame 1
velb_y{k} = (yb_2{k}-yb_1{k})/t; % y velocity using frame 2 - frame 1
velb_res{k} = sqrt(velb_x{k}.^2 + velb_y{k}.^2); % the final velocity vector as a function as its x and y components
% now we can make a overall velocity map, by reshaping the array
% for all the columns in 'loop', reshape the array 'griddata' to define, size U, V and RES
Ub(:,:,k)=reshape(griddata(xb_1{k},yb_1{k},velb_x{k},X(:),Y(:)),size(X,1),size(X,2));
Vb(:,:,k)=reshape(griddata(xb_1{k},yb_1{k},velb_y{k},X(:),Y(:)),size(X,1),size(X,2));
RESb(:,:,k)=reshape(griddata(xb_1{k},yb_1{k},velb_res{k},X(:),Y(:)),size(X,1),size(X,2));
end
% show a velocity map for the ball translations
figure(3)
% Set graphics objects properties: size of the figure (x0,y0,width,height)
set(gcf,'position',[246,738,1701,210])
% This loop will now display what we have just made
for k = 1:numFrames-1;
subplot(1,2,1); %creates a figure with 2 plots side by side
scatter(xb_1{k},yb_1{k},20,velb_res{k})
hold on
subplot(1,2,2);
%displays RES as an image using the full range of colors where each element of RES corresponds to a rectangular area in the image
imagesc(RESb(:,:,k))
pause(1)
end
%% Crop the images to only 1 ball per image
thresholdvalue = 13; %use as threshold when binarizing
r = 20; %radius of whole ball
for k = 1:numFrames
%subimage the balls in frames 1 and 2 by shrinking them to the coordinates of the balls
%should produce a series of images, where each image only shows 1 ball,for all the balls in the video
subframe1 = frame_1(round(yb_1{k})-r:round(yb_1{k})+r, round(xb_1{k})-r:round(xb_1{k})+r);
subframe2 = frame_2(round(yb_2{k})-r:round(yb_2{k})+r, round(xb_2{k})-r:round(xb_2{k})+r);
%check its worked
figure(4)
subplot(2,1,1)
imshow(subframe1)
subplot(2,1,2)
imshow(subframe2)
%threshold the image
pentagons_1 = subframe1 < thresholdvalue; % if thresholdvalue = <, searches for dark objects in the video frames, > searches for light objects
pentagons_2 = subframe2 < thresholdvalue;
pentagons_1 = imclearborder(pentagons_1); % get rid of black background in video frames
pentagons_2 = imclearborder(pentagons_2);
pentagons_1 = bwareafilt(pentagons_1, [5, inf]); % find blobs >5 pixels (i.e. pentagons on the balls)
pentagons_2 = bwareafilt(pentagons_2, [5, inf]);
%call the regionprops function to identify the circles and the centres
%of these
stats1 = regionprops('table', pentagons_1, 'Centroid', 'MajorAxisLength', 'MinorAxisLength');
stats2 = regionprops('table', pentagons_2, 'Centroid', 'MajorAxisLength', 'MinorAxisLength');
%store the centres coordinates
centres1 = stats1.Centroid;
centres2 = stats2.Centroid;
%store the diameters and radii
diameters1 = mean([stats1.MajorAxisLength stats1.MinorAxisLength],2);
diameters2 = mean([stats2.MajorAxisLength stats2.MinorAxisLength],2);
radii1 = diameters1/2;
radii2 = diameters2/2;
%check the circles in both subframes
subplot(2,1,1)
imshow(pentagons_1)
hold on
viscircles(centres1,radii1)
subplot(2,1,2)
imshow(pentagons_2)
hold on
viscircles(centres2,radii2)
%check centroids in both subframes
figure(6)
subplot(2,1,1)
imshow(subframe1)
hold on
plot(centres1(:,1),centres1(:,2),'b*')
hold off
subplot(2,1,2)
imshow(subframe2)
hold on
plot(centres2(:,1),centres2(:,2),'r*')
%identify where each circle has moved between frames 1 and 2
%returns the distance from each point in centres_2 to the corresponding point in centres_1
[indexp,distp] = dsearchn(centres2,centres1);
%assign the circles from frames 1 and 2 to x and y coordinate variables
xp_1{k} = centres1(:,1);
xp_2{k} = centres2(indexp,1);
yp_1{k} = centres1(:,2);
yp_2{k} = centres2(indexp,2);
%check its worked
figure(7)
subplot(2,1,1)
imshow(frame_1)
hold on
scatter(xp_1{k},yp_1{k},'r*')
subplot(2,1,2)
imshow(frame_2)
hold on
scatter(xp_2{k},yp_2{k},'b*')
end
% now we compute the translational velocity of each ball as v = d/t
velp_x{k} = (xp_2{k}-xp_1{k})/t; % x velocity using frame 2 - frame 1
velp_y{k} = (yp_2{k}-yp_1{k})/t; % y velocity using frame 2 - frame 1
velp_res{k} = sqrt(velp_x{k}.^2 + velp_y{k}.^2); % the final velocity vector as a function as its x and y components
% now we can make a overall velocity map, by reshaping the array
% for all the columns in 'loop', reshape the array 'griddata' to define, size U, V and RES
Up(:,:,k)=reshape(griddata(xp_1{k},yp_1{k},velp_x{k},X(:),Y(:)),size(X,1),size(X,2));
Vp(:,:,k)=reshape(griddata(xp_1{k},yp_1{k},velp_y{k},X(:),Y(:)),size(X,1),size(X,2));
RESp(:,:,k)=reshape(griddata(xp_1{k},yp_1{k},velp_res{k},X(:),Y(:)),size(X,1),size(X,2));
% show a velocity map for the ball translations
figure(3)
% Set graphics objects properties: size of the figure (x0,y0,width,height)
set(gcf,'position',[246,738,1701,210])
% This loop will now display what we have just made
for k = 1:numFrames-1;
subplot(1,2,1); %creates a figure with 2 plots side by side
scatter(xp_1{k},yp_1{k},20,velp_res{k})
hold on
subplot(1,2,2);
%displays RES as an image using the full range of colors where each element of RES corresponds to a rectangular area in the image
imagesc(RESp(:,:,k))
pause(1)
end
Image Analyst
Image Analyst el 21 de Mayo de 2020
OK, well now it would be easier if you just attached the video.
C.G.
C.G. el 22 de Mayo de 2020
Sorry I should have thoguht of that
C.G.
C.G. el 26 de Mayo de 2020
Hello just wondering if you were still able to help me with this issue?

Iniciar sesión para comentar.

Categorías

Etiquetas

Preguntada:

el 21 de Mayo de 2020

Comentada:

el 26 de Mayo de 2020

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by