Skip to content

Commit b7d7b9d

Browse files
committed
- test
1 parent a92b080 commit b7d7b9d

File tree

2 files changed

+208
-0
lines changed

2 files changed

+208
-0
lines changed

tools/push_ups/app.html

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Push-Up Counter</title>
7+
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
8+
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/movenet"></script>
9+
<style>
10+
body {
11+
font-family: Arial, sans-serif;
12+
display: flex;
13+
flex-direction: column;
14+
align-items: center;
15+
padding: 20px;
16+
}
17+
#videoContainer {
18+
position: relative;
19+
width: 640px;
20+
height: 480px;
21+
}
22+
#output {
23+
position: absolute;
24+
top: 0;
25+
left: 0;
26+
}
27+
button {
28+
margin: 10px;
29+
padding: 10px;
30+
font-size: 16px;
31+
}
32+
#stats {
33+
margin-top: 20px;
34+
font-size: 18px;
35+
}
36+
</style>
37+
</head>
38+
<body>
39+
<div id="videoContainer">
40+
<video id="video" width="640" height="480" autoplay></video>
41+
<canvas id="output" width="640" height="480"></canvas>
42+
</div>
43+
<button id="switchCamera">Switch Camera</button>
44+
<button id="startStop">Start</button>
45+
<div id="stats">
46+
Push-ups: <span id="pushUpCount">0</span><br>
47+
Tokens: <span id="tokenCount">0</span>
48+
</div>
49+
<div>
50+
<label for="pushUpsPerToken">Push-ups per token:</label>
51+
<input type="number" id="pushUpsPerToken" value="10" min="1">
52+
</div>
53+
<div id="rewards"></div>
54+
<script src="app.js"></script>
55+
</body>
56+
</html>

tools/push_ups/app.js

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
let video, canvas, ctx;
2+
let pushUpCount = 0, tokenCount = 0;
3+
let isCountingEnabled = false;
4+
let currentStream;
5+
let facingMode = "user";
6+
7+
// New variables for push-up detection
8+
let previousBrightness = 0;
9+
let brightnessDiffThreshold = 10; // Adjust based on testing
10+
let isGoingDown = true;
11+
let lastPushUpTime = 0;
12+
let pushUpCooldown = 1000; // 1 second cooldown between push-ups
13+
14+
async function setupCamera() {
15+
console.log("Setting up camera...");
16+
video = document.getElementById('video');
17+
const constraints = {
18+
video: { facingMode: facingMode }
19+
};
20+
try {
21+
currentStream = await navigator.mediaDevices.getUserMedia(constraints);
22+
video.srcObject = currentStream;
23+
console.log("Camera setup successful");
24+
} catch (error) {
25+
console.error("Camera setup failed:", error);
26+
}
27+
return new Promise((resolve) => {
28+
video.onloadedmetadata = () => {
29+
console.log("Video metadata loaded");
30+
resolve(video);
31+
};
32+
});
33+
}
34+
35+
function startDetection() {
36+
console.log("Starting detection...");
37+
if (!video) {
38+
console.warn("Video not ready. Aborting detection start.");
39+
return;
40+
}
41+
detect();
42+
}
43+
44+
async function detect() {
45+
if (!isCountingEnabled) return;
46+
try {
47+
const imageTensor = tf.browser.fromPixels(video);
48+
const resizedImage = tf.image.resizeBilinear(imageTensor, [64, 64]); // Smaller size for faster processing
49+
const grayImage = tf.image.rgbToGrayscale(resizedImage);
50+
const brightness = tf.mean(grayImage).dataSync()[0];
51+
52+
console.log("Current brightness:", brightness.toFixed(2));
53+
54+
const brightnessDiff = brightness - previousBrightness;
55+
56+
if (Math.abs(brightnessDiff) > brightnessDiffThreshold) {
57+
let currentTime = Date.now();
58+
if (currentTime - lastPushUpTime > pushUpCooldown) {
59+
if (isGoingDown && brightnessDiff > 0) {
60+
console.log("Push-up going up");
61+
isGoingDown = false;
62+
} else if (!isGoingDown && brightnessDiff < 0) {
63+
pushUpCount++;
64+
console.log("Push-up completed. Count:", pushUpCount);
65+
updateStats();
66+
isGoingDown = true;
67+
lastPushUpTime = currentTime;
68+
}
69+
}
70+
}
71+
72+
previousBrightness = brightness;
73+
74+
// Clean up tensors
75+
imageTensor.dispose();
76+
resizedImage.dispose();
77+
grayImage.dispose();
78+
} catch (error) {
79+
console.error("Error during motion detection:", error);
80+
}
81+
requestAnimationFrame(detect);
82+
}
83+
84+
function updateStats() {
85+
document.getElementById('pushUpCount').textContent = pushUpCount;
86+
const pushUpsPerToken = parseInt(document.getElementById('pushUpsPerToken').value);
87+
console.log("Updating stats. Push-ups:", pushUpCount, "Push-ups per token:", pushUpsPerToken);
88+
if (pushUpCount % pushUpsPerToken === 0) {
89+
tokenCount++;
90+
console.log("Token earned. New token count:", tokenCount);
91+
document.getElementById('tokenCount').textContent = tokenCount;
92+
}
93+
}
94+
95+
document.getElementById('switchCamera').addEventListener('click', async () => {
96+
console.log("Switching camera...");
97+
facingMode = facingMode === "user" ? "environment" : "user";
98+
if (currentStream) {
99+
currentStream.getTracks().forEach(track => track.stop());
100+
}
101+
await setupCamera();
102+
});
103+
104+
document.getElementById('startStop').addEventListener('click', () => {
105+
isCountingEnabled = !isCountingEnabled;
106+
console.log("Counting enabled:", isCountingEnabled);
107+
document.getElementById('startStop').textContent = isCountingEnabled ? 'Stop' : 'Start';
108+
if (isCountingEnabled) {
109+
startDetection();
110+
}
111+
});
112+
113+
// Reward system
114+
const rewards = [
115+
{ name: 'Extra TV time', cost: 1 },
116+
{ name: 'Favorite snack', cost: 2 },
117+
{ name: 'Movie night', cost: 3 }
118+
];
119+
120+
function displayRewards() {
121+
console.log("Displaying rewards");
122+
const rewardsContainer = document.getElementById('rewards');
123+
rewardsContainer.innerHTML = '<h3>Rewards:</h3>';
124+
rewards.forEach(reward => {
125+
const button = document.createElement('button');
126+
button.textContent = `${reward.name} (${reward.cost} tokens)`;
127+
button.addEventListener('click', () => redeemReward(reward));
128+
rewardsContainer.appendChild(button);
129+
});
130+
}
131+
132+
function redeemReward(reward) {
133+
console.log("Attempting to redeem reward:", reward.name);
134+
if (tokenCount >= reward.cost) {
135+
tokenCount -= reward.cost;
136+
document.getElementById('tokenCount').textContent = tokenCount;
137+
console.log("Reward redeemed. New token count:", tokenCount);
138+
alert(`You've redeemed: ${reward.name}`);
139+
} else {
140+
console.log("Not enough tokens to redeem reward");
141+
alert('Not enough tokens!');
142+
}
143+
}
144+
145+
async function init() {
146+
console.log("Initializing app...");
147+
await setupCamera();
148+
displayRewards();
149+
console.log("App initialization complete");
150+
}
151+
152+
init();

0 commit comments

Comments
 (0)