項目需要,要在QT界面上顯示PCL點雲。所以整理一下,供大家和自己參考。
PCL點雲顯示是基於VTK做的,之前有方法是使用cmake編譯一個VTK控件,放在QT裏,拖動使用。如下圖所示:
這樣做是十分麻煩的,博主沒做過。不過還有個更加簡單的方法。
在QT控件裏拖出一個widget控件
然後右鍵選擇“提升爲”,填寫提升類名稱和頭文件。如下:
選擇添加和提升即可。然後在頭文件裏添加響應的頭文件就可以了(具體看下面代碼)。
注:博主在剛開始用這個方法時,QT版本爲5.4.1,結果不行,後來改成5.6.3可以了。
代碼:
.h文件:
#include <QtWidgets/QMainWindow>
#include "ui_displaymessage.h"
#include <vtkRenderWindow.h>//注意添加這個頭文件,不添加會報錯,但是這個頭文件會帶來編譯時間大大增加
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include<QFile>
#include <QTextStream>
#include<opencv.hpp>
#include<iostream>
#include <vector>
using namespace cv;
class DisplayMessage : public QMainWindow
{
Q_OBJECT
public:
DisplayMessage(QWidget *parent = Q_NULLPTR);
public slots:
void on_openButton_clicked();
private:
Ui::DisplayMessageClass ui;
pcl::visualization::PCLVisualizer::Ptr viewer;
};
.cpp文件:
#include "displaymessage.h"
DisplayMessage::DisplayMessage(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
//初始化PCL顯示控件
viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));
ui.widget->SetRenderWindow(viewer->getRenderWindow());
viewer->setupInteractor(ui.widget->GetInteractor(), ui.widget->GetRenderWindow());
ui.widget->update();
}
void DisplayMessage::on_openButton_clicked()
{
QFile file("PointCloud.txt");
file.open(QIODevice::ReadOnly|QIODevice::Text);
QTextStream in(&file);
QString pointsStr;
QString midStr;
vector<double> mid;
Point3f point;
Vector<Point3f> points;
while (!in.atEnd()){
pointsStr = in.readLine();
int i = 0;
do{
midStr.append(pointsStr[i]);
i++;
if(pointsStr[i]==' '||pointsStr[i]=='\0'){
mid.push_back(midStr.toDouble());
midStr.clear();
i++;
}
}
while (pointsStr[i] != '\0');
point.x = mid[0];
point.y = mid[1];
point.z = mid[2];
points.push_back(point);
mid.clear();
}
//定義cloudPoints大小,無序點雲
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudPoints(new pcl::PointCloud<pcl::PointXYZ>);
cloudPoints->resize(points.size());
//將三維座標賦值給PCL點雲座標
for (int i = 0; i < points.size(); i++){
(*cloudPoints)[i].x = points[i].x;
(*cloudPoints)[i].y = points[i].y;
(*cloudPoints)[i].z = points[i].z;
}
//移除窗口點雲
viewer->removeAllPointClouds();
//點雲設置
//設置點雲顏色
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> cloud_color(cloudPoints, 255, 255, 255);
//點雲顏色渲染
viewer->addPointCloud(cloudPoints, cloud_color, "cloud");
//設置點雲大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
viewer->resetCamera();
ui.widget->update();
}
注:1.剛開始沒有添加頭文件#include <vtkRenderWindow.h>,報出錯誤:
錯誤2
error C2440: “static_cast”: 無法從“vtkObjectBase *const ”轉換爲“vtkRenderWindow *”C:\Program Files\PCL 1.8.0\3rdParty\VTK\include\vtk-7.0\vtkSmartPointer.h
添加後錯誤消失
2.這裏讀取的是txt文件,需要轉換爲PCL的數據格式,所以寫了個簡單的轉換算法,博主txt文件格式爲:
xxx xxx xxx
3.PCL官方格式爲pcd。只需要在txt文件前添加文件頭就可以了。格式如下:
# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS x y z
SIZE 4 4 4
TYPE F F F
COUNT 1 1 1
WIDTH 20240000
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 20240000
DATA ascii
注意:PCL點雲分爲有序點雲和無序點雲。博主只使用過無序點雲,無需點雲WIDTH設爲點雲個數,HEIGHT設爲1,
POINT設爲點雲個數。最後把txt後綴改爲pcd即可