点云

pcd 文件

参考:PCL:点云数据(*.pcd)文件格式详解

二进制格式

二进制格式的 pcd 文件读取

  • 读取 header --> 通过 parsePCDHeader 读取到 header 中每个字段的值
  • 计算每个字段的偏移量 --> 通过 header.size 计算 生成 offset
  • 将转化为 arraybuffer 后的二进制数据,导入到 DataView 通过遍历生成 position, normal, color 数据

读取后的 header

{
    "data": "binary",
    "headerLen": 216,
    "str": "\nVERSION 0.7\nFIELDS x y z intensity label timestamp\nSIZE 4 4 4 1 1 8\nTYPE F F F U U U\nCOUNT 1 1 1 1 1 1\nWIDTH 54513\nHEIGHT 1\nVIEWPOINT 0 0 0 1 0 0 0\nPOINTS 54513\nDATA binary\n",
    "version": 0.7,
    "fields": [ // 每个字段
        "x",
        "y",
        "z",
        "intensity",
        "label",
        "timestamp"
    ],
    "size": [ // 用字节数指定每一个维度的大小 用来计算偏移量 
        4,
        4,
        4,
        1,
        1,
        8
    ],
    "type": [
        "F",
        "F",
        "F",
        "U",
        "U",
        "U"
    ],
    "count": [
        1,
        1,
        1,
        1,
        1,
        1
    ],
    "width": 54513,
    "height": 1,
    "viewpoint": "0 0 0 1 0 0 0",
    "points": 54513,
    "offset": { // 每个字段的偏移量 (字节)
        "x": 0,
        "y": 4,
        "z": 8,
        "intensity": 12,
        "label": 13,
        "timestamp": 14
    },
    "rowSize": 22  // 每行占多少字节
}

生成 position, normal, color 代码

  function parsePCDBinary(pcdHeader, data) {
    const position = [];
    const normal = [];
    const color = [];
    const dataview = new DataView(data, pcdHeader.headerLen);
    const offset = pcdHeader.offset;
    for (let i = 0, row = 0; i < pcdHeader.points; i++, row += pcdHeader.rowSize) {
      if (offset.x !== void 0) {
        position.push(dataview.getFloat32(row + offset.x, LITTLE_ENDIAN));
        position.push(dataview.getFloat32(row + offset.y, LITTLE_ENDIAN));
        position.push(dataview.getFloat32(row + offset.z, LITTLE_ENDIAN));
      }
      if (offset.rgb !== void 0) {
        color.push(dataview.getUint8(row + offset.rgb + 0));
        color.push(dataview.getUint8(row + offset.rgb + 1));
        color.push(dataview.getUint8(row + offset.rgb + 2));
      }
      if (offset.normal_x !== void 0) {
        normal.push(dataview.getFloat32(row + offset.normal_x, LITTLE_ENDIAN));
        normal.push(dataview.getFloat32(row + offset.normal_y, LITTLE_ENDIAN));
        normal.push(dataview.getFloat32(row + offset.normal_z, LITTLE_ENDIAN));
      }
    }
    return { position, normal, color };
  }

posted @ 2023-02-03 16:43  __Bowen  阅读(118)  评论(0编辑  收藏  举报