// const URL = "https://teachablemachine.withgoogle.com/models/uYk-wIQy6/";
const URL = "https://teachablemachine.withgoogle.com/models/DTgj24KYa/";
let model, webcam, ctx, labelContainer, maxPredictions;
let isInitialized = false;
// Wait for libraries to load
function waitForLibraries() {
return new Promise((resolve) => {
const checkLibraries = () => {
if (typeof tmPose !== 'undefined' && typeof tf !== 'undefined') {
resolve();
} else {
setTimeout(checkLibraries, 100);
}
};
checkLibraries();
});
}
async function init() {
if (isInitialized) return;
// First, wait for libraries to load
await waitForLibraries();
const startBtn = document.getElementById('startBtn');
const statusIndicator = document.getElementById('statusIndicator');
const loadingSpinner = document.getElementById('loadingSpinner');
// Display loading status
startBtn.innerHTML = '🔄 Loading...';
startBtn.disabled = true;
loadingSpinner.style.display = 'block';
try {
const modelURL = URL + "model.json";
const metadataURL = URL + "metadata.json";
model = await tmPose.load(modelURL, metadataURL);
maxPredictions = model.getTotalClasses();
const size = 300;
const flip = true;
webcam = new tmPose.Webcam(size, size, flip);
await webcam.setup();
await webcam.play();
window.requestAnimationFrame(loop);
const canvas = document.getElementById("canvas");
canvas.width = size;
canvas.height = size;
ctx = canvas.getContext("2d");
labelContainer = document.getElementById("label-container");
labelContainer.innerHTML = '';
for (let i = 0; i < maxPredictions; i++) {
const div = document.createElement("div");
div.className = "prediction-item";
div.innerHTML = '
Loading...
';
labelContainer.appendChild(div);
}
// Update UI status
startBtn.innerHTML = '✅ Detecting...';
statusIndicator.classList.add('active');
loadingSpinner.style.display = 'none';
isInitialized = true;
} catch (error) {
console.error('Initialization failed:', error);
startBtn.innerHTML = '❌ Load Failed, Retry';
startBtn.disabled = false;
loadingSpinner.style.display = 'none';
}
}
async function loop(timestamp) {
if (webcam) {
webcam.update();
await predict();
window.requestAnimationFrame(loop);
}
}
async function predict() {
try {
const { pose, posenetOutput } = await model.estimatePose(webcam.canvas);
const prediction = await model.predict(posenetOutput);
for (let i = 0; i < maxPredictions; i++) {
const probability = (prediction[i].probability * 100).toFixed(1);
const className = prediction[i].className;
// Add emojis and better formatting
let emoji = '🏀';
if (probability > 80) emoji = '🔥';
else if (probability > 60) emoji = '⭐';
else if (probability > 40) emoji = '👍';
const predictionText = `${emoji} ${className}: ${probability}%`;
const predictionElement = labelContainer.childNodes[i];
if (predictionElement) {
predictionElement.querySelector('.prediction-text').innerHTML = predictionText;
// Add dynamic styling
const confidence = parseFloat(probability);
if (confidence > 50) {
predictionElement.style.borderLeftColor = '#44ff44';
predictionElement.style.background = 'rgba(68, 255, 68, 0.1)';
} else if (confidence > 30) {
predictionElement.style.borderLeftColor = '#ffd700';
predictionElement.style.background = 'rgba(255, 215, 0, 0.1)';
} else {
predictionElement.style.borderLeftColor = '#ff6b35';
predictionElement.style.background = 'rgba(255, 107, 53, 0.1)';
}
}
}
drawPose(pose);
} catch (error) {
console.error('Prediction error:', error);
}
}
function drawPose(pose) {
if (webcam && webcam.canvas && ctx) {
ctx.drawImage(webcam.canvas, 0, 0);
if (pose) {
const minPartConfidence = 0.5;
tmPose.drawKeypoints(pose.keypoints, minPartConfidence, ctx);
tmPose.drawSkeleton(pose.keypoints, minPartConfidence, ctx);
}
}
}
// Check if libraries are loaded after page load
window.addEventListener('load', async function() {
try {
await waitForLibraries();
console.log('🏀 NBA Pose Detector Ready!');
// Display ready status
const startBtn = document.getElementById('startBtn');
startBtn.innerHTML = '🚀 Start Detection';
startBtn.style.opacity = '1';
} catch (error) {
console.error('Library load failed:', error);
const startBtn = document.getElementById('startBtn');
startBtn.innerHTML = '❌ Load Failed';
startBtn.disabled = true;
}
});