Skip to content

Commit b984ca9

Browse files
committed
- minor improvements for the silly push up counter app
1 parent b7d7b9d commit b984ca9

File tree

2 files changed

+41
-74
lines changed

2 files changed

+41
-74
lines changed

tools/push_ups/app.html

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,41 @@
44
<meta charset="UTF-8">
55
<meta name="viewport" content="width=device-width, initial-scale=1.0">
66
<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>
7+
<script src="https://cdn.tailwindcss.com"></script>
378
</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>
9+
<body class="bg-gray-100 min-h-screen flex items-center justify-center">
10+
<div class="bg-white p-8 rounded-lg shadow-md max-w-md w-full">
11+
<h1 class="text-3xl font-bold mb-6 text-center text-indigo-600">Push-Up Counter</h1>
12+
13+
<div id="videoContainer" class="mb-6">
14+
<video id="video" class="w-full h-64 object-cover rounded-lg" autoplay muted></video>
15+
</div>
16+
17+
<div class="flex justify-between mb-6">
18+
<button id="switchCamera" class="bg-indigo-500 text-white px-4 py-2 rounded hover:bg-indigo-600 transition">Switch Camera</button>
19+
<button id="startStop" class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600 transition">Start</button>
20+
</div>
21+
22+
<div id="stats" class="mb-6">
23+
<div class="flex justify-between mb-2">
24+
<span class="font-semibold">Push-ups:</span>
25+
<span id="pushUpCount" class="text-indigo-600 font-bold">0</span>
26+
</div>
27+
<div class="flex justify-between">
28+
<span class="font-semibold">Tokens:</span>
29+
<span id="tokenCount" class="text-indigo-600 font-bold">0</span>
30+
</div>
31+
</div>
32+
33+
<div class="mb-6">
34+
<label for="pushUpsPerToken" class="block mb-2 font-semibold">Push-ups per token:</label>
35+
<input type="number" id="pushUpsPerToken" value="10" min="1" class="w-full px-3 py-2 border rounded focus:outline-none focus:ring-2 focus:ring-indigo-500">
36+
</div>
37+
38+
<div id="rewards" class="space-y-4"></div>
4239
</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>
40+
41+
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
5442
<script src="app.js"></script>
5543
</body>
5644
</html>

tools/push_ups/app.js

Lines changed: 8 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,64 +4,52 @@ let isCountingEnabled = false;
44
let currentStream;
55
let facingMode = "user";
66

7-
// New variables for push-up detection
87
let previousBrightness = 0;
9-
let brightnessDiffThreshold = 10; // Adjust based on testing
8+
let brightnessDiffThreshold = 10;
109
let isGoingDown = true;
1110
let lastPushUpTime = 0;
12-
let pushUpCooldown = 1000; // 1 second cooldown between push-ups
11+
let pushUpCooldown = 1000;
1312

1413
async function setupCamera() {
15-
console.log("Setting up camera...");
1614
video = document.getElementById('video');
1715
const constraints = {
1816
video: { facingMode: facingMode }
1917
};
2018
try {
2119
currentStream = await navigator.mediaDevices.getUserMedia(constraints);
2220
video.srcObject = currentStream;
23-
console.log("Camera setup successful");
2421
} catch (error) {
2522
console.error("Camera setup failed:", error);
2623
}
2724
return new Promise((resolve) => {
2825
video.onloadedmetadata = () => {
29-
console.log("Video metadata loaded");
3026
resolve(video);
3127
};
3228
});
3329
}
3430

3531
function startDetection() {
36-
console.log("Starting detection...");
37-
if (!video) {
38-
console.warn("Video not ready. Aborting detection start.");
39-
return;
40-
}
32+
if (!video) return;
4133
detect();
4234
}
4335

4436
async function detect() {
4537
if (!isCountingEnabled) return;
4638
try {
4739
const imageTensor = tf.browser.fromPixels(video);
48-
const resizedImage = tf.image.resizeBilinear(imageTensor, [64, 64]); // Smaller size for faster processing
40+
const resizedImage = tf.image.resizeBilinear(imageTensor, [64, 64]);
4941
const grayImage = tf.image.rgbToGrayscale(resizedImage);
5042
const brightness = tf.mean(grayImage).dataSync()[0];
5143

52-
console.log("Current brightness:", brightness.toFixed(2));
53-
5444
const brightnessDiff = brightness - previousBrightness;
5545

5646
if (Math.abs(brightnessDiff) > brightnessDiffThreshold) {
5747
let currentTime = Date.now();
5848
if (currentTime - lastPushUpTime > pushUpCooldown) {
5949
if (isGoingDown && brightnessDiff > 0) {
60-
console.log("Push-up going up");
6150
isGoingDown = false;
6251
} else if (!isGoingDown && brightnessDiff < 0) {
6352
pushUpCount++;
64-
console.log("Push-up completed. Count:", pushUpCount);
6553
updateStats();
6654
isGoingDown = true;
6755
lastPushUpTime = currentTime;
@@ -71,7 +59,6 @@ async function detect() {
7159

7260
previousBrightness = brightness;
7361

74-
// Clean up tensors
7562
imageTensor.dispose();
7663
resizedImage.dispose();
7764
grayImage.dispose();
@@ -84,16 +71,13 @@ async function detect() {
8471
function updateStats() {
8572
document.getElementById('pushUpCount').textContent = pushUpCount;
8673
const pushUpsPerToken = parseInt(document.getElementById('pushUpsPerToken').value);
87-
console.log("Updating stats. Push-ups:", pushUpCount, "Push-ups per token:", pushUpsPerToken);
8874
if (pushUpCount % pushUpsPerToken === 0) {
8975
tokenCount++;
90-
console.log("Token earned. New token count:", tokenCount);
9176
document.getElementById('tokenCount').textContent = tokenCount;
9277
}
9378
}
9479

9580
document.getElementById('switchCamera').addEventListener('click', async () => {
96-
console.log("Switching camera...");
9781
facingMode = facingMode === "user" ? "environment" : "user";
9882
if (currentStream) {
9983
currentStream.getTracks().forEach(track => track.stop());
@@ -103,50 +87,45 @@ document.getElementById('switchCamera').addEventListener('click', async () => {
10387

10488
document.getElementById('startStop').addEventListener('click', () => {
10589
isCountingEnabled = !isCountingEnabled;
106-
console.log("Counting enabled:", isCountingEnabled);
10790
document.getElementById('startStop').textContent = isCountingEnabled ? 'Stop' : 'Start';
91+
document.getElementById('startStop').classList.toggle('bg-green-500');
92+
document.getElementById('startStop').classList.toggle('bg-red-500');
10893
if (isCountingEnabled) {
10994
startDetection();
11095
}
11196
});
11297

113-
// Reward system
11498
const rewards = [
11599
{ name: 'Extra TV time', cost: 1 },
116100
{ name: 'Favorite snack', cost: 2 },
117101
{ name: 'Movie night', cost: 3 }
118102
];
119103

120104
function displayRewards() {
121-
console.log("Displaying rewards");
122105
const rewardsContainer = document.getElementById('rewards');
123-
rewardsContainer.innerHTML = '<h3>Rewards:</h3>';
106+
rewardsContainer.innerHTML = '<h3 class="text-xl font-semibold mb-4">Rewards:</h3>';
124107
rewards.forEach(reward => {
125108
const button = document.createElement('button');
126109
button.textContent = `${reward.name} (${reward.cost} tokens)`;
110+
button.className = 'w-full bg-indigo-500 text-white px-4 py-2 rounded hover:bg-indigo-600 transition';
127111
button.addEventListener('click', () => redeemReward(reward));
128112
rewardsContainer.appendChild(button);
129113
});
130114
}
131115

132116
function redeemReward(reward) {
133-
console.log("Attempting to redeem reward:", reward.name);
134117
if (tokenCount >= reward.cost) {
135118
tokenCount -= reward.cost;
136119
document.getElementById('tokenCount').textContent = tokenCount;
137-
console.log("Reward redeemed. New token count:", tokenCount);
138120
alert(`You've redeemed: ${reward.name}`);
139121
} else {
140-
console.log("Not enough tokens to redeem reward");
141122
alert('Not enough tokens!');
142123
}
143124
}
144125

145126
async function init() {
146-
console.log("Initializing app...");
147127
await setupCamera();
148128
displayRewards();
149-
console.log("App initialization complete");
150129
}
151130

152131
init();

0 commit comments

Comments
 (0)