【问题标题】:Creating pointer to read from .las binary file throws bad_alloc error创建从 .las 二进制文件读取的指针会引发 bad_alloc 错误
【发布时间】:2019-04-29 16:11:20
【问题描述】:

我目前正在编写代码以读取 .las(激光雷达点数据)文件。读入文件后,我创建了一个指针来遍历所有点。但是,它给了我一个 bad_alloc 错误。

我唯一能想到的是,标头的大小与 las 文件标头指定的大小不同。我仔细检查了我的标题,我认为我没有发现任何问题。

Header 和 PointRecord3 中的所有标题变量都来自这个documentation,分别是第 3 页和第 10 页。

更新:读入的点数为 402,673,112。但是,当我在其他激光雷达软件中打开它仔细检查时,点数只有 5,104,152。我相信这是因为我在用 C++ 打开之前在其他软件中过滤了云,因此减少了点数。

这是我的代码:

#ifndef POINTCLOUD_H
#define POINTCLOUD_H
#pragma once
#include <string>


class PointCloud
{
    public:
        PointCloud(const std::string &path);

    private:
        struct __attribute__((packed)) Header {

            char magic[4];
            uint16_t fileourceID;
            uint16_t globalEncoding;
            uint32_t guiData1;
            uint16_t guiData2;
            uint16_t guiData3;
            uint8_t guiData[8];
            uint8_t versionMaj, versionMin;
            char systemIdentifer[32];
            char genSoftware[32];
            uint16_t creationDay, creationYear;
            uint16_t headerSize;
            uint32_t pointDataOffset;
            uint32_t numVarLenRecords;
            uint8_t pointDataRecordFormat;
            uint16_t pointDataRecordLen;
            uint32_t numberOfPoints;
            uint32_t numPointsByReturn[5];
            double scaleX, scaleY, scaleZ;
            double offX, offY, offZ;
            double minX, minY, minZ;
            double maxX, maxY, maxZ;
        };

        struct __attribute__((packed)) PointRecord3 {
            uint32_t X, Y, Z;
            uint16_t intensity;
            uint8_t flags;
            uint8_t classification;
            uint8_t scanAngleRank;
            uint8_t userData;
            uint16_t pointSourceID;
            double gpsTime;
            uint16_t red;
            uint16_t green;
            uint16_t blue;
        }; 



#include "PointCloud.h"
#include <fstream>
#include <iostream>
#include <string>
#include <assert.h>

using namespace std;

PointCloud::PointCloud(const string &path)
{
    read(path);
}

void PointCloud::read(const string &path) {
    ifstream in(path.c_str(), ios::binary );
    if(in.is_open()){
        Header header;
        in.read((char *)&header, sizeof(header));

        assert(header.versionMaj == 1 && header.versionMin == 2);
        cout << "headerSize " << header.headerSize << " == " << sizeof(header) << " size of header struct" <<endl;

        cout << "FILE TYPE: LAS " << (int)header.versionMaj << "." << (int)header.versionMin << endl;
        cout << "POINT DATA OFFSET: " << (int)header.pointDataOffset <<endl;
        cout << "POINT DATA RECORD FORMAT: " << (int)header.pointDataRecordFormat <<endl;
        cout << "NUMBER OF POINTS: " << (int)header.numberOfPoints << endl;



        PointRecord3 *points = new PointRecord3[header.numberOfPoints];

       in.seekg(header.pointDataOffset);
        for(uint32_t i = 0; i < header.numberOfPoints; i++) {
            in.read((char *) (points + i), sizeof(*points));
       }
       if(in.good()) {

          throw runtime_error("error");
        }

      delete points;


    } else {
        cout << "file not opened" << endl;

    }

}

任何帮助将不胜感激!

这里也是 LAS 文件头的输出:

file signature:             'LASF'
  file source ID:             0
  global_encoding:            0
  project ID GUID data 1-4:   00000000-0000-0000-0000-000000000000
  version major.minor:        1.2
  system identifier:          'EXPORT'
  generating software:        'RiSCAN_PRO'
  file creation day/year:     317/2018
  header size:                227
  offset to point data:       313
  number var. length records: 1
  point data format:          3
  point data record length:   34
  number of point records:    5104152
  number of points by return: 5104152 0 0 0 0
  scale factor x y z:         0.00025 0.00025 0.00025
  offset x y z:               267805 3197054 13
  min x y z:                  267804.25250 3196596.64500 -1.89000
  max x y z:                  268760.27000 3197586.23000 23.33000
variable length header record 1 of 1:
  reserved             43707
  user ID              'LASF_Projection'
  record ID            34735
  length after header  32
  description          'GeoKeyDirectoryTag (mandatory)'
    GeoKeyDirectoryTag version 1.1.0 number of keys 3
      key 1025 tiff_tag_location 0 count 1 value_offset 2 - GTRasterTypeGeoKey: RasterPixelIsPoint
      key 1024 tiff_tag_location 0 count 1 value_offset 3 - GTModelTypeGeoKey: ModelTypeGeocentric
      key 2048 tiff_tag_location 0 count 1 value_offset 4326 - GeographicTypeGeoKey: GCS_WGS_84
reporting minimum and maximum for all LAS point record entries ...
  X               -2989    3821075
  Y            -1829412    2128911
  Z              -59559      41318
  intensity       32767      32768
  return_number       1          1
  number_of_returns   1          1
  edge_of_flight_line 0          0
  scan_direction_flag 1          1
  classification      0          0
  scan_angle_rank     0          0
  user_data           0          0
  point_source_ID     0          0
  gps_time 0.000000 0.000000
  Color R 0 0
        G 0 0
        B 0 0
number of first returns:        5104152
number of intermediate returns: 0
number of last returns:         5104152
number of single returns:       5104152
overview over number of returns of given pulse: 5104152 0 0 0 0 0 0
histogram of classification of points:
         5104152  never classified (0)

【问题讨论】:

  • 你想要delete[] points;。你的程序在崩溃之前走了多远?是否输出blah?
  • 您说“.las 文件”,好像每个人都知道那是什么。我们没有。什么是“.las”文件?
  • 我敢打赌,如果你写出你读到的点数,你的谜团就会被解开。
  • 在现代 C++ 中使用智能指针和容器。 不是手动内存管理。
  • @p0ps1c1e 尝试创建大小约为 11GB 的数组失败并不奇怪。您可能需要考虑内存映射文件而不是读取文件。

标签: c++ pointers bad-alloc las


【解决方案1】:

我想通了。所以发生的事情是 C++ 添加了一些额外的字节,导致我的头结构比实际的文件头大 5 个字节。我通过添加#pragma pack (push, 1) 解决了这个问题。

#ifndef POINTCLOUD_H
#define POINTCLOUD_H
#pragma pack (push, 1)
#include <string>


struct float3
{
    float x, y, z;

};

class PointCloud
{
    public:
        PointCloud(const std::string &path);

    private:

        struct __attribute__((packed)) Header
        {

            char fileSig[4];
            uint16_t fileourceID;
            uint16_t globalEncoding;
            uint32_t guiData1;
            uint16_t guiData2;
            uint16_t guiData3;
            uint8_t guiData[8];
            uint8_t versionMaj, versionMin;
            char systemIdentifer[32];
            char genSoftware[32];
            uint16_t creationDay, creationYear;
            uint16_t headerSize;
            uint32_t pointDataOffset;
            uint32_t numVarLenRecords;
            uint8_t pointDataRecordFormat;
            uint16_t pointDataRecordLen;
            uint32_t numberOfPoints;
            uint32_t numPointsByReturn[5];
            double scaleX, scaleY, scaleZ;
            double offX, offY, offZ;
            double minX, minY, minZ;
            double maxX, maxY, maxZ;
        };

        struct __attribute__((packed)) PointRecord3
        {
            uint32_t X, Y, Z;
            uint16_t intensity;
            uint8_t flags;
            uint8_t classification;
            uint8_t scanAngleRank;
            uint8_t userData;
            uint16_t pointSourceID;
            double gpsTime;
            uint16_t red;
            uint16_t green;
            uint16_t blue;
        };


        void read(const std::string &path);
};



#endif // POINTCLOUD_H

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-19
    • 2019-10-02
    • 2021-11-01
    • 2020-11-24
    • 1970-01-01
    相关资源
    最近更新 更多