v1.0
This commit is contained in:
53
Classes/HisThread.cpp
Normal file
53
Classes/HisThread.cpp
Normal file
@@ -0,0 +1,53 @@
|
||||
#include "HisThread.h"
|
||||
|
||||
HisThread::HisThread(PointCloud<PointXYZRGB>* cloudArg, PolygonMesh* meshArg)
|
||||
{
|
||||
mesh = meshArg;
|
||||
cloud = cloudArg;
|
||||
}
|
||||
|
||||
void HisThread::run()
|
||||
{
|
||||
PointCloud<PointXYZRGB>::Ptr finalCloud = cloud->makeShared();
|
||||
NormalEstimation<PointXYZRGB, Normal> n;//法线估计对象
|
||||
PointCloud<Normal>::Ptr normals(new PointCloud<Normal>);//存储估计的法线的指针
|
||||
search::KdTree<PointXYZRGB>::Ptr tree(new search::KdTree<PointXYZRGB>);
|
||||
tree->setInputCloud(finalCloud);
|
||||
n.setInputCloud(finalCloud);
|
||||
n.setSearchMethod(tree);
|
||||
n.setKSearch(20);
|
||||
n.compute(*normals); //计算法线,结果存储在normals中
|
||||
|
||||
//将点云和法线放到一起
|
||||
PointCloud<PointXYZRGBNormal>::Ptr cloud_with_normals(new PointCloud<PointXYZRGBNormal>);
|
||||
concatenateFields(*finalCloud, *normals, *cloud_with_normals);
|
||||
|
||||
//创建搜索树
|
||||
search::KdTree<PointXYZRGBNormal>::Ptr tree2(new search::KdTree<PointXYZRGBNormal>);
|
||||
tree2->setInputCloud(cloud_with_normals);
|
||||
//创建Poisson对象,并设置参数
|
||||
Poisson<PointXYZRGBNormal> pn;
|
||||
pn.setConfidence(true); //是否使用法向量的大小作为置信信息。如果false,所有法向量均归一化。
|
||||
pn.setDegree(2); //设置参数degree[1,5],值越大越精细,耗时越久。
|
||||
pn.setDepth(8); //树的最大深度,求解2^d x 2^d x 2^d立方体元。由于八叉树自适应采样密度,指定值仅为最大深度。
|
||||
pn.setIsoDivide(8); //用于提取ISO等值面的算法的深度
|
||||
pn.setManifold(true); //是否添加多边形的重心,当多边形三角化时。 设置流行标志,如果设置为true,则对多边形进行细分三角话时添加重心,设置false则不添加
|
||||
pn.setManifold(false);
|
||||
pn.setOutputPolygons(false); //是否输出多边形网格(而不是三角化移动立方体的结果)
|
||||
//pn.setSamplesPerNode(3.0); //设置落入一个八叉树结点中的样本点的最小数量。无噪声,[1.0-5.0],有噪声[15.-20.]平滑
|
||||
pn.setSamplesPerNode(18); //设置落入一个八叉树结点中的样本点的最小数量。无噪声,[1.0-5.0],有噪声[15.-20.]平滑
|
||||
pn.setScale(1.25); //设置用于重构的立方体直径和样本边界立方体直径的比率。
|
||||
pn.setSolverDivide(8); //设置求解线性方程组的Gauss-Seidel迭代方法的深度
|
||||
//pn.setIndices();
|
||||
|
||||
//设置搜索方法和输入点云
|
||||
pn.setSearchMethod(tree2);
|
||||
pn.setInputCloud(cloud_with_normals);
|
||||
|
||||
//执行重构
|
||||
pn.performReconstruction(*mesh);
|
||||
// auto pclData = PointCloudData::getInstance(cloud);
|
||||
// pclData->getViewer()->removeAllPointClouds();
|
||||
// pclData->getViewer()->addPolygonMesh(mesh, "my");
|
||||
|
||||
}
|
||||
32
Classes/HisThread.h
Normal file
32
Classes/HisThread.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <qthread.h>
|
||||
#include <pcl/point_types.h>
|
||||
#include <pcl/io/vtk_lib_io.h>
|
||||
#include <pcl/kdtree/kdtree_flann.h>
|
||||
#include <pcl/features/normal_3d_omp.h>
|
||||
#include <pcl/features/normal_3d.h>
|
||||
#include <pcl/surface/gp3.h>
|
||||
#include <pcl/surface/poisson.h>
|
||||
#include <pcl/PolygonMesh.h>
|
||||
#include <pcl/features/normal_3d.h>
|
||||
#include <pcl/features/normal_3d_omp.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace pcl;
|
||||
|
||||
class HisThread :
|
||||
public QThread
|
||||
{
|
||||
public:
|
||||
HisThread(PointCloud<PointXYZRGB>* cloud,PolygonMesh* meshArg);
|
||||
~HisThread(){};
|
||||
|
||||
|
||||
private:
|
||||
PolygonMesh* mesh;// 多变形网格,用于存储结果
|
||||
PointCloud<PointXYZRGB>* cloud;
|
||||
|
||||
protected:
|
||||
void run();
|
||||
};
|
||||
@@ -10,7 +10,10 @@ void MyThread::run()
|
||||
if(!pcd.empty())
|
||||
{
|
||||
PointCloud<PointXYZRGB>::Ptr cloudPtr(new PointCloud<PointXYZRGB>);
|
||||
io::loadPCDFile(pcd, *cloudPtr);
|
||||
if (QString::fromStdString(pcd).endsWith(".pcd", Qt::CaseInsensitive))
|
||||
io::loadPCDFile(pcd, *cloudPtr);
|
||||
else if (QString::fromStdString(pcd).endsWith(".ply", Qt::CaseInsensitive))
|
||||
io::loadPLYFile(pcd, *cloudPtr);
|
||||
cloud = *cloudPtr;
|
||||
}
|
||||
|
||||
@@ -29,7 +32,3 @@ PointCloud<PointXYZRGB> MyThread::getCloud()
|
||||
{
|
||||
return cloud;
|
||||
}
|
||||
|
||||
MyThread::~MyThread()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class MyThread :
|
||||
{
|
||||
public:
|
||||
MyThread();
|
||||
~MyThread();
|
||||
~MyThread(){};
|
||||
void setPcd(QString str);
|
||||
PointCloud<PointXYZRGB> getCloud();
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <pcl/io/pcd_io.h>
|
||||
#include <pcl/visualization/pcl_visualizer.h>
|
||||
#include <pcl/io/vtk_lib_io.h>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include "Reconstruction.h"
|
||||
|
||||
using namespace pcl;
|
||||
|
||||
@@ -1,16 +1,21 @@
|
||||
#include "Reconstruction.h"
|
||||
#include "MyThread.h"
|
||||
#include "YourThread.h"
|
||||
|
||||
Reconstruction::Reconstruction(QWidget* parent)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
this->setWindowIcon(QIcon(":/icon/image/common/icon.png"));
|
||||
calibData = new CalibrationData();
|
||||
calibrator = new Calibrator();
|
||||
dirModel = new TreeModel(this);
|
||||
td = new YourThread(&cloud);
|
||||
t = new MyThread;
|
||||
htd = new HisThread(&cloud, &mesh);
|
||||
connect(td, SIGNAL(finished()), this, SLOT(setCloud()));
|
||||
connect(t, SIGNAL(finished()), this, SLOT(setCloud()));
|
||||
connect(htd, SIGNAL(finished()), this, SLOT(setCloud()));
|
||||
device = Device::getInstance();
|
||||
setStyle();
|
||||
}
|
||||
@@ -18,6 +23,15 @@ Reconstruction::Reconstruction(QWidget* parent)
|
||||
#pragma region Style
|
||||
void Reconstruction::setStyle()
|
||||
{
|
||||
boost::shared_ptr<visualization::PCLVisualizer> viewer(new visualization::PCLVisualizer("3D Viewer"));
|
||||
viewer->setBackgroundColor(0.458, 0.529, 0.844);
|
||||
viewer->initCameraParameters();
|
||||
auto pclData = PointCloudData::getInstance(cloud);
|
||||
pclData->setViewer(viewer);
|
||||
pclData->setUI(ui);
|
||||
ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());
|
||||
ui.qvtkWidget->update();
|
||||
|
||||
this->setContentsMargins(0, 0, 0, 0);
|
||||
// this->setFixedSize(1240, 680);
|
||||
// ui.centralWidget->setGeometry(0, 40, 1240, 680);
|
||||
@@ -67,6 +81,7 @@ void Reconstruction::setPicStyle()
|
||||
ui.pushButton_8->setEnabled(false);
|
||||
ui.pushButton_9->setEnabled(false);
|
||||
ui.pushButton_10->setEnabled(false);
|
||||
ui.pushButton_19->setEnabled(false);
|
||||
}
|
||||
|
||||
ui.label_21->setPixmap(QPixmap(":/icon/image/projection/novideo.jpg"));
|
||||
@@ -97,8 +112,9 @@ void Reconstruction::setButtonStyle()
|
||||
// 三维重建界面
|
||||
ui.pushButton_13->setIcon(QIcon(":/icon/image/reconstruction/import.png"));
|
||||
ui.pushButton_14->setIcon(QIcon(":/icon/image/reconstruction/export.png"));
|
||||
ui.pushButton_15->setIcon(QIcon(":/icon/image/reconstruction/save2.png"));
|
||||
ui.pushButton_15->setIcon(QIcon(":/icon/image/reconstruction/surface.png"));
|
||||
ui.pushButton_16->setIcon(QIcon(":/icon/image/reconstruction/color.png"));
|
||||
ui.pushButton_18->setIcon(QIcon(":/icon/image/reconstruction/help2.png"));
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
@@ -144,14 +160,15 @@ void pp_callback(const visualization::AreaPickingEvent& event, void* args)
|
||||
auto pclData = PointCloudData::getInstance();
|
||||
PointCloud<PointXYZRGB>::Ptr cloudPtr(new PointCloud<PointXYZRGB>);
|
||||
cloudPtr = pclData->getCloud().makeShared();
|
||||
int num = pclData->getNum();
|
||||
auto num = pclData->getNum();
|
||||
std::vector<int> indices;
|
||||
|
||||
if (event.getPointsIndices(indices) == -1)
|
||||
return;
|
||||
// cout << indices.size() << "\n";
|
||||
PointCloud<PointXYZRGB>::Ptr clicked_points_3d(new PointCloud<PointXYZRGB>);
|
||||
for (int i = 0; i < indices.size(); ++i)
|
||||
if(indices.size()>0){
|
||||
for (auto i = 0; i < indices.size(); ++i)
|
||||
{
|
||||
clicked_points_3d->points.push_back(cloudPtr->points.at(indices[i]));
|
||||
}
|
||||
@@ -165,30 +182,40 @@ void pp_callback(const visualization::AreaPickingEvent& event, void* args)
|
||||
|
||||
pclData->getViewer()->addPointCloud(clicked_points_3d, red, cloudName);
|
||||
pclData->getViewer()->
|
||||
setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, cloudName);
|
||||
setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 10, cloudName);
|
||||
// pclData->getViewer()->updatePointCloud(clicked_points_3d,"cloudName");
|
||||
pclData->setIndices(indices);
|
||||
pclData->getUI().qvtkWidget->SetRenderWindow(pclData->getViewer()->getRenderWindow());
|
||||
pclData->getUI().qvtkWidget->update();
|
||||
}
|
||||
}
|
||||
|
||||
void Reconstruction::setCloud()
|
||||
{
|
||||
ui.label_9->setVisible(false);
|
||||
|
||||
if (loadingStatus)
|
||||
if(possionStatus)
|
||||
{
|
||||
cloud = t->getCloud();
|
||||
loadingStatus = false;
|
||||
}
|
||||
|
||||
if (reconstructStatus)
|
||||
auto pclData = PointCloudData::getInstance(cloud);
|
||||
pclData->getViewer()->removeAllPointClouds();
|
||||
pclData->getViewer()->addPolygonMesh(mesh, "my");
|
||||
possionStatus = false;
|
||||
}else
|
||||
{
|
||||
reconstructStatus = false;
|
||||
}
|
||||
cout << cloud[0].r;
|
||||
if (loadingStatus)
|
||||
{
|
||||
cloud = t->getCloud();
|
||||
loadingStatus = false;
|
||||
}
|
||||
|
||||
updateQVTK(cloud, color);
|
||||
if (reconstructStatus)
|
||||
{
|
||||
reconstructStatus = false;
|
||||
}
|
||||
cout << cloud[0].r;
|
||||
|
||||
updateQVTK(cloud, color);
|
||||
}
|
||||
}
|
||||
|
||||
void Reconstruction::updateQVTK(PointCloud<PointXYZRGB> cloud, QColor color)
|
||||
@@ -568,12 +595,18 @@ void Reconstruction::on_pushButton_4_clicked()
|
||||
}
|
||||
|
||||
ui.lineEdit->setText(fileName);
|
||||
|
||||
td->setPath(fileName.toStdString());
|
||||
// 投影结构光图案
|
||||
device->getProjector()->displayPattern(44);
|
||||
// device->getProjector()->displayPattern(44);
|
||||
// todo 接着进行投影操作
|
||||
}
|
||||
|
||||
// 投影图案
|
||||
void Reconstruction::on_pushButton_19_clicked()
|
||||
{
|
||||
device->getProjector()->displayPattern(44);
|
||||
}
|
||||
|
||||
// 相机拍照
|
||||
void Reconstruction::on_pushButton_9_clicked()
|
||||
{
|
||||
@@ -674,7 +707,9 @@ void Reconstruction::on_pushButton_17_clicked()
|
||||
// 异常点选择
|
||||
void Reconstruction::on_pushButton_11_clicked()
|
||||
{
|
||||
// todo 异常点选择
|
||||
QMessageBox::information(this, tr("QMessageBox::information()"),
|
||||
"Please press the 'X' in the keyboard to choose the outlier points!");
|
||||
|
||||
}
|
||||
|
||||
// 异常点剔除
|
||||
@@ -711,7 +746,7 @@ void Reconstruction::on_pushButton_13_clicked()
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(
|
||||
this, tr("open multiple image file"),
|
||||
"./", tr("PCD files(*.pcd);PLY files(*.ply);All files (*.*)")); // todo 文件类型待确认
|
||||
"./", tr("PCD files(*.pcd);;PLY files(*.ply);;All files (*.*)")); // todo 文件类型待确认
|
||||
|
||||
if (fileName.isEmpty())
|
||||
{
|
||||
@@ -733,36 +768,36 @@ void Reconstruction::on_pushButton_13_clicked()
|
||||
t->setPcd(fileName);
|
||||
t->start();
|
||||
loadingStatus = true;
|
||||
|
||||
// todo 存储文件或文件路径
|
||||
}
|
||||
|
||||
// 导出结果
|
||||
void Reconstruction::on_pushButton_14_clicked()
|
||||
{
|
||||
// todo 导出结果
|
||||
}
|
||||
|
||||
// 保存截图
|
||||
void Reconstruction::on_pushButton_15_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getSaveFileName(this,
|
||||
tr("save screen shot"),
|
||||
"",
|
||||
tr("*.png;; *.jpg;; *.bmp;; All files(*.*)"));
|
||||
|
||||
QString fileName=QFileDialog::getSaveFileName(this, tr("Save to file"),
|
||||
"./", tr("PCD files(*.pcd);;PLY files(*.ply);;All files (*.*)"));
|
||||
|
||||
if (!fileName.isNull())
|
||||
{
|
||||
// 截图所选的控件暂时用 label_17 替代
|
||||
QPixmap pix = QPixmap::grabWidget(ui.qvtkWidget);
|
||||
pix.save(fileName);
|
||||
if (fileName.endsWith(".pcd", Qt::CaseInsensitive))
|
||||
io::savePCDFileBinary(fileName.toStdString(), cloud);
|
||||
else if (fileName.endsWith(".ply", Qt::CaseInsensitive))
|
||||
io::savePLYFileBinary(fileName.toStdString(), cloud);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 泊松曲面重建
|
||||
void Reconstruction::on_pushButton_15_clicked()
|
||||
{
|
||||
ui.label_9->setVisible(true);
|
||||
QCoreApplication::processEvents();
|
||||
htd->start();
|
||||
possionStatus = true;
|
||||
}
|
||||
|
||||
// 颜色选取
|
||||
void Reconstruction::on_pushButton_16_clicked()
|
||||
{
|
||||
auto pclData = PointCloudData::getInstance(cloud);
|
||||
QColor colortmp = QColorDialog::getColor(Qt::black);
|
||||
if (colortmp.isValid())
|
||||
{
|
||||
@@ -777,4 +812,5 @@ void Reconstruction::on_pushButton_18_clicked()
|
||||
Help* help = new Help();
|
||||
help->show();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
#pragma endregion
|
||||
@@ -13,8 +13,19 @@
|
||||
#include "ui_Reconstruction.h"
|
||||
#include <pcl/point_types.h>
|
||||
#include <pcl/io/pcd_io.h>
|
||||
#include <pcl/io/ply_io.h>
|
||||
#include <pcl/io/png_io.h>
|
||||
#include <pcl/visualization/pcl_visualizer.h>
|
||||
#include <pcl/io/vtk_lib_io.h>
|
||||
#include <vtkOutputwindow.h>
|
||||
#include <pcl\filters\statistical_outlier_removal.h>
|
||||
#include <pcl/filters/voxel_grid.h>
|
||||
#include <pcl/common/transforms.h>
|
||||
#include <vector>
|
||||
#include <pcl/io/obj_io.h>
|
||||
#include <pcl/PolygonMesh.h>
|
||||
#include <pcl/features/normal_3d.h>
|
||||
#include <pcl/features/normal_3d_omp.h>
|
||||
#include <vtkRenderWindow.h>
|
||||
#include <QProgressDialog>
|
||||
#include "Camera.h"
|
||||
@@ -24,17 +35,19 @@
|
||||
#include "Calibrator.h"
|
||||
#include "CalibrationData.h"
|
||||
#include "Device.h"
|
||||
#include "HisThread.h"
|
||||
#include "CoreAlgorithm.h"
|
||||
#include "MyThread.h"
|
||||
#include "YourThread.h"
|
||||
#include "PointCloudData.h"
|
||||
#include "Help.h"
|
||||
#include <iostream>
|
||||
|
||||
using namespace pcl;
|
||||
using namespace std;
|
||||
|
||||
enum Role { ImageFilenameRole = Qt::UserRole, GrayImageRole, ColorImageRole };
|
||||
|
||||
class MyThread;
|
||||
class YourThread;
|
||||
|
||||
class Reconstruction : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -67,8 +80,11 @@ private:
|
||||
bool reconstructStatus = false; // 点云渲染
|
||||
|
||||
// 点云多线程
|
||||
MyThread* t;
|
||||
MyThread *t;
|
||||
HisThread* htd;
|
||||
PolygonMesh mesh;
|
||||
bool loadingStatus = false; // 点云渲染
|
||||
bool possionStatus = false;
|
||||
void setStyle();
|
||||
void setPicStyle();
|
||||
void setButtonStyle();
|
||||
@@ -93,6 +109,7 @@ private slots:
|
||||
void on_pushButton_16_clicked();
|
||||
void on_pushButton_17_clicked();
|
||||
void on_pushButton_18_clicked();
|
||||
void on_pushButton_19_clicked();
|
||||
void setPicAction(QString action);
|
||||
void setCloud();
|
||||
};
|
||||
@@ -48,7 +48,7 @@ void YourThread::run()
|
||||
kp.at<float>(i, j) = m3[i][j];
|
||||
|
||||
auto cArg = CameraArguments::getInstance(r, t, kc, kp);
|
||||
CoreAlgorithm testCase = CoreAlgorithm("./Data/image/reconstruction/tq.png", cArg);
|
||||
CoreAlgorithm testCase = CoreAlgorithm(path, cArg);
|
||||
testCase.run();
|
||||
vector<Mat> coordinates=testCase.getCoordinates();
|
||||
cloud->width = coordinates.size();
|
||||
@@ -66,4 +66,9 @@ void YourThread::run()
|
||||
|
||||
auto pclData = PointCloudData::getInstance(*cloud);
|
||||
pclData->setCloud(*cloud);
|
||||
}
|
||||
|
||||
void YourThread::setPath(string pathArg)
|
||||
{
|
||||
path = pathArg;
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <qthread.h>
|
||||
#include <pcl/point_types.h>
|
||||
#include <pcl/io/vtk_lib_io.h>
|
||||
#include "CoreAlgorithm.h"
|
||||
#include "PointCloudData.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -14,10 +13,13 @@ class YourThread :
|
||||
{
|
||||
public:
|
||||
YourThread(PointCloud<PointXYZRGB> *cloud);
|
||||
~YourThread(){};
|
||||
~YourThread(){}
|
||||
void setPath(string pathArg);
|
||||
|
||||
|
||||
private:
|
||||
PointCloud<PointXYZRGB> *cloud;
|
||||
string path;
|
||||
protected:
|
||||
void run();
|
||||
};
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
AllocConsole();//分配控制台
|
||||
freopen("CONOUT$", "w+t", stdout);//向控制台输出
|
||||
// AllocConsole();//分配控制台
|
||||
// freopen("CONOUT$", "w+t", stdout);//向控制台输出
|
||||
QApplication a(argc, argv);
|
||||
Loading l;
|
||||
l.show();
|
||||
|
||||
Reference in New Issue
Block a user