anycoder-1e973fcc / index.html
nzhenev's picture
Upload folder using huggingface_hub
223fd23 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SAM3 Scene Reconstructor | AI Spatial Analysis</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg-dark: #0a0b10;
--bg-panel: #14161f;
--accent: #6366f1;
--accent-glow: rgba(99, 102, 241, 0.4);
--text-main: #f3f4f6;
--text-muted: #9ca3af;
--border: #2d303e;
--success: #10b981;
--grid-color: rgba(255, 255, 255, 0.03);
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Inter', sans-serif;
background-color: var(--bg-dark);
color: var(--text-main);
height: 100vh;
overflow: hidden;
display: flex;
flex-direction: column;
}
/* Background Grid Animation */
.bg-grid {
position: fixed;
top: 0;
left: 0;
width: 200%;
height: 200%;
background-image:
linear-gradient(var(--grid-color) 1px, transparent 1px),
linear-gradient(90deg, var(--grid-color) 1px, transparent 1px);
background-size: 40px 40px;
transform: perspective(500px) rotateX(60deg) translateY(-100px) translateZ(-200px);
animation: gridMove 20s linear infinite;
z-index: -1;
pointer-events: none;
}
@keyframes gridMove {
0% { transform: perspective(500px) rotateX(60deg) translateY(0) translateZ(-200px); }
100% { transform: perspective(500px) rotateX(60deg) translateY(40px) translateZ(-200px); }
}
/* Header */
header {
height: 60px;
background: rgba(20, 22, 31, 0.8);
backdrop-filter: blur(10px);
border-bottom: 1px solid var(--border);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 24px;
z-index: 100;
}
.logo {
display: flex;
align-items: center;
gap: 12px;
font-weight: 700;
font-size: 1.2rem;
letter-spacing: -0.02em;
}
.logo i {
color: var(--accent);
font-size: 1.4rem;
filter: drop-shadow(0 0 8px var(--accent-glow));
}
.anycoder-link {
font-family: 'Space Mono', monospace;
font-size: 0.8rem;
color: var(--text-muted);
text-decoration: none;
border: 1px solid var(--border);
padding: 6px 12px;
border-radius: 4px;
transition: all 0.3s ease;
}
.anycoder-link:hover {
border-color: var(--accent);
color: var(--accent);
background: rgba(99, 102, 241, 0.1);
}
/* Main Layout */
main {
flex: 1;
display: grid;
grid-template-columns: 300px 1fr 320px;
gap: 1px;
background: var(--border); /* Creates gap borders */
height: calc(100vh - 60px);
}
/* Panels Common */
.panel {
background: var(--bg-dark);
display: flex;
flex-direction: column;
overflow: hidden;
}
.panel-header {
padding: 16px;
font-weight: 600;
font-size: 0.9rem;
border-bottom: 1px solid var(--border);
display: flex;
justify-content: space-between;
align-items: center;
background: var(--bg-panel);
}
.panel-content {
flex: 1;
overflow-y: auto;
padding: 20px;
}
/* Left Sidebar - Controls */
.upload-zone {
border: 2px dashed var(--border);
border-radius: 8px;
padding: 30px 20px;
text-align: center;
cursor: pointer;
transition: all 0.3s;
margin-bottom: 24px;
position: relative;
overflow: hidden;
}
.upload-zone:hover {
border-color: var(--accent);
background: rgba(99, 102, 241, 0.05);
}
.upload-zone i {
font-size: 2rem;
color: var(--text-muted);
margin-bottom: 12px;
}
.upload-zone p {
font-size: 0.9rem;
color: var(--text-muted);
}
.control-group {
margin-bottom: 24px;
}
.control-label {
display: block;
font-size: 0.8rem;
color: var(--text-muted);
margin-bottom: 8px;
font-weight: 500;
}
.slider-container {
display: flex;
align-items: center;
gap: 10px;
}
input[type="range"] {
flex: 1;
-webkit-appearance: none;
height: 4px;
background: var(--border);
border-radius: 2px;
outline: none;
}
input[type="range"]::-webkit-slider-thumb {
-webkit-appearance: none;
width: 16px;
height: 16px;
background: var(--accent);
border-radius: 50%;
cursor: pointer;
box-shadow: 0 0 10px var(--accent-glow);
}
.setting-toggle {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px;
background: var(--bg-panel);
border: 1px solid var(--border);
border-radius: 6px;
margin-bottom: 8px;
cursor: pointer;
}
.setting-toggle.active {
border-color: var(--accent);
}
.toggle-switch {
width: 36px;
height: 20px;
background: var(--border);
border-radius: 10px;
position: relative;
transition: 0.3s;
}
.setting-toggle.active .toggle-switch {
background: var(--accent);
}
.toggle-switch::after {
content: '';
position: absolute;
top: 2px;
left: 2px;
width: 16px;
height: 16px;
background: white;
border-radius: 50%;
transition: 0.3s;
}
.setting-toggle.active .toggle-switch::after {
transform: translateX(16px);
}
.btn-primary {
width: 100%;
padding: 14px;
background: var(--accent);
color: white;
border: none;
border-radius: 6px;
font-weight: 600;
cursor: pointer;
transition: 0.2s;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
margin-top: auto;
}
.btn-primary:hover {
background: #5659d6;
box-shadow: 0 0 15px var(--accent-glow);
}
/* Center - Viewport */
.viewport {
position: relative;
background: #000;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
}
.viewport-overlay {
position: absolute;
top: 20px;
left: 20px;
display: flex;
gap: 10px;
}
.badge {
background: rgba(0,0,0,0.6);
backdrop-filter: blur(4px);
padding: 4px 8px;
border-radius: 4px;
font-size: 0.75rem;
font-family: 'Space Mono', monospace;
border: 1px solid rgba(255,255,255,0.1);
}
/* The 3D Scene Simulation */
.scene-container {
width: 100%;
height: 100%;
position: relative;
perspective: 1000px;
transform-style: preserve-3d;
}
.reconstruction-layer {
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
/* Simulated Human Skeleton/Mesh */
.human-mesh {
width: 200px;
height: 400px;
position: relative;
transform-style: preserve-3d;
animation: rotateModel 10s infinite linear;
display: none; /* Hidden initially */
}
@keyframes rotateModel {
0% { transform: rotateY(0deg); }
100% { transform: rotateY(360deg); }
}
/* Simple CSS Geometric Human Representation */
.head { width: 40px; height: 50px; background: rgba(99, 102, 241, 0.2); border: 1px solid var(--accent); border-radius: 12px; position: absolute; top: 0; left: 80px; box-shadow: 0 0 20px var(--accent-glow); }
.torso { width: 80px; height: 120px; background: rgba(99, 102, 241, 0.15); border: 1px solid var(--accent); position: absolute; top: 55px; left: 60px; clip-path: polygon(0% 0%, 100% 0%, 80% 100%, 20% 100%); }
.arm-l { width: 20px; height: 140px; background: rgba(99, 102, 241, 0.15); border: 1px solid var(--accent); position: absolute; top: 55px; left: 30px; transform-origin: top; transform: rotate(10deg); }
.arm-r { width: 20px; height: 140px; background: rgba(99, 102, 241, 0.15); border: 1px solid var(--accent); position: absolute; top: 55px; right: 30px; transform-origin: top; transform: rotate(-10deg); }
.leg-l { width: 25px; height: 160px; background: rgba(99, 102, 241, 0.15); border: 1px solid var(--accent); position: absolute; top: 180px; left: 65px; }
.leg-r { width: 25px; height: 160px; background: rgba(99, 102, 241, 0.15); border: 1px solid var(--accent); position: absolute; top: 180px; right: 65px; }
/* Point Cloud Effect */
.points {
position: absolute;
width: 4px; height: 4px;
background: var(--success);
border-radius: 50%;
box-shadow: 0 0 4px var(--success);
}
/* Right Sidebar - Data */
.data-card {
background: var(--bg-panel);
border: 1px solid var(--border);
border-radius: 6px;
padding: 12px;
margin-bottom: 12px;
}
.data-card h4 {
font-size: 0.75rem;
text-transform: uppercase;
color: var(--text-muted);
margin-bottom: 8px;
display: flex;
justify-content: space-between;
}
.metric-value {
font-family: 'Space Mono', monospace;
font-size: 1.1rem;
color: var(--text-main);
}
.progress-bar {
height: 4px;
background: var(--border);
border-radius: 2px;
margin-top: 8px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width 0.5s ease;
}
.log-console {
font-family: 'Space Mono', monospace;
font-size: 0.7rem;
color: var(--text-muted);
height: 200px;
overflow-y: auto;
background: #000;
padding: 10px;
border-radius: 4px;
}
.log-entry {
margin-bottom: 4px;
border-left: 2px solid transparent;
padding-left: 6px;
}
.log-entry.info { border-color: var(--accent); color: #c7d2fe; }
.log-entry.success { border-color: var(--success); color: #d1fae5; }
/* Loading Animation */
.scanning-laser {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 2px;
background: var(--success);
box-shadow: 0 0 15px var(--success);
animation: scan 2s ease-in-out infinite;
display: none;
z-index: 10;
}
@keyframes scan {
0% { top: 0%; opacity: 0; }
10% { opacity: 1; }
90% { opacity: 1; }
100% { top: 100%; opacity: 0; }
}
/* Responsive */
@media (max-width: 1024px) {
main {
grid-template-columns: 250px 1fr;
}
.right-panel {
display: none;
}
}
@media (max-width: 768px) {
main {
grid-template-columns: 1fr;
display: block;
overflow-y: auto;
}
.panel {
height: auto;
min-height: 300px;
border-bottom: 1px solid var(--border);
}
}
</style>
</head>
<body>
<div class="bg-grid"></div>
<header>
<div class="logo">
<i class="fa-solid fa-cube"></i>
<span>SAM3 Reconstructor</span>
</div>
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link">Built with anycoder</a>
</header>
<main>
<!-- Left Panel: Controls -->
<aside class="panel">
<div class="panel-header">
<span>Input & Configuration</span>
<i class="fa-solid fa-sliders"></i>
</div>
<div class="panel-content">
<div class="upload-zone" id="dropZone">
<i class="fa-solid fa-cloud-arrow-up"></i>
<p><strong>Drop Video or Image</strong><br>or click to browse</p>
<input type="file" id="fileInput" hidden accept="image/*,video/*">
</div>
<div class="control-group">
<label class="control-label">Mesh Density</label>
<div class="slider-container">
<span style="font-size: 0.8rem; color:var(--text-muted)">Low</span>
<input type="range" min="1" max="100" value="75" class="slider">
<span style="font-size: 0.8rem; color:var(--text-muted)">High</span>
</div>
</div>
<div class="control-group">
<label class="control-label">Body Shape Precision</label>
<div class="setting-toggle active" onclick="toggleSetting(this)">
<span>SMPL-X Model</span>
<div class="toggle-switch"></div>
</div>
</div>
<div class="control-group">
<label class="control-label">Features</label>
<div class="setting-toggle active" onclick="toggleSetting(this)">
<span>Temporal Consistency</span>
<div class="toggle-switch"></div>
</div>
<div class="setting-toggle" onclick="toggleSetting(this)">
<span>Texture Projection</span>
<div class="toggle-switch"></div>
</div>
</div>
<button class="btn-primary" id="processBtn" onclick="startReconstruction()">
<i class="fa-solid fa-play"></i> Start Reconstruction
</button>
</div>
</aside>
<!-- Center Panel: Viewport -->
<section class="panel">
<div class="panel-header">
<span>3D Viewport</span>
<div style="display: flex; gap: 10px;">
<i class="fa-solid fa-expand" style="cursor: pointer; color: var(--text-muted);"></i>
<i class="fa-solid fa-camera" style="cursor: pointer; color: var(--text-muted);"></i>
</div>
</div>
<div class="viewport" id="viewport">
<div class="viewport-overlay">
<div class="badge"><i class="fa-solid fa-video"></i> Source: None</div>
<div class="badge"><i class="fa-solid fa-ruler-combined"></i> Scale: 1:1</div>
<div class="badge" id="fpsCounter">FPS: 0</div>
</div>
<div class="scene-container">
<div class="scanning-laser" id="laser"></div>
<div class="reconstruction-layer">
<!-- Placeholder for when no content is loaded -->
<div id="placeholder-text" style="text-align: center; color: var(--text-muted);">
<i class="fa-solid fa-cube" style="font-size: 4rem; margin-bottom: 20px; opacity: 0.2;"></i>
<p>Waiting for input...</p>
</div>
<!-- The 3D Model Representation -->
<div class="human-mesh" id="humanModel">
<div class="head"></div>
<div class="torso"></div>
<div class="arm-l"></div>
<div class="arm-r"></div>
<div class="leg-l"></div>
<div class="leg-r"></div>
</div>
</div>
</div>
</div>
</section>
<!-- Right Panel: Analytics -->
<aside class="panel right-panel">
<div class="panel-header">
<span>Analysis Data</span>
<i class="fa-solid fa-chart-pie"></i>
</div>
<div class="panel-content">
<div class="data-card">
<h4>Processing Status <span id="statusText">Idle</span></h4>
<div class="progress-bar">
<div class="progress-fill" id="mainProgress"></div>
</div>
</div>
<div class="data-card">
<h4>Detected Persons</h4>
<div class="metric-value" id="personCount">0</div>
</div>
<div class="data-card">
<h4>Shape Parameters (Betas)</h4>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-top: 8px;">
<div style="background:rgba(0,0,0,0.3); padding: 4px; border-radius: 4px; font-size: 0.7rem;">H: <span id="valH">0.00</span></div>
<div style="background:rgba(0,0,0,0.3); padding: 4px; border-radius: 4px; font-size: 0.7rem;">W: <span id="valW">0.00</span></div>
<div style="background:rgba(0,0,0,0.3); padding: 4px; border-radius: 4px; font-size: 0.7rem;">D: <span id="valD">0.00</span></div>
<div style="background:rgba(0,0,0,0.3); padding: 4px; border-radius: 4px; font-size: 0.7rem;">Pose: <span id="valP">0.00</span></div>
</div>
</div>
<div class="control-label" style="margin-top: 10px;">System Log</div>
<div class="log-console" id="consoleLog">
<div class="log-entry info">> System initialized</div>
<div class="log-entry info">> Ready for SAM3 input</div>
</div>
</div>
</aside>
</main>
<script>
// DOM Elements
const dropZone = document.getElementById('dropZone');
const fileInput = document.getElementById('fileInput');
const processBtn = document.getElementById('processBtn');
const placeholderText = document.getElementById('placeholder-text');
const humanModel = document.getElementById('humanModel');
const laser = document.getElementById('laser');
const mainProgress = document.getElementById('mainProgress');
const statusText = document.getElementById('statusText');
const consoleLog = document.getElementById('consoleLog');
const personCount = document.getElementById('personCount');
const fpsCounter = document.getElementById('fpsCounter');
// State
let isProcessing = false;
let animationFrameId;
// Event Listeners
dropZone.addEventListener('click', () => fileInput.click());
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.style.borderColor = 'var(--accent)';
dropZone.style.background = 'rgba(99, 102, 241, 0.1)';
});
dropZone.addEventListener('dragleave', (e) => {
e.preventDefault();
dropZone.style.borderColor = 'var(--border)';
dropZone.style.background = 'transparent';
});
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.style.borderColor = 'var(--border)';
dropZone.style.background = 'transparent';
if (e.dataTransfer.files.length > 0) {
handleFile(e.dataTransfer.files[0]);
}
});
fileInput.addEventListener('change', (e) => {
if (fileInput.files.length > 0) {
handleFile(fileInput.files[0]);
}
});
function toggleSetting(element) {
element.classList.toggle('active');
log(`Setting changed: ${element.querySelector('span').innerText} -> ${element.classList.contains('active')}`);
}
function handleFile(file) {
log(`File loaded: ${file.name}`, 'info');
dropZone.innerHTML = `<i class="fa-solid fa-check" style="color: var(--success)"></i><p><strong>${file.name}</strong><br>Ready to process</p>`;
processBtn.disabled = false;
}
function log(message, type = 'info') {
const entry = document.createElement('div');
entry.className = `log-entry ${type}`;
entry.innerText = `> ${message}`;
consoleLog.appendChild(entry);
consoleLog.scrollTop = consoleLog.scrollHeight;
}
function startReconstruction() {
if (isProcessing) return;
isProcessing = true;
// UI Updates
processBtn.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i> Processing...';
placeholderText.style.display = 'none';
humanModel.style.display = 'none'; // Hide first
laser.style.display = 'block';
statusText.innerText = "Analyzing...";
statusText.style.color = "var(--accent)";
log("Initializing SAM3 Model...", 'info');
// Simulation Timeline
let progress = 0;
const interval = setInterval(() => {
progress += 1;
mainProgress.style.width = `${progress}%`;
// Random data updates
updateRandomStats();
if (progress === 30) {
log("Segmenting foreground objects...", 'info');
statusText.innerText = "Segmentation";
}
if (progress === 60) {
log("Estimating SMPL-X parameters...", 'info');
statusText.innerText = "Shape Est.";
}
if (progress === 80) {
log("Generating mesh topology...", 'info');
statusText.innerText = "Meshing";
humanModel.style.display = 'block'; // Show model wireframe-ish
humanModel.style.opacity = '0.5';
}
if (progress >= 100) {
clearInterval(interval);
finishProcessing();
}
}, 50); // 5 seconds total simulation
}
function finishProcessing() {
isProcessing = false;
processBtn.innerHTML = '<i class="fa-solid fa-rotate-right"></i> Restart';
laser.style.display = 'none';
statusText.innerText = "Completed";
statusText.style.color = "var(--success)";
humanModel.style.opacity = '1';
log("Reconstruction complete.", 'success');
log("Scene rendered successfully.", 'success');
personCount.innerText = "1";
startFPSLoop();
spawnParticles();
}
function updateRandomStats() {
document.getElementById('valH').innerText = (Math.random() * 2 - 1).toFixed(2);
document.getElementById('valW').innerText = (Math.random() * 2 - 1).toFixed(2);
document.getElementById('valD').innerText = (Math.random() * 2 - 1).toFixed(2);
document.getElementById('valP').innerText = (Math.random()).toFixed(2);
}
function startFPSLoop() {
setInterval(() => {
fpsCounter.innerText = `FPS: ${Math.floor(Math.random() * 10 + 55)}`; // Fake 60fps
}, 500);
}
// Visual Flair: Spawn particles around the model
function spawnParticles() {
const container = document.querySelector('.scene-container');
setInterval(() => {
if (!isProcessing && document.getElementById('statusText').innerText === "Completed") {
const dot = document.createElement('div');
dot.classList.add('points');
// Random position around center
const angle = Math.random() * Math.PI * 2;
const radius = 100 + Math.random() * 50;
const x = Math.cos(angle) * radius;
const z = Math.sin(angle) * radius;
const y = (Math.random() - 0.5) * 300;
dot.style.transform = `translate3d(${x}px, ${y}px, ${z}px)`;
dot.style.left = '50%';
dot.style.top = '50%';
container.appendChild(dot);
// Animate and remove
const anim = dot.animate([
{ opacity: 0, transform: `translate3d(${x}px, ${y}px, ${z}px) scale(0)` },
{ opacity: 1, transform: `translate3d(${x}px, ${y}px, ${z}px) scale(1)`, offset: 0.1 },
{ opacity: 0, transform: `translate3d(${x}px, ${y - 50}px, ${z}px) scale(0)` }
], {
duration: 2000,
easing: 'ease-out'
});
anim.onfinish = () => dot.remove();
}
}, 100);
}
</script>
</body>
</html>