forked from amrut-prabhu/table-tennis-ball-trajectory
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgetBallPosition.m
112 lines (92 loc) · 3.59 KB
/
getBallPosition.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
% Returns the x and y coordinates of the table tennis ball in the given
% frame. Returns (-1, -1) if ball is not detected.
% Input:
% frame (uint8): An image frame of the moving table tennis ball video.
% Output:
% ballX (double): x coordinate of the table tennis ball in the frame wrt
% to top left corner
% ballY (double): y coordinate of the table tennis ball in the frame wrt
% to top left corner (positive axis is downwards)
function[ballX, ballY] = getBallPosition(frame, cam)
% fprintf("In function getBallPosition()\n");
% ================================Constants================================
% Threshold used to classify a window as containing the streak of the moving ball
BALL_THRESHOLD = 6;
% Threshold used to classify a window as an empty window, i.e., no movement is captured in the window
EMPTY_THRESHOLD = 2;
% Dimensions of the sliding window
WINDOW_WIDTH = 48;
WINDOW_HEIGHT = 35;
% Dimensions of the video frame
[FRAME_HEIGHT, FRAME_WIDTH] = size(frame);
% Coordinates from which to start searching for the ball
START_X = 480;
START_Y = 220;
X_LIMIT = FRAME_WIDTH - WINDOW_WIDTH;
if cam == 2
START_X = 600;
end
if cam == 3
X_LIMIT = 1400;
end
% Logical value to decide whether the moving window should be displayed
IS_PROCESSING_SHOWN = false;
% ===========================Logic/Implementation==========================
if IS_PROCESSING_SHOWN
diffFig = figure();
movegui(diffFig,'northwest');
% imshow(uint8(frame));
imshow(uint8(frame),'InitialMagnification',200)
drawnow;
end
% Represents coordinates of the table tennis ball
ballX = -1;
ballY = -1;
y = START_Y;
while y < FRAME_HEIGHT - WINDOW_HEIGHT
% TODO: FIND A WAY TO OPTIMISE INCREMENT OF ROW (similar to col = col + windowWidth)
y = y + 1;
x = START_X;
while x < X_LIMIT
x = x + 1;
window = frame(y:y+WINDOW_HEIGHT, x:x+WINDOW_WIDTH);
avgPixelValue = mean2(window);
if IS_PROCESSING_SHOWN
% Turn off message warning: 'Image is too big to fit on screen; displaying at 67%'
% [message, MSGID] = lastwarn();
MSGID = 'images:initSize:adjustingMag';
warning('off', MSGID);
RGB = insertShape(uint8(frame),'Rectangle',[x y WINDOW_WIDTH WINDOW_HEIGHT],'LineWidth',3);
% truesize([300 200]);
% imshow(RGB,'InitialMagnification',200)
imshow(RGB);
drawnow;
end
if ~hasEmptyBorders(window)
% fprintf("Invalid window\n"); % since borders are not black (empty)
continue;
end
% fprintf("Window at(%d,%d) avgVal=%3.2f\n", x, y, avgPixelValue);
% TODO: Alternatively, we can reduce threshold, use a function to
% see if size of streak is large enough. If not, exit the function.
% This way we can account for smaller streaks? Need to experiment a
% bit.
if (avgPixelValue > BALL_THRESHOLD)
[ballX, ballY] = getCentreOfBallStreak(window, x, y);
% fprintf("Ball = (%4f,%4f)\n", ballX, ballY);
if IS_PROCESSING_SHOWN
close(diffFig);
end
return;
elseif (avgPixelValue < EMPTY_THRESHOLD)
% Speed optimisation: Increment by a large amount
ballX = avgPixelValue;
x = x + WINDOW_WIDTH*0.75;
end
end
end
% fprintf("No ball found\n");
if IS_PROCESSING_SHOWN
close(diffFig);
end
end