点云提取扫描线
1.掃描線提取原理
目前車載LiDAR系統搭載的激光掃描儀主要是線性掃描,獲得的掃描點在目標上按掃描線排列。在同一掃描線中,系統記錄的連續激光腳點的掃描角度差值為固定值(一般為激光掃描儀的角度分辨率)。在一個完整的掃描周期中,若掃描視場角為頂部天空,會出現無激光腳點返回的情況。此時當前掃描線的最后一個點和下一條掃描線的起始點的掃描角度有一個非規律的階躍。同理,因為車載激光點云的連續性,當掃描視角為頂部天空時,GPS時間差也會出現一個非規律的階躍。因此可以設置一個角度閡值或時間閡值檢測掃描線兩端的斷點,將連續點云歸于一條掃描線中,從而將離散的掃描點轉化成有序的二維掃描線數據集。(參考自方莉娜博士論文)
由于.las格式的點云文件包含每個離散點的掃描角度和GPS時間信息,所以可以按照上述方法提取出掃描線,并按照掃描線進行點云特征識別與分析等。本文的例子采用時間閾值提取掃描線。
2.核心代碼實現
2.1 自定義pcl點云類型
struct myPointXYZTI {PCL_ADD_POINT4D;union{float coordinate[3];struct{float x;float y;float z;};};double GPSTime;int intensity;EIGEN_MAKE_ALIGNED_OPERATOR_NEW; }EIGEN_ALIGN16;POINT_CLOUD_REGISTER_POINT_STRUCT(myPointXYZTI,// 注冊點類型宏(float, x, x)(float, y, y)(float, z, z)(double, GPSTime, GPSTime)(int, intensity, intensity))2.2 讀取點云txt文件
txt文件點云按行保存,格式為:X,Y,Z,GPSTime,intensity .
bool CloudIO::readTxtFile(const string &fileName, const char tag, const mypcXYZTIPtr &pointCloud) {cout << "reading file start..... " << endl;ifstream fin(fileName);string linestr;while (getline(fin, linestr)){vector<string> strvec;string s;stringstream ss(linestr);while (getline(ss, s, tag)){strvec.push_back(s);}myPointXYZTI p;p.x = stod(strvec[0]);p.y = stod(strvec[1]);p.z = stod(strvec[2]);p.GPSTime = stod(strvec[3]);p.intensity = stoi(strvec[4]);pointCloud->points.push_back(p);}fin.close();cout << "reading file finished! " << endl;cout << "There are " << pointCloud->points.size() << " points!" << endl;return true; }2.3 掃描線提取
void CloudIO::extractScanLine(mypcXYZTIPtr cloud, vector<vector<int> >& ScanLineVec) {vector<int> temp;for (int i = 1; i < cloud->points.size() - 1; i++){double time = cloud->points[i].GPSTime - cloud->points[i - 1].GPSTime;if (fabs(time) < 0.0015){temp.push_back(i);}else{ScanLineVec.push_back(temp);vector<int>().swap(temp);}}//第一個點加入第一條掃描線ScanLineVec[0].push_back(0);cout << "ScanLineVec size: " << ScanLineVec.size() << endl; }2.4 掃描線采樣顯示
void CloudIO::ScanLineDisplay(mypcXYZTIPtr &cloud, vector<vector<int> >& ScanLineVec, int ScanLineNum) {pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgbcloud(new pcl::PointCloud<pcl::PointXYZRGB>);pcl::PointXYZRGB p;bool flag = true;for (int i = 0; i < ScanLineVec.size(); i++){if (i % ScanLineNum == 0){for (int j = 0; j < ScanLineVec[i].size(); j++){p.x = cloud->points[ScanLineVec[i].at(j)].x;p.y = cloud->points[ScanLineVec[i].at(j)].y;p.z = cloud->points[ScanLineVec[i].at(j)].z;if (flag == true){p.r = 225; p.g = 0; p.b = 0;}else{p.r = 0; p.g = 255; p.b = 0;}rgbcloud->points.push_back(p);}if (flag == true){flag = false;}else{ flag = true; }}}cout << rgbcloud->points.size() << endl;boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));viewer->setBackgroundColor(255, 255, 255);viewer->addPointCloud(rgbcloud, "Ground");while (!viewer->wasStopped()){viewer->spinOnce(100);boost::this_thread::sleep(boost::posix_time::microseconds(100000));} }2.5 結果顯示
2.6 備注
1.上述點云掃描線采樣間隔為6,對相鄰掃描線賦不同顏色進行區分。
2.時間間隔參數的設置主要依據激光掃描儀的掃描頻率或對原始點云時間直方圖進行分析。
歡迎關注我的公眾號。
總結
- 上一篇: nova4e升级鸿蒙,看完这三点 告诉你
- 下一篇: okhttp异常