找到
1
篇与
体素大小
相关的结果
-
使用 Python NumPy 原生代码实现点云的体素下采样 在 3D 数据处理领域,点云是一种重要的空间信息表示形式,用于捕捉物体和环境的几何形状。然而,点云数据通常非常密集,包含数百万甚至更多的点,这对存储、处理和可视化都带来了挑战。为了解决这个问题,我们需要对点云进行下采样,以减少点的数量,同时尽量保留数据的整体结构。体素下采样(Voxel Downsampling)是一种高效的下采样方法,它通过将点云划分到三维网格(体素)中并对每个体素内的点进行平均来实现这一目标。 什么是体素下采样? 此部分内容需要付费后才能阅读 您当前未登录,游客身份购买的内容仅在当前浏览器生效 (7天)。 清除Cookie或更换设备后需重新购买。 为获得永久阅读权限, 建议注册账户 后购买。 支付 4.99 元阅读 请使用支付宝扫描二维码支付 金额:4.99 元 二维码2小时内有效,支付成功后页面将自动刷新 if(typeof payit_generate_qr === "undefined") { function payit_generate_qr(id, url, cid, price) { var container = document.getElementById(id); var qrContainer = container.querySelector(".payit-qrcode-container"); var qrCodeDiv = container.querySelector(".payit-qrcode"); var btn = container.querySelector(".payit-button"); btn.disabled = true; btn.innerText = "二维码生成中..."; var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { try { var res = JSON.parse(xhr.responseText); if(res.code === 0 && res.qr_code) { qrContainer.style.display = "block"; container.querySelector(".payit-mask").style.display = "none"; new QRCode(qrCodeDiv, { text: res.qr_code, width: 150, height: 150 }); payit_check_status(id, "https://www.hubtools.cn/payit/check", res.out_trade_no); } else { alert("二维码生成失败: " + (res.msg || "未知错误")); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } catch (e) { alert("从服务器获取数据时出错。"); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } else { alert("请求服务器失败。"); btn.disabled = false; btn.innerText = "支付 " + price + " 元阅读"; } } }; xhr.send("cid=" + cid + "&price=" + price); } } if(typeof set_payit_cookie === "undefined") { function set_payit_cookie(name, value, days) { var expires = ""; if (days) { var date = new Date(); date.setTime(date.getTime() + (days*24*60*60*1000)); expires = "; expires=" + date.toUTCString(); } document.cookie = name + "=" + (value || "") + expires + "; path=/"; } } if(typeof payit_check_status === "undefined") { function payit_check_status(id, url, order_id) { var interval = setInterval(function() { var xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function() { if (xhr.readyState === 4 && xhr.status === 200) { try { var res = JSON.parse(xhr.responseText); if (res.code === 0) { clearInterval(interval); // 如果是游客,前端设置cookie if (res.token) { var cookieName = "payit_cid_" + res.cid; set_payit_cookie(cookieName, res.token, res.expire); } document.getElementById(id).innerHTML = "支付成功,正在刷新页面..."; setTimeout(function() { location.reload(); }, 200); } } catch (e) { /* 支付未成功,不处理 */ } } }; xhr.send("out_trade_no=" + order_id); }, 3000); } } .payit-wrapper { border: 2px dashed #e67e22; background-color: #fdf5ee; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; } .payit-wrapper .payit-guest-notice { font-size: 13px; color: #555; background-color: rgba(0,0,0,0.03); border: 1px solid rgba(0,0,0,0.05); padding: 10px; margin: 15px auto; border-radius: 5px; max-width: 95%; line-height: 1.6; } .payit-wrapper .payit-guest-notice p { margin: 5px 0; } .payit-wrapper .payit-guest-notice a { color: #e67e22; font-weight: bold; text-decoration: none; } .payit-wrapper .payit-guest-notice a:hover { text-decoration: underline; } .payit-mask .payit-notice { font-size: 18px; color: #e67e22; font-weight: bold; margin-bottom: 15px; display: flex; align-items: center; justify-content: center; } .payit-mask .payit-button { background-color: #e67e22; color: #ffffff; border: none; padding: 12px 25px; font-size: 16px; cursor: pointer; border-radius: 5px; transition: opacity 0.2s; } .payit-mask .payit-button:hover { opacity: 0.9; } .payit-mask .payit-button:disabled { opacity: 0.6; cursor: not-allowed; } .payit-qrcode-container { color: #333; } .payit-qrcode-container p { margin: 10px 0; } .payit-qrcode { width: 150px; height: 150px; margin: 10px auto; padding: 5px; background: white; border: 1px solid #ddd; border-radius: 3px;} 代码实现 以下是一个完整的 Python 脚本,使用 NumPy 实现点云的体素下采样。代码简洁高效,适用于大多数基本的点云处理需求。 import numpy as np from collections import defaultdict def read_point_cloud(file_path): """读取点云文件,假设每行是一个点的xyz坐标,可能包含其他属性""" points = [] with open(file_path, 'r') as f: for line in f: parts = line.strip().split() if len(parts) >= 3: # 至少包含xyz三个坐标 x, y, z = map(float, parts[:3]) points.append([x, y, z]) return np.array(points) def voxel_downsample(points, voxel_size): """体素下采样""" # 创建体素网格 voxel_grid = defaultdict(list) # 计算每个点所在的体素 for point in points: voxel_coord = tuple((point // voxel_size).astype(int)) voxel_grid[voxel_coord].append(point) # 对每个体素内的点取平均 downsampled_points = [] for voxel_coord, voxel_points in voxel_grid.items(): if voxel_points: avg_point = np.mean(voxel_points, axis=0) downsampled_points.append(avg_point) return np.array(downsampled_points) def write_point_cloud(file_path, points): """将点云写入文件""" with open(file_path, 'w') as f: for point in points: f.write(f"{point[0]} {point[1]} {point[2]}\n") def main(): # 配置参数 input_file = "test1_pointcloud - Cloud.subsampled.txt" # 输入点云文件 output_file = "downsampled_test1_pointcloud - Cloud.subsampled.txt" # 输出点云文件 voxel_size = 1.2 # 体素大小,根据你的点云尺度调整 # 读取点云 points = read_point_cloud(input_file) print(f"原始点云数量: {len(points)}") # 体素下采样 downsampled_points = voxel_downsample(points, voxel_size) print(f"下采样后点云数量: {len(downsampled_points)}") # 保存下采样后的点云 write_point_cloud(output_file, downsampled_points) print(f"下采样后的点云已保存到: {output_file}") if __name__ == "__main__": main()体素大小的选择 体素大小(voxel_size)是下采样的关键参数,直接影响结果: 较大的体素大小:会导致更激进的下采样,点数减少更多,但可能会丢失细节。 较小的体素大小:保留更多细节,但下采样后的点云仍然较大。 选择合适的体素大小需要根据点云的尺度以及应用需求。例如,对于建筑扫描,1 厘米的体素大小可能合适;而对于室外大场景,1 米的体素大小可能更适合。 效果展示 左边是原始的点云,右边是体素下采样之后的点云。 下采样前后的对比图片