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

回答 (1 件)

Image Analyst
Image Analyst 2020 年 5 月 21 日

0 投票

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 件のコメント

C.G.
C.G. 2020 年 5 月 21 日
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 2020 年 5 月 21 日
Attach the two frames in question as PNG images.
C.G.
C.G. 2020 年 5 月 21 日
編集済み: C.G. 2020 年 5 月 21 日
The frames should be attached here
Image Analyst
Image Analyst 2020 年 5 月 21 日
How are you getting the yb_1{k} and yb_2{k}?
C.G.
C.G. 2020 年 5 月 21 日
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 2020 年 5 月 21 日
OK, well now it would be easier if you just attached the video.
C.G.
C.G. 2020 年 5 月 22 日
Sorry I should have thoguht of that
C.G.
C.G. 2020 年 5 月 26 日
Hello just wondering if you were still able to help me with this issue?

サインインしてコメントする。

カテゴリ

タグ

質問済み:

2020 年 5 月 21 日

コメント済み:

2020 年 5 月 26 日

Community Treasure Hunt

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

Start Hunting!

Translated by