File size: 8,928 Bytes
891aed9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | <!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>
|