-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPointFeatureMatching.m
More file actions
105 lines (83 loc) · 2.86 KB
/
Copy pathPointFeatureMatching.m
File metadata and controls
105 lines (83 loc) · 2.86 KB
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
clear all;
clc;
%read the reference video
video = VideoReader("workout.mov");
%read first frame and convert to grayscale
firstFrame = read(video,1);
ffGray = rgb2gray(firstFrame);
%get roi from first frame
imshow(ffGray)
title("Drag Rectangle Around Athlete's Head")
roi = getrect;
athlete = imcrop(ffGray, roi);
%detect point features of roi/athlete
athletePoints = detectSIFTFeatures(athlete);
figure;
imshow(athlete);
title("100 Strongest Point Features from Athlete Head");
hold on;
plot(selectStrongest(athletePoints, 100));
%extract feature descriptors
[athleteFeatures, athletePoints] = extractFeatures(athlete, athletePoints);
figure
imshow(ffGray);
title("Drag Rectangle Around Athlete's Entire Body")
fullBody = getrect;
yMax = fullBody(2);
yMin = fullBody(2) + fullBody(4);
med = (yMax + yMin) / 2;
%rep counting
scale = 0.5;
yOffset = 80;
repCount = 0;
repState = 0;
minFeatures = 3;
%% main loop
while hasFrame(video)
%convert current frame to grayscale
currFrame = readFrame(video);
cfg = imresize(rgb2gray(currFrame), scale);
cfgPoints = detectSIFTFeatures(cfg);
cfgPoints = selectStrongest(cfgPoints, 50);
[cfgFeatures, cfgPoints] = extractFeatures(cfg, cfgPoints);
%putative point matches
pairs = matchFeatures(athleteFeatures, cfgFeatures, MatchThreshold=40,...
MaxRatio=0.7, Unique=true);
matchedAthletePoints = athletePoints(pairs(:, 1), :);
matchedcfgPoints = cfgPoints(pairs(:, 2), :);
%locate object using utative matches
[tform, inlierIdx] = estgeotform2d(matchedAthletePoints, matchedcfgPoints, "affine");
inliercfgPoints = matchedcfgPoints(inlierIdx, :);
%scale locations back to original coordinate space
locs = inliercfgPoints.Location / scale;
%count features past threshold
numUp = sum(locs(:, 2) < yMax + yOffset);
numDown = sum(locs(:, 2) > med - yOffset);
atUp = numUp >= minFeatures;
atDown = numDown >= minFeatures;
%rep state machine (up, down, up)
if repState == 0 && atUp
repState = 1;
fprintf("\nState: Up, go down\n");
elseif repState == 1 && atDown
repState = 2;
fprintf("State: Down, go up\n");
elseif repState == 2 && atUp
repState = 0;
fprintf("State: Up, go down\n");
repCount = repCount + 1;
disp("Reps counted: " + repCount);
end
%display
imshow(currFrame);
hold on;
%scale back for correct overlay on original frame
plot(inliercfgPoints.Location(:,1)/scale, ...
inliercfgPoints.Location(:,2)/scale, ...
'ro', 'MarkerSize', 5, 'LineWidth', 1);
yline(yMax + yOffset, 'b--', 'Up Target');
yline(med - yOffset, 'b--', 'Median Target');
hold off;
pause(0.0000000000001/5000)
end
fprintf("Final rep count: %d\n", repCount);