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 &amp; 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>