解析点云文件

89 阅读1分钟

点云PCD解析

点云头部信息

£ .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z timestamp intensity ring azimuth
SIZE 4 4 4 8 1 2 4
TYPE F F F F U U F
COUNT 1 1 1 1 1 1 1
WIDTH 3378
HEIGHT 128
VIEWPOINT 0 0 0 1 0 0 0
POINTS 432384
DATA binary

实现逻辑

var { resolve } = require('path')
const { Buffer } = require('node:buffer');

fs.readFile(resolve(__dirname,'2.pcd'),(err,buffer) => {
  if (err) {
    console.error('Error reading file:',err);
    return;
  }
  const headerEndIndex = buffer.indexOf(Buffer.from('DATA binary')) + 'DATA binary'.length;
  const header = buffer.slice(0,headerEndIndex).toString('utf-8');
console.log(header)
  // 提取文件头部信息
  const headerLines = header.split('\n');
  let width,height,pointsCount,fields;

  headerLines.forEach(line => {
    if (line.startsWith('FIELDS')) {
      fields = line.split(' ').slice(1);  // 获取字段名(x, y, z, rgb)
    }
    if (line.startsWith('WIDTH')) {
      width = parseInt(line.split(' ')[1]);  // 获取点云的宽度
    }
    if (line.startsWith('HEIGHT')) {
      height = parseInt(line.split(' ')[1]);  // 获取点云的高度
    }
    if (line.startsWith('POINTS')) {
      pointsCount = parseInt(line.split(' ')[1]);  // 获取点的总数
    }
  });
  const pointData = buffer.slice(headerEndIndex);  // 获取二进制数据部分
  let points = [];
  let offset = 0;

  // 每个点包含 4 字节 x, 4 字节 y, 4 字节 z, 4 字节 rgb (一共 16 字节)
  for (let i = 0; i < pointsCount; i++) {
    const x = pointData.readFloatLE(offset);       // 读取 4 字节的浮动类型 x
    const y = pointData.readFloatLE(offset + 4);   // 读取 4 字节的浮动类型 y
    const z = pointData.readFloatLE(offset + 8);   // 读取 4 字节的浮动类型 z
    const rgb = pointData.readUInt32LE(offset + 12); // 读取 4 字节的 RGB(整数)
    const intensity = pointData.readFloatLE(offset + 16); 
    // 提取 RGB 颜色值的红、绿、蓝分量(假设是以 8 位的形式存储)
    const r = (rgb >> 16) & 0xFF;
    const g = (rgb >> 8) & 0xFF;
    const b = rgb & 0xFF;

    // 将每个点的数据存储到数组中
    points.push({ x,y,z,rgb: { r,g,b } ,intensity});

    // 移动到下一个点的位置(16 字节)
    offset += 20;
  }
});