aicodingfun commited on
Commit
19bb843
Β·
verified Β·
1 Parent(s): d37737e

Create script.js

Browse files
Files changed (1) hide show
  1. script.js +156 -0
script.js ADDED
@@ -0,0 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // const URL = "https://teachablemachine.withgoogle.com/models/uYk-wIQy6/";
2
+ const URL = "https://teachablemachine.withgoogle.com/models/DTgj24KYa/";
3
+
4
+ let model, webcam, ctx, labelContainer, maxPredictions;
5
+ let isInitialized = false;
6
+
7
+ // Wait for libraries to load
8
+ function waitForLibraries() {
9
+ return new Promise((resolve) => {
10
+ const checkLibraries = () => {
11
+ if (typeof tmPose !== 'undefined' && typeof tf !== 'undefined') {
12
+ resolve();
13
+ } else {
14
+ setTimeout(checkLibraries, 100);
15
+ }
16
+ };
17
+ checkLibraries();
18
+ });
19
+ }
20
+
21
+ async function init() {
22
+ if (isInitialized) return;
23
+
24
+ // First, wait for libraries to load
25
+ await waitForLibraries();
26
+
27
+ const startBtn = document.getElementById('startBtn');
28
+ const statusIndicator = document.getElementById('statusIndicator');
29
+ const loadingSpinner = document.getElementById('loadingSpinner');
30
+
31
+ // Display loading status
32
+ startBtn.innerHTML = 'πŸ”„ Loading...';
33
+ startBtn.disabled = true;
34
+ loadingSpinner.style.display = 'block';
35
+
36
+ try {
37
+ const modelURL = URL + "model.json";
38
+ const metadataURL = URL + "metadata.json";
39
+
40
+ model = await tmPose.load(modelURL, metadataURL);
41
+ maxPredictions = model.getTotalClasses();
42
+
43
+ const size = 300;
44
+ const flip = true;
45
+ webcam = new tmPose.Webcam(size, size, flip);
46
+ await webcam.setup();
47
+ await webcam.play();
48
+
49
+ window.requestAnimationFrame(loop);
50
+
51
+ const canvas = document.getElementById("canvas");
52
+ canvas.width = size;
53
+ canvas.height = size;
54
+ ctx = canvas.getContext("2d");
55
+ labelContainer = document.getElementById("label-container");
56
+ labelContainer.innerHTML = '';
57
+
58
+ for (let i = 0; i < maxPredictions; i++) {
59
+ const div = document.createElement("div");
60
+ div.className = "prediction-item";
61
+ div.innerHTML = '<div class="prediction-text">Loading...</div>';
62
+ labelContainer.appendChild(div);
63
+ }
64
+
65
+ // Update UI status
66
+ startBtn.innerHTML = 'βœ… Detecting...';
67
+ statusIndicator.classList.add('active');
68
+ loadingSpinner.style.display = 'none';
69
+ isInitialized = true;
70
+
71
+ } catch (error) {
72
+ console.error('Initialization failed:', error);
73
+ startBtn.innerHTML = '❌ Load Failed, Retry';
74
+ startBtn.disabled = false;
75
+ loadingSpinner.style.display = 'none';
76
+ }
77
+ }
78
+
79
+ async function loop(timestamp) {
80
+ if (webcam) {
81
+ webcam.update();
82
+ await predict();
83
+ window.requestAnimationFrame(loop);
84
+ }
85
+ }
86
+
87
+ async function predict() {
88
+ try {
89
+ const { pose, posenetOutput } = await model.estimatePose(webcam.canvas);
90
+ const prediction = await model.predict(posenetOutput);
91
+
92
+ for (let i = 0; i < maxPredictions; i++) {
93
+ const probability = (prediction[i].probability * 100).toFixed(1);
94
+ const className = prediction[i].className;
95
+
96
+ // Add emojis and better formatting
97
+ let emoji = 'πŸ€';
98
+ if (probability > 80) emoji = 'πŸ”₯';
99
+ else if (probability > 60) emoji = '⭐';
100
+ else if (probability > 40) emoji = 'πŸ‘';
101
+
102
+ const predictionText = `${emoji} ${className}: ${probability}%`;
103
+
104
+ const predictionElement = labelContainer.childNodes[i];
105
+ if (predictionElement) {
106
+ predictionElement.querySelector('.prediction-text').innerHTML = predictionText;
107
+
108
+ // Add dynamic styling
109
+ const confidence = parseFloat(probability);
110
+ if (confidence > 50) {
111
+ predictionElement.style.borderLeftColor = '#44ff44';
112
+ predictionElement.style.background = 'rgba(68, 255, 68, 0.1)';
113
+ } else if (confidence > 30) {
114
+ predictionElement.style.borderLeftColor = '#ffd700';
115
+ predictionElement.style.background = 'rgba(255, 215, 0, 0.1)';
116
+ } else {
117
+ predictionElement.style.borderLeftColor = '#ff6b35';
118
+ predictionElement.style.background = 'rgba(255, 107, 53, 0.1)';
119
+ }
120
+ }
121
+ }
122
+
123
+ drawPose(pose);
124
+ } catch (error) {
125
+ console.error('Prediction error:', error);
126
+ }
127
+ }
128
+
129
+ function drawPose(pose) {
130
+ if (webcam && webcam.canvas && ctx) {
131
+ ctx.drawImage(webcam.canvas, 0, 0);
132
+ if (pose) {
133
+ const minPartConfidence = 0.5;
134
+ tmPose.drawKeypoints(pose.keypoints, minPartConfidence, ctx);
135
+ tmPose.drawSkeleton(pose.keypoints, minPartConfidence, ctx);
136
+ }
137
+ }
138
+ }
139
+
140
+ // Check if libraries are loaded after page load
141
+ window.addEventListener('load', async function() {
142
+ try {
143
+ await waitForLibraries();
144
+ console.log('πŸ€ NBA Pose Detector Ready!');
145
+
146
+ // Display ready status
147
+ const startBtn = document.getElementById('startBtn');
148
+ startBtn.innerHTML = 'πŸš€ Start Detection';
149
+ startBtn.style.opacity = '1';
150
+ } catch (error) {
151
+ console.error('Library load failed:', error);
152
+ const startBtn = document.getElementById('startBtn');
153
+ startBtn.innerHTML = '❌ Load Failed';
154
+ startBtn.disabled = true;
155
+ }
156
+ });