| <!DOCTYPE html> |
| <html lang="en"> |
|
|
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Sharp</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&display=swap" rel="stylesheet"> |
| <link rel="stylesheet" href="{{ url_for('static', path='css/styles.css') }}"> |
| <script type="importmap"> |
| { |
| "imports": { |
| "three": "https://esm.sh/three@0.164.0", |
| "@mkkellogg/gaussian-splats-3d": "https://esm.sh/@mkkellogg/gaussian-splats-3d@0.4.6" |
| } |
| } |
| </script> |
| </head> |
|
|
| <body> |
| <canvas id="particleCanvas"></canvas> |
|
|
| <button class="theme-toggle" id="themeToggle" aria-label="Toggle theme"> |
| <svg class="sun-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" |
| stroke-linejoin="round"> |
| <circle cx="12" cy="12" r="5" /> |
| <line x1="12" y1="1" x2="12" y2="3" /> |
| <line x1="12" y1="21" x2="12" y2="23" /> |
| <line x1="4.22" y1="4.22" x2="5.64" y2="5.64" /> |
| <line x1="18.36" y1="18.36" x2="19.78" y2="19.78" /> |
| <line x1="1" y1="12" x2="3" y2="12" /> |
| <line x1="21" y1="12" x2="23" y2="12" /> |
| <line x1="4.22" y1="19.78" x2="5.64" y2="18.36" /> |
| <line x1="18.36" y1="5.64" x2="19.78" y2="4.22" /> |
| </svg> |
| <svg class="moon-icon" viewBox="0 0 24 24" fill="none" stroke-width="2" stroke-linecap="round" |
| stroke-linejoin="round"> |
| <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" /> |
| </svg> |
| </button> |
|
|
| <div class="app-container"> |
| <header class="header"> |
| <h1 class="logo">Sharp</h1> |
| <p class="tagline">Transform images into Gaussian Splats</p> |
| </header> |
|
|
| <div class="card"> |
| <form id="uploadForm"> |
| <div class="upload-zone" id="dropZone"> |
| <div class="upload-icon"> |
| <svg viewBox="0 0 24 24" fill="none" stroke-width="1.5" stroke-linecap="round" |
| stroke-linejoin="round"> |
| <path d="M12 16V4m0 0l-4 4m4-4l4 4" /> |
| <path d="M3 20h18" /> |
| </svg> |
| </div> |
| <div class="upload-text"> |
| <h3>Drop your image here</h3> |
| <p>or click to browse</p> |
| </div> |
| <input type="file" id="fileInput" name="files" accept="image/*" style="display: none"> |
| </div> |
|
|
| <div class="file-list" id="fileList"></div> |
|
|
| <button type="submit" class="submit-btn" id="submitBtn"> |
| <span> |
| <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" |
| stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M12 3v18M3 12l9 9 9-9" /> |
| </svg> |
| Generate |
| </span> |
| </button> |
| </form> |
|
|
| <div class="loader-container" id="loaderContainer"> |
| <div class="loader"></div> |
| <p class="loader-text">Generating Gaussian Splats...</p> |
| <p class="loader-subtext">This may take a moment</p> |
| </div> |
|
|
| <div class="results" id="results"></div> |
| </div> |
|
|
| |
| <div class="viewer-container" id="viewerContainer"> |
| <button class="back-btn" id="backBtn"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" |
| stroke-linejoin="round"> |
| <path d="M19 12H5M12 19l-7-7 7-7" /> |
| </svg> |
| Back to Upload |
| </button> |
|
|
| <div class="viewer-header"> |
| <div class="viewer-title"> |
| <h3>3D Gaussian Splat Viewer</h3> |
| <span class="file-badge" id="viewerFilename">output.ply</span> |
| </div> |
| <div class="viewer-actions"> |
| <button class="viewer-btn" id="resetViewBtn"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" |
| stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8" /> |
| <path d="M3 3v5h5" /> |
| </svg> |
| Reset View |
| </button> |
| <button class="viewer-btn primary" id="downloadBtn"> |
| <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" |
| stroke-linecap="round" stroke-linejoin="round"> |
| <path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" /> |
| <polyline points="7 10 12 15 17 10" /> |
| <line x1="12" y1="15" x2="12" y2="3" /> |
| </svg> |
| Download PLY |
| </button> |
| </div> |
| </div> |
|
|
| <div class="viewer-canvas-container" id="viewerCanvasContainer"> |
| <div class="viewer-controls-hint" id="controlsHint"> |
| 🖱️ Left click + drag to rotate • Scroll to zoom • Right click + drag to pan |
| </div> |
| </div> |
|
|
| <div class="viewer-footer"> |
| <span>Powered by <a href="https://threejs.org/" target="_blank" rel="noopener">Three.js</a> & <a |
| href="https://github.com/mkkellogg/GaussianSplats3D" target="_blank" rel="noopener">Gaussian |
| Splats 3D</a></span> |
| </div> |
| </div> |
|
|
| <footer class="footer"> |
| <p><a href="https://apple.github.io/ml-sharp/" target="_blank" rel="noopener">Mescheder et al., 2025</a> • |
| Sharp: Monocular View Synthesis in Less Than a Second</p> |
| </footer> |
| </div> |
|
|
| |
| <script src="{{ url_for('static', path='js/main.js') }}"></script> |
|
|
| |
| <script type="module" src="{{ url_for('static', path='js/viewer.js') }}"></script> |
| </body> |
|
|
| </html> |