Files
rUv f3c77b1750 Add WiFi DensePose implementation and results
- Implemented the WiFi DensePose model in PyTorch, including CSI phase processing, modality translation, and DensePose prediction heads.
- Added a comprehensive training utility for the model, including loss functions and training steps.
- Created a CSV file to document hardware specifications, architecture details, training parameters, performance metrics, and advantages of the model.
2025-06-07 05:23:07 +00:00

384 lines
13 KiB
JavaScript

// WiFi DensePose Application JavaScript
document.addEventListener('DOMContentLoaded', function() {
// Initialize tabs
initTabs();
// Initialize hardware visualization
initHardware();
// Initialize demo simulation
initDemo();
// Initialize architecture interaction
initArchitecture();
});
// Tab switching functionality
function initTabs() {
const tabs = document.querySelectorAll('.nav-tab');
const tabContents = document.querySelectorAll('.tab-content');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
// Get the tab id
const tabId = tab.getAttribute('data-tab');
// Remove active class from all tabs and contents
tabs.forEach(t => t.classList.remove('active'));
tabContents.forEach(c => c.classList.remove('active'));
// Add active class to current tab and content
tab.classList.add('active');
document.getElementById(tabId).classList.add('active');
});
});
}
// Hardware panel functionality
function initHardware() {
// Antenna interaction
const antennas = document.querySelectorAll('.antenna');
antennas.forEach(antenna => {
antenna.addEventListener('click', () => {
antenna.classList.toggle('active');
updateCSIDisplay();
});
});
// Start CSI simulation
updateCSIDisplay();
setInterval(updateCSIDisplay, 1000);
}
// Update CSI display with random values
function updateCSIDisplay() {
const activeAntennas = document.querySelectorAll('.antenna.active');
const isActive = activeAntennas.length > 0;
// Only update if at least one antenna is active
if (isActive) {
const amplitudeFill = document.querySelector('.csi-fill.amplitude');
const phaseFill = document.querySelector('.csi-fill.phase');
const amplitudeValue = document.querySelector('.csi-row:first-child .csi-value');
const phaseValue = document.querySelector('.csi-row:last-child .csi-value');
// Generate random values
const amplitude = (Math.random() * 0.4 + 0.5).toFixed(2); // Between 0.5 and 0.9
const phase = (Math.random() * 1.5 + 0.5).toFixed(1); // Between 0.5 and 2.0
// Update the display
amplitudeFill.style.width = `${amplitude * 100}%`;
phaseFill.style.width = `${phase * 50}%`;
amplitudeValue.textContent = amplitude;
phaseValue.textContent = `${phase}π`;
}
}
// Demo functionality
function initDemo() {
const startButton = document.getElementById('startDemo');
const stopButton = document.getElementById('stopDemo');
const demoStatus = document.getElementById('demoStatus');
const signalCanvas = document.getElementById('signalCanvas');
const poseCanvas = document.getElementById('poseCanvas');
const signalStrength = document.getElementById('signalStrength');
const latency = document.getElementById('latency');
const personCount = document.getElementById('personCount');
const confidence = document.getElementById('confidence');
const keypoints = document.getElementById('keypoints');
let demoRunning = false;
let animationFrameId = null;
let signalCtx = signalCanvas.getContext('2d');
let poseCtx = poseCanvas.getContext('2d');
// Initialize canvas contexts
signalCtx.fillStyle = 'rgba(0, 0, 0, 0.2)';
signalCtx.fillRect(0, 0, signalCanvas.width, signalCanvas.height);
poseCtx.fillStyle = 'rgba(0, 0, 0, 0.2)';
poseCtx.fillRect(0, 0, poseCanvas.width, poseCanvas.height);
// Start demo button
startButton.addEventListener('click', () => {
if (!demoRunning) {
demoRunning = true;
startButton.disabled = true;
stopButton.disabled = false;
demoStatus.textContent = 'Running';
demoStatus.className = 'status status--success';
// Start the animations
startSignalAnimation();
startPoseAnimation();
// Update metrics with random values
updateDemoMetrics();
}
});
// Stop demo button
stopButton.addEventListener('click', () => {
if (demoRunning) {
demoRunning = false;
startButton.disabled = false;
stopButton.disabled = true;
demoStatus.textContent = 'Stopped';
demoStatus.className = 'status status--info';
// Stop the animations
if (animationFrameId) {
cancelAnimationFrame(animationFrameId);
}
}
});
// Signal animation
function startSignalAnimation() {
let time = 0;
const fps = 30;
const interval = 1000 / fps;
let then = Date.now();
function animate() {
if (!demoRunning) return;
const now = Date.now();
const elapsed = now - then;
if (elapsed > interval) {
then = now - (elapsed % interval);
// Clear canvas
signalCtx.clearRect(0, 0, signalCanvas.width, signalCanvas.height);
signalCtx.fillStyle = 'rgba(0, 0, 0, 0.2)';
signalCtx.fillRect(0, 0, signalCanvas.width, signalCanvas.height);
// Draw amplitude signal
signalCtx.beginPath();
signalCtx.strokeStyle = '#1FB8CD';
signalCtx.lineWidth = 2;
for (let x = 0; x < signalCanvas.width; x++) {
const y = signalCanvas.height / 2 +
Math.sin(x * 0.05 + time) * 30 +
Math.sin(x * 0.02 + time * 1.5) * 15;
if (x === 0) {
signalCtx.moveTo(x, y);
} else {
signalCtx.lineTo(x, y);
}
}
signalCtx.stroke();
// Draw phase signal
signalCtx.beginPath();
signalCtx.strokeStyle = '#FFC185';
signalCtx.lineWidth = 2;
for (let x = 0; x < signalCanvas.width; x++) {
const y = signalCanvas.height / 2 +
Math.cos(x * 0.03 + time * 0.8) * 20 +
Math.cos(x * 0.01 + time * 0.5) * 25;
if (x === 0) {
signalCtx.moveTo(x, y);
} else {
signalCtx.lineTo(x, y);
}
}
signalCtx.stroke();
time += 0.05;
}
animationFrameId = requestAnimationFrame(animate);
}
animate();
}
// Human pose animation
function startPoseAnimation() {
// Create a human wireframe model with keypoints
const keyPoints = [
{ x: 200, y: 70 }, // Head
{ x: 200, y: 100 }, // Neck
{ x: 200, y: 150 }, // Torso
{ x: 160, y: 100 }, // Left shoulder
{ x: 120, y: 130 }, // Left elbow
{ x: 100, y: 160 }, // Left hand
{ x: 240, y: 100 }, // Right shoulder
{ x: 280, y: 130 }, // Right elbow
{ x: 300, y: 160 }, // Right hand
{ x: 180, y: 200 }, // Left hip
{ x: 170, y: 250 }, // Left knee
{ x: 160, y: 290 }, // Left foot
{ x: 220, y: 200 }, // Right hip
{ x: 230, y: 250 }, // Right knee
{ x: 240, y: 290 }, // Right foot
];
// Connections between points
const connections = [
[0, 1], // Head to neck
[1, 2], // Neck to torso
[1, 3], // Neck to left shoulder
[3, 4], // Left shoulder to left elbow
[4, 5], // Left elbow to left hand
[1, 6], // Neck to right shoulder
[6, 7], // Right shoulder to right elbow
[7, 8], // Right elbow to right hand
[2, 9], // Torso to left hip
[9, 10], // Left hip to left knee
[10, 11], // Left knee to left foot
[2, 12], // Torso to right hip
[12, 13], // Right hip to right knee
[13, 14], // Right knee to right foot
[9, 12] // Left hip to right hip
];
let time = 0;
const fps = 30;
const interval = 1000 / fps;
let then = Date.now();
function animate() {
if (!demoRunning) return;
const now = Date.now();
const elapsed = now - then;
if (elapsed > interval) {
then = now - (elapsed % interval);
// Clear canvas
poseCtx.clearRect(0, 0, poseCanvas.width, poseCanvas.height);
poseCtx.fillStyle = 'rgba(0, 0, 0, 0.2)';
poseCtx.fillRect(0, 0, poseCanvas.width, poseCanvas.height);
// Animate keypoints with subtle movement
const animatedPoints = keyPoints.map((point, index) => {
// Add subtle movement based on position
const xOffset = Math.sin(time + index * 0.2) * 2;
const yOffset = Math.cos(time + index * 0.2) * 2;
return {
x: point.x + xOffset,
y: point.y + yOffset
};
});
// Draw connections (skeleton)
poseCtx.strokeStyle = '#1FB8CD';
poseCtx.lineWidth = 3;
connections.forEach(([i, j]) => {
poseCtx.beginPath();
poseCtx.moveTo(animatedPoints[i].x, animatedPoints[i].y);
poseCtx.lineTo(animatedPoints[j].x, animatedPoints[j].y);
poseCtx.stroke();
});
// Draw keypoints
poseCtx.fillStyle = '#FFC185';
animatedPoints.forEach(point => {
poseCtx.beginPath();
poseCtx.arc(point.x, point.y, 5, 0, Math.PI * 2);
poseCtx.fill();
});
// Draw body segments (simplified DensePose representation)
drawBodySegments(poseCtx, animatedPoints);
time += 0.05;
}
animationFrameId = requestAnimationFrame(animate);
}
animate();
}
// Draw body segments for DensePose visualization
function drawBodySegments(ctx, points) {
// Define simplified body segments
const segments = [
[0, 1, 6, 3], // Head and shoulders
[1, 2, 12, 9], // Torso
[3, 4, 5, 3], // Left arm
[6, 7, 8, 6], // Right arm
[9, 10, 11, 9], // Left leg
[12, 13, 14, 12] // Right leg
];
ctx.globalAlpha = 0.2;
segments.forEach((segment, index) => {
const gradient = ctx.createLinearGradient(
points[segment[0]].x, points[segment[0]].y,
points[segment[2]].x, points[segment[2]].y
);
gradient.addColorStop(0, '#1FB8CD');
gradient.addColorStop(1, '#FFC185');
ctx.fillStyle = gradient;
ctx.beginPath();
ctx.moveTo(points[segment[0]].x, points[segment[0]].y);
// Connect the points in the segment
for (let i = 1; i < segment.length; i++) {
ctx.lineTo(points[segment[i]].x, points[segment[i]].y);
}
ctx.closePath();
ctx.fill();
});
ctx.globalAlpha = 1.0;
}
// Update demo metrics
function updateDemoMetrics() {
if (!demoRunning) return;
// Update with random values
const strength = Math.floor(Math.random() * 10) - 50;
const lat = Math.floor(Math.random() * 8) + 8;
const persons = Math.floor(Math.random() * 2) + 1;
const conf = (Math.random() * 10 + 80).toFixed(1);
signalStrength.textContent = `${strength} dBm`;
latency.textContent = `${lat} ms`;
personCount.textContent = persons;
confidence.textContent = `${conf}%`;
// Schedule next update
setTimeout(updateDemoMetrics, 2000);
}
}
// Architecture interaction
function initArchitecture() {
const stepCards = document.querySelectorAll('.step-card');
stepCards.forEach(card => {
card.addEventListener('click', () => {
// Get step number
const step = card.getAttribute('data-step');
// Remove active class from all steps
stepCards.forEach(s => s.classList.remove('highlight'));
// Add active class to current step
card.classList.add('highlight');
});
});
}