I'm fairly new to the Point Cloud world. In addition, I'm not so experienced in C++.
I need to read .las files and process them using the pcl library. This is a sample file from the dataset that I need to read. I followed this youtube video. However, since the file I'm trying to read is of version 1.3, I followed the corresponding spec file to define the header fields and I used 'Data Record Format 3' which is the data record format mentioned in the file header.
This are my definitions for the header and data record format:
#pragma once
#include <string>
#include <vector>
struct float4
{
float x, y, z, intensity;
};
class PointCloud
{
public:
uint32_t getVertsCount();
float4* getVertsData();
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr read(const std::string& path);//void read(const std::string &path);
private:
std::vector<float4> verts;
#pragma pack(1)
struct Header
{
char magic[4];
uint16_t fileSourceID;
uint16_t globalEncoding;
uint32_t guidData1;
uint16_t guidData2;
uint16_t guidData3;
uint8_t guidData4[8];
uint8_t versionMaj, versionMin;
char systemIdentifier[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 offsetX, offsetY, offsetZ;
double maxX, minX, maxY, minY, maxZ, minZ;
uint64_t waveform;
};
//#pragma pack(1)
struct 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;
};
};
I used the following code to read the point data, but I failed to get correct points:
template<typename PointT>
typename pcl::PointCloud<PointT>::Ptr PointCloud::read(const string& path)
{
ifstream inf(path, ios::binary);
typename pcl::PointCloud<PointT>::Ptr lasCloud(new pcl::PointCloud<PointT>);
if (inf.is_open())
{
Header header;
inf.read((char*)&header, sizeof(header));
cout << "Signature: " << header.magic << endl;
cout << "Source ID: " << int(header.fileSourceID) << endl;
cout << "Global Encoding: " << int(header.globalEncoding) << endl;
cout << "Guid 1: " << int(header.guidData1) << endl;
cout << "Guid 2: " << int(header.guidData2) << endl;
cout << "Guid 3: " << int(header.guidData3) << endl;
cout << "Guid 4: " << header.guidData4 << endl;
cout << (int)header.versionMaj << '.' << (int)header.versionMin << endl;
cout << "Sys Identifier: " << header.systemIdentifier << endl;
cout << "Gen Software: " << header.genSoftware << endl;
cout << "Creation Day: " << header.creationDay << endl;
cout << "Creation Year: " << header.creationYear << endl;
cout << header.headerSize << " == " << sizeof(header) << endl;
cout << "Point Data Offset: " << header.pointDataOffset << endl;
cout << "Number of Variable Len Records: " << header.numVarLenRecords << endl;
cout << "point Data Record Format: " << header.pointDataRecordFormat << endl;
cout << "point Data Record Len: " << header.pointDataRecordLen << endl;
cout << "Number of Points: " << header.numberOfPoints << endl;
cout << "Number of Points by Return: " << header.numPointsByReturn << endl;
cout << "Scales: " << header.scaleX << ", " << header.scaleY << ", " << header.scaleZ << endl;
cout << "Offsets: " << header.offsetX << ", " << header.offsetY << ", " << header.offsetZ << endl;
cout << "Xmin = " << header.minX << ", Ymin = " << header.minY << ", Zmin = " << header.minZ << endl;
cout << "Xmax = " << header.maxX << ", Ymax = " << header.maxY << ", Zmax = " << header.maxZ << endl;
cout << "Waveform: "<<header.waveform << endl;
assert(header.versionMaj == 1 && header.versionMin == 3);
//assert(header.headerSize == sizeof(header));
assert(header.pointDataRecordFormat == 3);
//inf.seekg(header.pointDataOffset);
inf.seekg(sizeof(header));
//inf.seekg(header.pointDataOffset+sizeof(header.waveform));
for (uint32_t i = 0; i < header.numberOfPoints; i++)
{
//PointRecord1* points = new PointRecord1[header.numberOfPoints];
PointRecord3 point;
//inf.read((char*)(points + i), sizeof(PointRecord1));
//inf.read((char*)&point, sizeof(PointRecord1));
inf.read((char*)&point, sizeof(PointRecord3));
PointT cloudPoint;
cloudPoint.x = (float)(point.x * header.scaleX) + header.offsetX;
cloudPoint.y = (float)(point.y * header.scaleY) + header.offsetY;
cloudPoint.z = (float)(point.z * header.scaleZ) + header.offsetZ;
cloudPoint.intensity = (float)(point.intensity) / 65536.0;
lasCloud->points.push_back(cloudPoint);
}
if (!inf.good())
throw runtime_error("Reading went wrong!");
}
else
{
throw runtime_error("Can't find any!");
}
lasCloud->width = lasCloud->points.size();
lasCloud->height = 1;
lasCloud->is_dense = true;
std::cout << "Cloud size = " << lasCloud->points.size() << endl;
return lasCloud;
}
int main (int argc, char** argv)
{
std::cout << "starting enviroment" << std::endl;
pcl::visualization::PCLVisualizer::Ptr viewer (new pcl::visualization::PCLVisualizer ("3D Viewer"));
CameraAngle setAngle = FPS; //XY, FPS, Side, TopDown
initCamera(setAngle, viewer);
pcl::PointCloud<pcl::PointXYZI>::Ptr inputCloudI; //
PointCloud pcd;
inputCloudI=pcd.read<pcl::PointXYZI>("C:/Users/hedey/OneDrive/Documents/Research_papers/STDF/10_4231_MFQF-Q141/I-65/LiDAR/RoadSurface/NB/20180524_I65_NB_RoadSurface_1_50.5.las");
std::cout << "Cloud size = " << inputCloudI->points.size() << endl;
renderPointCloud(viewer, inputCloudI, "lasCloud");
while (!viewer->wasStopped())
{
viewer->spinOnce();
}
}
There is a problem that I noticed. The header size is defined to be 227 (this is the value of the header size field). However, there is an 8-byte field named 'Start of Waveform Data Packet Record' at the end of the header, which if included in the header definition will make the header size 235 bytes. Also, the pointDataOffset field which was used to seek the points data in the youtube video is pointing to 227 bytes. When I used it to seek the points data, I got unreasonable point values.
My target is to process this point cloud and display it using the pcl cloud, but I'm failing to read the points correctly.
I have no idea about Lidar and *.las files, but I've noticed that the input file was created with libLAS
> file 20180524_I65_NB_RoadSurface_1_50.5.las
20180524_I65_NB_RoadSurface_1_50.5.las: LIDAR point data records, version 1.3, SYSID libLAS, Generating Software libLAS 1.6.0
So, why don't you use libLAS to read the data in? https://liblas.org/
libLAS comes with convenient CLI utility programs to handle las files, e.g.:
lasinfo 20180524_I65_NB_RoadSurface_1_50.5.las
---------------------------------------------------------
Header Summary
---------------------------------------------------------
Version: 1.3
Source ID: 0
Reserved: 0
Project ID/GUID: '00000000-0000-0000-0000-000000000000'
System ID: 'libLAS'
Generating Software: 'libLAS 1.6.0'
File Creation Day/Year: 144/2018
Header Byte Size 227
Data Offset: 227
Header Padding: 0
Number Var. Length Records: None
Point Data Format: 3
Number of Point Records: 22017565
Compressed: False
Number of Points by Return: 0 0 0 0 0
Scale Factor X Y Z: 0.00100000000000 0.00100000000000 0.00100000000000
Offset X Y Z: 590284.000 4339456.000 157.000
Min X Y Z: 589879.772 4338728.975 149.667
Max X Y Z: 590334.248 4339568.021 178.397
Spatial Reference: None
---------------------------------------------------------
Schema Summary
---------------------------------------------------------
Point Format ID: 3
Number of dimensions: 16
Custom schema?: false
Size in bytes: 34
Dimensions
---------------------------------------------------------
'X' -- size: 32 offset: 0
'Y' -- size: 32 offset: 4
'Z' -- size: 32 offset: 8
'Intensity' -- size: 16 offset: 12
'Return Number' -- size: 3 offset: 14
'Number of Returns' -- size: 3 offset: 14
'Scan Direction' -- size: 1 offset: 14
'Flightline Edge' -- size: 1 offset: 14
'Classification' -- size: 8 offset: 15
'Scan Angle Rank' -- size: 8 offset: 16
'User Data' -- size: 8 offset: 17
'Point Source ID' -- size: 16 offset: 18
'Time' -- size: 64 offset: 20
'Red' -- size: 16 offset: 28
'Green' -- size: 16 offset: 30
'Blue' -- size: 16 offset: 32
---------------------------------------------------------
Point Inspection Summary
---------------------------------------------------------
Header Point Count: 22017565
Actual Point Count: 22017565
Minimum and Maximum Attributes (min,max)
---------------------------------------------------------
Min X, Y, Z: 600191.027, 4313816.564, 148.621
Max X, Y, Z: 600212.594, 4314678.007, 156.632
Bounding Box: 600191.027, 4313816.564, 600212.594, 4314678.007
Time: 55449082.421688, 55488872.904376
Return Number: 0, 0
Return Count: 0, 0
Flightline Edge: 0, 0
Intensity: 0, 255
Scan Direction Flag: 0, 0
Scan Angle Rank: 0, 0
Classification: 1, 3
Point Source Id: 0, 31
User Data: 0, 0
Minimum Color (RGB): 0 0 0
Maximum Color (RGB): 0 0 0
Number of Points by Return
---------------------------------------------------------
(1) 22017565
Number of Returns by Pulse
---------------------------------------------------------
(0) 22017565
Point Classifications
---------------------------------------------------------
7187055 Unclassified (1)
8128678 Ground (2)
6701832 Low Vegetation (3)
-------------------------------------------------------
0 withheld
0 keypoint
0 synthetic
-------------------------------------------------------
and
las2txt 20180524_I65_NB_RoadSurface_1_50.5.las qq.txt && head qq.txt
600209.243,4313837.086,155.155
600209.342,4313839.620,155.191
600209.232,4313836.806,155.154
600209.338,4313839.516,155.197
600209.221,4313836.523,155.165
600209.333,4313839.398,155.194
600209.206,4313836.177,155.158
600209.328,4313839.285,155.200
600209.189,4313835.778,155.145
600209.322,4313839.152,155.193
This means that the file is OK, the library works, and you'll save yourself lots of time learning the basic library usage rather then trying to reimplement it yourself (think of various data formats etc., error handling etc., testing etc., getting feedback in case of troubles, etc., and your time)
I am trying to edit the pixels of an image with opencv.
I used this code:
#include<iostream>
#include<opencv2/opencv.hpp>
#include<stdint.h>
using namespace std;
uchar* array123()
{
uchar arr[3] = { 123, 123, 123 };
return arr;
};
int main()
{
cv::Mat img = cv::imread("img.jpg");
uchar* n;
for (int x = 0; x < img.cols; x++)
{
for (int y = 0; y < img.rows; y++)
{
n = array123();
cout << "n " << (int)*n << " " << (int)*(n + 1) << " " << (int)*(n + 2) << endl;
cv::Vec3b& color = img.at<cv::Vec3b>(y, x);
cout << "Before change " << (int)color[0] << " " << (int)color[1] << " " << (int)color[2] << endl;
color[0] = *n;
color[1] = *(n + 1);
color[2] = *(n + 2);
img.at<cv::Vec3b>(y, x) = color;
cv::Vec3b color2 = img.at<cv::Vec3b>(y, x);
cout << "After change " << (int)color2[0] << " " << (int)color2[1] << " " << (int)color2[2] << endl;
}
}
}
The console will log something like this:
n 123 123 123
Before change 153 123 26
After change 204 204 204
... repeating with After change always being 204 204 204 ...
And if I save the image is just a gray image with 204, 204, 204 RGB values
Does anyone know why this happens?
I got a task from my lecture to make association program from my data mining class, and i'm using c++ in microsoft visual studio 2017 since that is the only language i understand.
I'm trying to get support result but all i got is 0. i use an algorithm i got from some sites, but i can't implement it to my code because the value is 0.
I think the problem is in the input data reading, the one with for(int i=0;i<n;i++).
this is my code :
#include<iostream>
#include<string>
using namespace std;
int main()
{
float n = 5, support1 = 0, support2 = 0, support3 = 0;
string item1, item2;
//dataset fixed
string tra1[5] = { "milk", "beer" , "coffee" , "sugar" , "detergen" };
string tra2[5] = { "egg", "flour" , "milk" , "sugar" };
string tra3[5] = { "coffee", "butter" , "cigarette" , "sugar" };
string tra4[5] = { "doritos", "tea" , "coconut oil" , "soap" };
string tra5[5] = { "detergen", "milk" , "sugar" , "coca cola" };
cout << "item 1 : "; cin >> item1;//for example coffee
cout << "item 2 : "; cin >> item2;//for example sugar
cout << endl << "------------------------------" << endl;
//i think this is where the problem is
for (int i = 0;i < n;i++)
{
//tra1
if (item1 == tra1[5]) { support1 + 1; }
if (item2 == tra1[5]) { support2 + 1; }
if (item1 == tra1[5] && item2 == tra1[5]) { support3 + 1; }
//tra2
if (item1 == tra2[5]) { support1 + 1; }
if (item2 == tra2[5]) { support2 + 1; }
if (item1 == tra2[5] && item2 == tra2[5]) { support3 + 1; }
//tra3
if (item1 == tra3[5]) { support1 + 1; }
if (item2 == tra3[5]) { support2 + 1; }
if (item1 == tra3[5] && item2 == tra3[5]) { support3 + 1; }
//tra4
if (item1 == tra4[5]) { support1 + 1; }
if (item2 == tra4[5]) { support2 + 1; }
if (item1 == tra4[5] && item2 == tra4[5]) { support3 + 1; }
//tra5
if (item1 == tra5[5]) { support1 + 1; }
if (item2 == tra5[5]) { support2 + 1; }
else if (item1 == tra1[5] && item2 == tra5[5]) { support3 + 1; }
}
//print how many times are coffee and sugar purchased
cout << "Transaction done " << item1 << " : " << support1 << endl;
cout << "Transaction done " << item2 << " : " << support2 << endl;
cout << "Transaction done " << item2 << " dan " << item2 << " : " << support3 << endl;
cout << endl << "------------------------------" << endl;
float result1,result2,result3;
result1 = (support1 / n) * 100;
result2 = (support2 / n) * 100;
result3 = (support3 / n) * 100;
cout << "Item 1 : " << item1 << "\t" << "Item 2 : " << item2 << endl;
cout << "support " << item1 << " : " << result1 << endl;
cout << "support " << item2 << " : " << result2 << endl;
cout << "support " << item1 << " dan " << item2 << " : " << result3 << endl;
return 0;
}
in your code, inside the loop you keep referencing tra2[5] . I think you mean to use tra2[i] instead. The way you have it now you're only looking at one past the last item in your arrays (arrays are 0-based. Valid indices are [0-4])
2 things, you’re for loop is trying to access the 6th index of the array when it’s only initialized to have 5 indicis.
2nd the support1,2,3 variables are initialized to 0 but you never actually increment those variables, which are used as part of your final calculation.
Your for loop needs to change to have “support1 + 1” be “support1+=1”.
im wondering how to dynamicaly declare variable name with ionic 2.
i want to implemet a read more function with ion-list result but to do it i need to have individual variable names.
// my ts file
import { Component } from '#angular/core';
import { NavController,Platform ,LoadingController, NavParams } from 'ionic-
angular';
import { GardeService } from '../../app/services/Garde.service';
#Component({
selector: 'page-home',
templateUrl: 'home.html'
})
export class Home {
//data:any;
public newslist: Array<Object>;
mytext:any;
prewords:any;
textpreview:any;
fulltext:any;
constructor(public data:GardeService) {}
ngOnInit()
{
this.loadnews();
this.fulltext = true;
this.textpreview = false;
}
public loadnews(){
this.newslist = [];
var map: {[key:string]:string} = {};
this.data.LoadNews().subscribe(
data => {
for(let i=0;i<data.length;i++){
//this.newslist.push(data[i]);
//console.log("news",data[i].content);
this.mytext = data[i].content.split(' ');
this.prewords = this.mytext[0] + " " + this.mytext[1] + " " +
this.mytext[2] + " " + this.mytext[3] + " " +
this.mytext[4] + " " + this.mytext[5] + " " + this.mytext[6] + " " +
this.mytext[7] + " " + this.mytext[8] + " " +
this.mytext[9] + " " + this.mytext[10] + " " + this.mytext[11] + " "
+ this.mytext[12] + " " + this.mytext[13] + " " +
this.mytext[14] + " " + this.mytext[15] + " " + this.mytext[16] + ""
+ this.mytext[17] + " " + this.mytext[18] + " " +
this.mytext[19] + " " + this.mytext[20];
//map['fulltext'+i] = true;
this.textpreview = false;
this.newslist.push({poster: data[i].poster, title: data[i].title,
img:data[i].img, content:data[i].content,
pre:this.prewords});
//console.log("les mots descriptifs",this.prewords);
}
},
err => {
console.log(err);
},
() => console.log('news loaded')
);
}
public readMore(){
this.textpreview = true;
this.fulltext = false;
}
}
// my html file
ion-col width-100 text-wrap>
<p style="text-align:justify;" color="dark" ion-text>
<span ion-text [hidden]="textpreview">{{item.pre}}</span><span
ion-text (click)="readMore()">...Lire plus</span>
<span ion-text [hidden]="fulltext">{{item.content}}</span>
</p>
</ion-col>
i want to have dynamic changing this.fulltext and this.textpreview variable names in order to do that because when i click the read more link all the content of all the ion-itens extend . i only want it to happen the place i click
I'm trying to return a value from a function but all it return is the value 1.
It's suppose to have 5 arguments in the computeCivIndex(), even if I hard coded the values the output I receive would still be 1.
Why is this so ?
float LocationData::computeCivIndex()
{
civNum1 = 45.0 / 100;
civNum2 = 20 + 50;
civNum3 = civNum2 / 200;
civNum4 = civNum1 - civNum3;
civNum5 = 5 + 10;
return civNum;
}
//display data
void LocationData::displaydata()
{
cout << "CIV value: " << computeCivIndex << endl;
}
You miss () in cout << "CIV value: " << computeCivIndex() << endl;.
For importance of braces you can check this link.
cout << "CIV value: " << computeCivIndex << endl;
seems to be printing the value of the function (not the return value). You need to put the function brackets in:
cout << "CIV value: " << computeCivIndex() << endl;
//convert sunType to sunTypePercentage
float LocationData::computeCivIndex(string st, int earth, int moons, float particle, float plasma)
{
float sunTypePercent;
if(st == "Type 0")
{
sunTypePercent = 80.0;
}
else if(st == "Type B")
{
sunTypePercent = 45.0;
}
else if(st == "Type A")
{
sunTypePercent = 60.0;
}
else if(st == "Type F")
{
sunTypePercent = 75.0;
}
else if(st == "Type G")
{
sunTypePercent = 90.0;
}
else if(st == "Type K")
{
sunTypePercent = 80.0;
}
else if(st == "Type M")
{
sunTypePercent = 70.0;
}
// calculate CIV Value
float civNum,civNum1,civNum2,civNum3,civNum4,civNum5;
civNum1 = sunTypePercent / 100;
civNum2 = plasma + particle;
civNum3 = civNum2 / 200;
civNum4 = civNum1 - civNum3;
civNum5 = earth + moons;
civNum = civNum4 * civNum5;
return civNum;
}
//display data
void LocationData::displaydata()
{
cout << "suntype: " << sunType << endl;
cout << "earth: " << noOfEarthLikePlanets << endl;
cout << "moons: " << noOfEarthLikeMoons << endl;
cout << "particle: " << aveParticulateDensity << endl;
cout <<"density: " << avePlasmaDensity << endl;
cout << "CIV value: " << computeCivIndex()<< endl;
}
This is the actual code which i'm having problem with. For the computeCivIndex() function it is actually a static under the public LocationData class in my LocationData.h file which look something like this.
static float compute CivIndex(string st, int earth, int moons, float particle, float plasma);
so in order to retrieve the value from the function should I do this instead?
cout << "CIV value: " << LocationData.computeCivIndex() << endl;