| <!DOCTYPE html> |
| <html lang="zh-CN"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Huhb3D Synthetic Data Generator - Demo</title> |
| <style> |
| *{margin:0;padding:0;box-sizing:border-box} |
| body{background:#0e1117;color:#e0e0e0;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,sans-serif;line-height:1.6} |
| .container{max-width:1200px;margin:0 auto;padding:20px} |
| h1{font-size:1.8em;margin-bottom:4px} |
| .subtitle{color:#aaa;margin-bottom:16px} |
| .warning{background:#332b00;border:1px solid #665200;border-radius:8px;padding:12px 16px;margin-bottom:20px;color:#ffc107;font-size:0.9em} |
| .warning a{color:#4fc3f7} |
| .section-title{font-size:1.3em;font-weight:600;margin:24px 0 12px;padding-bottom:8px;border-bottom:1px solid #333} |
| .metrics{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:24px} |
| .metric{background:#1a1a2e;border-radius:8px;padding:16px;text-align:center} |
| .metric .val{font-size:2em;font-weight:700} |
| .metric .lbl{color:#aaa;font-size:0.9em} |
| .slider-row{display:flex;align-items:center;gap:12px;margin-bottom:16px} |
| .slider-row label{color:#ccc;font-weight:600;font-size:14px;white-space:nowrap} |
| .slider-row input[type=range]{flex:1;accent-color:#4fc3f7} |
| .img-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:16px} |
| .img-cell{text-align:center} |
| .img-cell .img-title{color:#ccc;font-weight:600;margin-bottom:8px;font-size:14px} |
| .img-wrap{background:#1a1a2e;border-radius:6px;overflow:hidden;aspect-ratio:4/3;display:flex;align-items:center;justify-content:center} |
| .img-wrap img{max-width:100%;max-height:100%;object-fit:contain;display:block} |
| .img-wrap .placeholder{color:#888;font-size:13px;padding:20px} |
| .tabs{display:flex;gap:4px;margin:16px 0 0;border-bottom:2px solid #333} |
| .tab{padding:8px 16px;cursor:pointer;border-radius:6px 6px 0 0;background:#1a1a2e;color:#aaa;font-size:0.85em;transition:all .2s} |
| .tab:hover{color:#fff} |
| .tab.active{background:#2d2d44;color:#fff;border-bottom:2px solid #4fc3f7;margin-bottom:-2px} |
| .tab-content{display:none;background:#1a1a2e;border-radius:0 0 8px 8px;padding:16px;overflow-x:auto} |
| .tab-content.active{display:block} |
| .tab-content pre{color:#ccc;font-size:0.8em;white-space:pre-wrap;word-break:break-all} |
| .legend{background:#1a1a2e;border-radius:8px;padding:16px;margin-top:16px} |
| .legend pre{color:#ccc;font-size:0.8em} |
| .deploy{background:#1a1a2e;border-radius:8px;padding:20px;margin-top:16px} |
| .deploy h3{margin-bottom:12px;color:#4fc3f7} |
| .deploy code{background:#0e1117;padding:2px 6px;border-radius:4px;font-size:0.85em;color:#81c784} |
| .deploy pre{background:#0e1117;padding:12px;border-radius:6px;overflow-x:auto;margin:8px 0;color:#ccc;font-size:0.8em} |
| .footer{text-align:center;color:#666;font-size:0.8em;margin-top:32px;padding-top:16px;border-top:1px solid #333} |
| </style> |
| </head> |
| <body> |
| <div class="container"> |
| <h1>🤖 Huhb3D Synthetic Data Generator</h1> |
| <p class="subtitle">面向机器人视觉训练的合成数据生成器 — Demo 展示</p> |
|
|
| <div class="warning"> |
| ⚠️ <strong>在线 Demo 模式</strong> — 当前展示预生成的样例数据。要使用自己的 CAD 模型生成数据,请在本地部署并编译 C++ 渲染引擎。<br> |
| 📦 GitHub: <a href="https://github.com/AIminminAI/Huhb3D-Viewer" target="_blank">AIminminAI/Huhb3D-Viewer</a> | |
| 📦 Gitee: <a href="https://gitee.com/aiminminai/Huhb3D-Viewer" target="_blank">aiminminai/Huhb3D-Viewer</a> |
| </div> |
|
|
| <div class="section-title">📊 Demo 数据概览</div> |
| <div class="metrics"> |
| <div class="metric"><div class="val" style="color:#4fc3f7">6</div><div class="lbl">RGB 图像</div></div> |
| <div class="metric"><div class="val" style="color:#81c784">6</div><div class="lbl">语义 Mask</div></div> |
| <div class="metric"><div class="val" style="color:#ffb74d">0</div><div class="lbl">深度图</div></div> |
| <div class="metric"><div class="val" style="color:#e57373">✅</div><div class="lbl">6DoF 位姿</div></div> |
| </div> |
|
|
| <div class="section-title">🖼️ 渲染效果展示</div> |
| <div class="slider-row"> |
| <label>选择视角: <span id="idxLabel">1</span> / 6</label> |
| <input type="range" id="viewSlider" min="0" max="5" value="0"> |
| </div> |
| <div class="img-grid"> |
| <div class="img-cell"> |
| <div class="img-title">📷 RGB 渲染图</div> |
| <div class="img-wrap"><img id="rgbImg" src="" alt="RGB"></div> |
| </div> |
| <div class="img-cell"> |
| <div class="img-title">🏷️ 语义分割 Mask</div> |
| <div class="img-wrap"><img id="maskImg" src="" alt="Mask"></div> |
| </div> |
| <div class="img-cell"> |
| <div class="img-title">📏 深度图</div> |
| <div class="img-wrap"><div class="placeholder">深度图需在本地编译 C++ 引擎后生成</div></div> |
| </div> |
| </div> |
|
|
| <div class="section-title">📐 6DoF & BOP 格式数据</div> |
| <div class="tabs"> |
| <div class="tab active" data-tab="gt6dof">🎯 6DoF Ground Truth</div> |
| <div class="tab" data-tab="sceneCam">📷 scene_camera.json</div> |
| <div class="tab" data-tab="sceneGt">📋 scene_gt.json</div> |
| <div class="tab" data-tab="camPoses">🎥 camera_poses.json</div> |
| </div> |
| <div class="tab-content active" id="tab-gt6dof"><pre id="json-gt6dof">Loading...</pre></div> |
| <div class="tab-content" id="tab-sceneCam"><pre id="json-sceneCam">Loading...</pre></div> |
| <div class="tab-content" id="tab-sceneGt"><pre id="json-sceneGt">Loading...</pre></div> |
| <div class="tab-content" id="tab-camPoses"><pre id="json-camPoses">Loading...</pre></div> |
|
|
| <details class="legend" style="margin-top:16px"> |
| <summary style="cursor:pointer;color:#4fc3f7;font-weight:600">🏷️ 语义标签分类</summary> |
| <pre> |
| # Category -> (R, G, B) in 0-255 range |
| 0 FreeSurface 127 127 127 |
| 1 HorizontalPlane 0 0 255 |
| 2 LateralPlane_X 0 255 0 |
| 3 LateralPlane_Z 255 0 0 |
| 4 NearHorizontal 255 255 0 |
| 5 NearLateral_X 255 0 255 |
| 6 NearLateral_Z 0 255 255 |
| 7 Degenerate 255 127 0 |
| 8 Reserved1 127 0 255 |
| 9 Reserved2 0 127 255 |
| </pre> |
| </details> |
|
|
| <div class="section-title">🔧 本地部署(解锁完整功能)</div> |
| <div class="deploy"> |
| <h3>要使用自己的 CAD 模型生成数据,请按以下步骤本地部署:</h3> |
| <p>1. 克隆仓库:<code>git clone https://github.com/AIminminAI/Huhb3D-Viewer</code></p> |
| <p>2. 安装 Python 依赖:<code>pip install streamlit Pillow numpy opencv-python</code></p> |
| <p>3. 编译 C++ 渲染引擎:需要 Visual Studio 2019+ (Windows) 或 GCC (Linux)</p> |
| <p>4. 启动 Web UI:<code>streamlit run app.py --server.port 8501</code></p> |
| <h3 style="margin-top:12px">Docker 部署(最省心):</h3> |
| <pre>docker build -t huhb3d-synthetic . |
| docker run -p 7860:7860 huhb3d-synthetic</pre> |
| <p>详见 <a href="https://github.com/AIminminAI/Huhb3D-Viewer" style="color:#4fc3f7">GitHub README</a> 获取完整部署指南。</p> |
| </div> |
|
|
| <div class="footer">Huhb3D Synthetic Data Generator v2.0 | AGPL-3.0 License</div> |
| </div> |
|
|
| <script> |
| var rgbFiles = [ |
| "demo_data/rgb/frame_0001.png", |
| "demo_data/rgb/frame_0010.png", |
| "demo_data/rgb/frame_0025.png", |
| "demo_data/rgb/frame_0050.png", |
| "demo_data/rgb/frame_0075.png", |
| "demo_data/rgb/frame_0100.png" |
| ]; |
| var maskFiles = [ |
| "demo_data/mask/mask_0001.png", |
| "demo_data/mask/mask_0010.png", |
| "demo_data/mask/mask_0025.png", |
| "demo_data/mask/mask_0050.png", |
| "demo_data/mask/mask_0075.png", |
| "demo_data/mask/mask_0100.png" |
| ]; |
| |
| var slider = document.getElementById('viewSlider'); |
| var label = document.getElementById('idxLabel'); |
| var rgbImg = document.getElementById('rgbImg'); |
| var maskImg = document.getElementById('maskImg'); |
| |
| function updateView(idx) { |
| label.textContent = idx + 1; |
| rgbImg.src = rgbFiles[idx]; |
| maskImg.src = maskFiles[idx]; |
| } |
| |
| slider.addEventListener('input', function() { |
| updateView(parseInt(this.value)); |
| }); |
| |
| updateView(0); |
| |
| document.querySelectorAll('.tab').forEach(function(tab) { |
| tab.addEventListener('click', function() { |
| document.querySelectorAll('.tab').forEach(function(t) { t.classList.remove('active'); }); |
| document.querySelectorAll('.tab-content').forEach(function(c) { c.classList.remove('active'); }); |
| this.classList.add('active'); |
| document.getElementById('tab-' + this.dataset.tab).classList.add('active'); |
| }); |
| }); |
| |
| var jsonFiles = { |
| 'gt6dof': 'demo_data/gt_6dof.json', |
| 'sceneCam': 'demo_data/scene_camera.json', |
| 'sceneGt': 'demo_data/scene_gt.json', |
| 'camPoses': 'demo_data/camera_poses.json' |
| }; |
| |
| Object.keys(jsonFiles).forEach(function(key) { |
| fetch(jsonFiles[key]) |
| .then(function(r) { return r.json(); }) |
| .then(function(data) { |
| document.getElementById('json-' + key).textContent = JSON.stringify(data, null, 2); |
| }) |
| .catch(function() { |
| document.getElementById('json-' + key).textContent = '数据加载失败'; |
| }); |
| }); |
| </script> |
| </body> |
| </html> |
|
|