Skip to content

Commit a05cf88

Browse files
committed
.
1 parent f4e5a3c commit a05cf88

File tree

7 files changed

+1810
-279
lines changed

7 files changed

+1810
-279
lines changed
3.66 MB
Binary file not shown.

public/EgoHumanoid/assets/D.png

3.87 KB
Loading
29.6 KB
Loading

public/EgoHumanoid/index.html

Lines changed: 491 additions & 127 deletions
Large diffs are not rendered by default.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
"""
2+
点云降采样脚本
3+
使用 Open3D 对 pointcloud.ply 进行体素降采样(Voxel Downsampling)
4+
"""
5+
6+
import argparse
7+
import os
8+
import open3d as o3d
9+
10+
11+
def downsample(input_path, output_path, voxel_size):
12+
"""
13+
对点云进行体素降采样
14+
15+
参数:
16+
input_path: 输入点云文件路径
17+
output_path: 输出点云文件路径
18+
voxel_size: 体素大小,越大降采样越多(单位与点云坐标一致)
19+
"""
20+
print(f"读取点云: {input_path}")
21+
pcd = o3d.io.read_point_cloud(input_path)
22+
original_count = len(pcd.points)
23+
print(f"原始点数: {original_count:,}")
24+
25+
print(f"体素大小: {voxel_size}")
26+
pcd_down = pcd.voxel_down_sample(voxel_size=voxel_size)
27+
downsampled_count = len(pcd_down.points)
28+
ratio = downsampled_count / original_count * 100
29+
30+
print(f"降采样后点数: {downsampled_count:,} ({ratio:.1f}%)")
31+
print(f"减少了: {original_count - downsampled_count:,} 个点")
32+
33+
o3d.io.write_point_cloud(output_path, pcd_down, write_ascii=False)
34+
35+
input_size = os.path.getsize(input_path) / (1024 * 1024)
36+
output_size = os.path.getsize(output_path) / (1024 * 1024)
37+
print(f"文件大小: {input_size:.1f}MB -> {output_size:.1f}MB")
38+
print(f"保存至: {output_path}")
39+
40+
41+
if __name__ == "__main__":
42+
parser = argparse.ArgumentParser(description="点云降采样工具")
43+
parser.add_argument(
44+
"-i", "--input",
45+
default="pointcloud.ply",
46+
help="输入点云文件路径 (默认: pointcloud.ply)",
47+
)
48+
parser.add_argument(
49+
"-o", "--output",
50+
default="pointcloud_downsampled.ply",
51+
help="输出点云文件路径 (默认: pointcloud_downsampled.ply)",
52+
)
53+
parser.add_argument(
54+
"-v", "--voxel-size",
55+
type=float,
56+
default=0.01,
57+
help="体素大小,越大降采样越多 (默认: 0.01)",
58+
)
59+
args = parser.parse_args()
60+
61+
downsample(args.input, args.output, args.voxel_size)

public/EgoHumanoid/scripts.js

Lines changed: 207 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -61,18 +61,41 @@ function copyCitation() {
6161
setTimeout(() => btn.textContent = 'Copy', 2000);
6262
}
6363

64-
// Charts
65-
const chartColors = { robot: '#4A90D9', cotrain: '#00D4AA', grid: 'rgba(255,255,255,0.05)' };
64+
// Charts - Updated with blue color scheme
65+
const chartColors = {
66+
robot: '#2563EB', // Primary blue
67+
cotrain: '#10B981', // Accent green
68+
grid: 'rgba(37,99,235,0.08)'
69+
};
70+
6671
const chartOptions = {
6772
responsive: true,
6873
maintainAspectRatio: false,
6974
plugins: {
7075
legend: { display: false },
71-
tooltip: { backgroundColor: 'rgba(10,10,15,0.9)', titleColor: '#fff', bodyColor: '#8B8B9E', borderColor: 'rgba(255,255,255,0.1)', borderWidth: 1, padding: 12, cornerRadius: 8 }
76+
tooltip: {
77+
backgroundColor: 'rgba(30,41,59,0.95)',
78+
titleColor: '#fff',
79+
bodyColor: '#94A3B8',
80+
borderColor: 'rgba(37,99,235,0.2)',
81+
borderWidth: 1,
82+
padding: 12,
83+
cornerRadius: 8
84+
}
7285
},
7386
scales: {
74-
x: { grid: { color: chartColors.grid }, ticks: { color: '#8B8B9E' } },
75-
y: { grid: { color: chartColors.grid }, ticks: { color: '#8B8B9E' }, min: 0, max: 100 }
87+
x: {
88+
grid: { color: chartColors.grid },
89+
ticks: { color: '#64748B' },
90+
border: { color: 'rgba(37,99,235,0.15)' }
91+
},
92+
y: {
93+
grid: { color: chartColors.grid },
94+
ticks: { color: '#64748B' },
95+
min: 0,
96+
max: 100,
97+
border: { color: 'rgba(37,99,235,0.15)' }
98+
}
7699
}
77100
};
78101

@@ -83,8 +106,8 @@ if (inDomainCtx) {
83106
data: {
84107
labels: ['Pillow', 'Trash', 'Toy', 'Cart', 'Average'],
85108
datasets: [
86-
{ label: 'Robot-only', data: [60, 61.3, 47.5, 42.5, 58.8], backgroundColor: chartColors.robot, borderRadius: 6 },
87-
{ label: 'Co-training', data: [85, 97.5, 70, 42.5, 78.4], backgroundColor: chartColors.cotrain, borderRadius: 6 }
109+
{ label: 'Robot-only', data: [60, 85, 47.5, 42.5, 58.8], backgroundColor: chartColors.robot, borderRadius: 6 },
110+
{ label: 'Co-training', data: [85, 97.5, 61.3, 70, 78.4], backgroundColor: chartColors.cotrain, borderRadius: 6 }
88111
]
89112
},
90113
options: chartOptions
@@ -115,8 +138,183 @@ document.querySelectorAll('a[href^="#"]').forEach(anchor => {
115138
});
116139
});
117140

118-
// Nav background
141+
// Nav background - transparent on hero, solid when scrolled
119142
const nav = document.querySelector('.nav');
120143
window.addEventListener('scroll', () => {
121-
nav.style.background = window.scrollY > 50 ? 'rgba(10, 10, 15, 0.95)' : 'rgba(10, 10, 15, 0.85)';
144+
if (window.scrollY > 80) {
145+
nav.classList.add('scrolled');
146+
} else {
147+
nav.classList.remove('scrolled');
148+
}
149+
});
150+
151+
// Side Navigation - Active section tracking
152+
const sideNavItems = document.querySelectorAll('.side-nav-item');
153+
const sections = document.querySelectorAll('section[id], .hero[id]');
154+
155+
const sectionObserver = new IntersectionObserver((entries) => {
156+
entries.forEach(entry => {
157+
if (entry.isIntersecting) {
158+
const id = entry.target.getAttribute('id');
159+
sideNavItems.forEach(item => {
160+
item.classList.remove('active');
161+
if (item.getAttribute('data-section') === id) {
162+
item.classList.add('active');
163+
}
164+
});
165+
}
166+
});
167+
}, {
168+
threshold: 0.2,
169+
rootMargin: '-10% 0px -70% 0px'
170+
});
171+
172+
sections.forEach(section => sectionObserver.observe(section));
173+
174+
// Side nav smooth scroll
175+
sideNavItems.forEach(item => {
176+
item.addEventListener('click', function(e) {
177+
e.preventDefault();
178+
const targetId = this.getAttribute('href');
179+
const target = document.querySelector(targetId);
180+
if (target) {
181+
target.scrollIntoView({ behavior: 'smooth', block: 'start' });
182+
}
183+
});
122184
});
185+
186+
// Scaling Analysis Charts - Data from scaling.py
187+
const scalingColors = {
188+
ratio_1_2: '#3A8DC1', // Blue
189+
ratio_1_1: '#5AAE61', // Green
190+
ratio_2_1: '#E5A835' // Orange
191+
};
192+
193+
// Raw data from scaling.py
194+
const scalingRawData = {
195+
pillow: { '1:2': [0, 65, 90, 97.5], '1:1': [0, 77.5, 85, 80], '2:1': [0, 82.5, 85, 80] },
196+
trash: { '1:2': [55, 80, 92.5, 87.5], '1:1': [55, 80, 95, 82.5], '2:1': [55, 95, 87.5, 85] },
197+
toy: { '1:2': [37.5, 35, 68.75, 58.75], '1:1': [37.5, 41.25, 58.75, 71.25], '2:1': [37.5, 41.25, 61.25, 78.75] },
198+
cart: { '1:2': [31.25, 26.25, 38.75, 50], '1:1': [31.25, 40, 58.75, 52.5], '2:1': [31.25, 67.5, 41.25, 65] }
199+
};
200+
201+
// Calculate average for each ratio
202+
function calcAverage(ratio) {
203+
return [0, 1, 2, 3].map(i =>
204+
(scalingRawData.pillow[ratio][i] + scalingRawData.trash[ratio][i] + scalingRawData.toy[ratio][i] + scalingRawData.cart[ratio][i]) / 4
205+
);
206+
}
207+
208+
scalingRawData.average = {
209+
'1:2': calcAverage('1:2'),
210+
'1:1': calcAverage('1:1'),
211+
'2:1': calcAverage('2:1')
212+
};
213+
214+
const scalingLabels = ['0', '100', '200', '300'];
215+
216+
const scalingChartOptions = {
217+
responsive: true,
218+
maintainAspectRatio: true,
219+
aspectRatio: 1,
220+
plugins: {
221+
legend: { display: false },
222+
tooltip: {
223+
backgroundColor: 'rgba(30, 41, 59, 0.95)',
224+
titleColor: '#fff',
225+
bodyColor: '#94A3B8',
226+
borderColor: 'rgba(37, 99, 235, 0.2)',
227+
borderWidth: 1,
228+
padding: 12,
229+
cornerRadius: 8
230+
}
231+
},
232+
scales: {
233+
x: {
234+
grid: { color: 'rgba(0, 0, 0, 0.06)' },
235+
ticks: { color: '#666666', font: { size: 12 } },
236+
border: { color: '#CCCCCC' },
237+
title: { display: true, text: 'Human Demos', color: '#555555', font: { size: 13, weight: 'bold' } }
238+
},
239+
y: {
240+
grid: { color: 'rgba(0, 0, 0, 0.06)' },
241+
ticks: { color: '#666666', font: { size: 12 } },
242+
min: 0,
243+
max: 100,
244+
border: { color: '#CCCCCC' }
245+
}
246+
}
247+
};
248+
249+
function createScalingChart(canvasId, taskKey) {
250+
const ctx = document.getElementById(canvasId);
251+
if (!ctx) return null;
252+
253+
const taskData = scalingRawData[taskKey];
254+
255+
return new Chart(ctx, {
256+
type: 'line',
257+
data: {
258+
labels: scalingLabels,
259+
datasets: [
260+
{
261+
label: 'Robot:Human 1:2',
262+
data: taskData['1:2'],
263+
borderColor: scalingColors.ratio_1_2,
264+
backgroundColor: scalingColors.ratio_1_2 + '20',
265+
fill: false,
266+
tension: 0.3,
267+
pointRadius: 6,
268+
pointBackgroundColor: scalingColors.ratio_1_2,
269+
pointBorderColor: '#FFFFFF',
270+
pointBorderWidth: 2,
271+
pointHoverRadius: 8,
272+
borderWidth: 3
273+
},
274+
{
275+
label: 'Robot:Human 1:1',
276+
data: taskData['1:1'],
277+
borderColor: scalingColors.ratio_1_1,
278+
backgroundColor: scalingColors.ratio_1_1 + '20',
279+
fill: false,
280+
tension: 0.3,
281+
pointRadius: 6,
282+
pointBackgroundColor: scalingColors.ratio_1_1,
283+
pointBorderColor: '#FFFFFF',
284+
pointBorderWidth: 2,
285+
pointHoverRadius: 8,
286+
borderWidth: 3
287+
},
288+
{
289+
label: 'Robot:Human 2:1',
290+
data: taskData['2:1'],
291+
borderColor: scalingColors.ratio_2_1,
292+
backgroundColor: scalingColors.ratio_2_1 + '20',
293+
fill: false,
294+
tension: 0.3,
295+
pointRadius: 6,
296+
pointBackgroundColor: scalingColors.ratio_2_1,
297+
pointBorderColor: '#FFFFFF',
298+
pointBorderWidth: 2,
299+
pointHoverRadius: 8,
300+
borderWidth: 3
301+
}
302+
]
303+
},
304+
options: scalingChartOptions
305+
});
306+
}
307+
308+
let scalingCharts = {};
309+
310+
function initScalingCharts() {
311+
// Create all 5 charts
312+
scalingCharts.average = createScalingChart('scalingAverage', 'average');
313+
scalingCharts.pillow = createScalingChart('scalingPillow', 'pillow');
314+
scalingCharts.trash = createScalingChart('scalingTrash', 'trash');
315+
scalingCharts.toy = createScalingChart('scalingToy', 'toy');
316+
scalingCharts.cart = createScalingChart('scalingCart', 'cart');
317+
}
318+
319+
// Initialize charts
320+
initScalingCharts();

0 commit comments

Comments
 (0)