刚今天验收的实验,记录一下。
是比较基础的三维重建内容。
算是三维重建入门。
系统:windows
环境:visual studio 2013
语言:c++
相关:OpenCV 2、Kinect SDK 2.0、PCL库
内容:
使用Kinect 2.0拍摄获取深度图,将彩色图与深度图配准生成点云;
然后每次拍摄得到的点云用ICP算法进行融合,形成完整点云(每次拍摄仅做微小偏移);
之后稍微对点云做了些许处理;
还添加了回档的功能;
声明:
有挺多借鉴博客与参考资料的,太多懒得写,假装忘了~
原理:(以下不对变量作用作解释,具体可参照变量名猜测,完整代码最后给出)
流程图如下
1.关于彩色图与深度图的配准,官方文档给出了如下3个坐标系:
Kinect中总共有着3种坐标空间:
1.相机空间(Camera space):拥有三个坐标轴,假设kinect面朝正前方,那么X轴向左递增,Y轴向上递增,Z轴向前递增。
2.深度空间(Depth space):拥有三个坐标轴,其中x、y分别是深度图中像素的位置,z轴为像素的深度值。
3.色彩空间(Color space):拥有两个坐标轴,其中x、y分别是彩色图像中像素的位置。
由此,如果知道参数其实自己也能算,但是kinect事实上已经给出了函数。如下图所示
下图为单次生成的点云:
2.关于ICP算法点云配准:
它的本质思路如下:
1.计算两个点云之间的匹配关系;
2.计算旋转平移矩阵;
3.旋转平移源点云。
4.如果误差达到要求或者迭代次数够了,则退出,否则回到第一步。
具体实现可以参照原论文。
这里使用的是PCL库里自带的实现
接下来几幅图是点云融合过程(两个点云,慢慢融合)
融合效果:
3.点云处理,都是水水的实验性的处理,
1.第一种是简单的按照y轴进行颜色变换
2.第二种是根据高度生成水面
3.第三种是三角网格化
详情见代码
代码:
#ifndef KINECT_FXXL_H
#define KINECT_FXXL_H
#include <Kinect.h>
#endif
#include <Kinect.h>
#include "KinectFxxL.h"
#ifndef TEST_FXXL_H
#define TEST_FXXL_H
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
typedef unsigned short UINT16;
void showImage(Mat tmpMat, string windowName = "tmpImage");
Mat convertDepthToMat(const UINT16* pBuffer, int width, int height);
string convertIntToString(int num);
#endif
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include "OpenCVFxxL.h"
#define pause system("pause")
typedef unsigned short UINT16;
using namespace std;
using namespace cv;
void showImage(Mat tmpMat, string windowName)
{
imshow(windowName, tmpMat);
if (cvWaitKey(0) == 27) //ESC键值为27
return;
}
Mat convertDepthToMat(const UINT16* pBuffer, int width, int height)
{
Mat ret;
uchar* pMat;
ret = Mat(height, width, CV_8UC1);
pMat = ret.data; //uchar类型的指针,指向Mat数据矩阵的首地址
for (int i = 0; i < width*height; i++)
*(pMat + i) = *(pBuffer + i);
return ret;
}
string convertIntToString(int num)
{
string ret = "";
if (num < 0) return puts("the function only fits positive int number"), "";
while (num) ret += (num % 10) + '0', num /= 10;
reverse(ret.begin(), ret.end());
if (ret.size() == 0) ret += "0";
return ret;
}
#ifndef PCL_FXXL_H
#define PCL_FXXL_H
#include <time.h>
#include <stdlib.h>
#include <map>
#include <time.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <thread>
#include <mutex>
#include <queue>
#include <boost/make_shared.hpp> //boost指针相关头文件
#include <pcl/io/io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h> //点类型定义头文件
#include <pcl/point_cloud.h> //点云类定义头文件
#include <pcl/point_representation.h> //点表示相关的头文件
#include <pcl/io/pcd_io.h> //PCD文件打开存储类头文件
#include <pcl/filters/voxel_grid.h> //用于体素网格化的滤波类头文件
#include <pcl/filters/filter.h> //滤波相关头文件
#include <pcl/features/normal_3d.h> //法线特征头文件
#include <pcl/registration/icp.h> //ICP类相关头文件
#include <pcl/registration/icp_nl.h> //非线性ICP 相关头文件
#include <pcl/registration/transforms.h> //变换矩阵类头文件
#include <pcl/visualization/pcl_visualizer.h> //可视化类头文件
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/gp3.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <cv.h>
#include "OpenCVFxxL.h"
#define shapeCloud(x) x->width=1,x->height=x->size()
#define GAP_NORMAL 0.001
#define GAP_TRANSPARENT 0.005
#define random(x) (rand()%x)
using namespace cv;
using namespace std;
using namespace pcl;
using pcl::visualization::PointCloudColorHandlerGenericField;
using pcl::visualization::PointCloudColorHandlerCustom;
typedef PointXYZRGBA PointT;
typedef PointCloud<PointT> PointCloudT;
typedef PointXYZ PointX;
typedef PointCloud<PointX> PointCloudX;
typedef PointCloud<PointNormal> PointCloudWithNormals;
extern boost::shared_ptr<pcl::visualization::PCLVisualizer> visualizer;
extern bool iterationFlag_visualizer;
void makeBall(PointCloudT::Ptr cloud, double x_p, double y_p, double z_p, int r_color, int g_color, int b_color, double radius, double gap = GAP_NORMAL);
void makeWall(PointCloudT::Ptr cloud, double min_x, double max_x, double min_y, double max_y, double min_z, double max_z, int r_color, int g_color, int b_color, double gap = GAP_TRANSPARENT);
void getTriangles(const PointCloudT::Ptr cloud, PolygonMesh &triangles);
void getExCloud(const PointCloudT::Ptr cloud, PointCloudT::Ptr exCloud);
void filterCloud(PointCloudX::Ptr cloud, double size = 0.05);
void filterCloud(PointCloudT::Ptr cloud, double size = 0.05);
void showPolygonMesh(PolygonMesh polygonMesh);
void showPointCloudX(PointCloudX::Ptr cloud0);
void showPointCloudT(PointCloudT::Ptr cloud0, PointCloudT::Ptr cloud1 = NULL);
void showTransform(const PointCloudWithNormals::Ptr targetCloud, const PointCloudWithNormals::Ptr sourceCloud);
void keyBoardEventOccurred(const pcl::visualization::KeyboardEvent& event, void *nothing);
void initVisualizer();
void cloudMerge(const PointCloudT::Ptr cloudSrc, const PointCloudT::Ptr cloudTgt, PointCloudT::Ptr cloudRet, Eigen::Matrix4f &transformingMatrix, bool flag_slow, bool filterFlag = true);
class PointRepresentationT :public PointRepresentation<PointNormal>
{
using PointRepresentation<PointNormal>::nr_dimensions_;
public:
PointRepresentationT();
virtual void copyToFloatArray(const PointNormal &p, float *out) const;
};
#endif
#include <time.h>
#include <stdlib.h>
#include <map>
#include <time.h>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <thread>
#include <mutex>
#include <queue>
#include <boost/make_shared.hpp> //boost指针相关头文件
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h> //点类型定义头文件
#include <pcl/point_cloud.h> //点云类定义头文件
#include <pcl/point_representation.h> //点表示相关的头文件
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h> //PCD文件打开存储类头文件
#include <pcl/filters/voxel_grid.h> //用于体素网格化的滤波类头文件
#include <pcl/filters/filter.h> //滤波相关头文件
#include <pcl/features/normal_3d.h> //法线特征头文件
#include <pcl/registration/icp.h> //ICP类相关头文件
#include <pcl/registration/icp_nl.h> //非线性ICP 相关头文件
#include <pcl/registration/transforms.h> //变换矩阵类头文件
#include <pcl/visualization/pcl_visualizer.h> //可视化类头文件
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/surface/gp3.h>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <cv.h>
#include "OpenCVFxxL.h"
#include "PCLFxxL.h"
boost::shared_ptr<pcl::visualization::PCLVisualizer> visualizer(new pcl::visualization::PCLVisualizer("fxxl"));
bool iterationFlag_visualizer;
void makeBall(PointCloudT::Ptr cloud, double x_p, double y_p, double z_p, int r_color, int g_color, int b_color, double radius, double gap)
{
for (double x = x_p - radius; x <= x_p + radius; x += gap)
{
double tmp0 = sqrt(radius*radius - (x - x_p)*(x - x_p));
for (double y = y_p - tmp0; y <= y_p + tmp0; y += gap)
{
double z = z_p + sqrt(radius*radius - (x - x_p)*(x - x_p) - (y - y_p)*(y - y_p));
PointT tmpPoint;
tmpPoint.x = x, tmpPoint.y = y, tmpPoint.z = z, tmpPoint.r = r_color, tmpPoint.g = g_color, tmpPoint.b = b_color;
cloud->points.push_back(tmpPoint);
}
}
cout << cloud->points.size() << endl;
}
void makeWall(PointCloudT::Ptr cloud, double min_x, double max_x, double min_y, double max_y, double min_z, double max_z, int r_color, int g_color, int b_color, double gap)
{
for (double x = min_x; x <= max_x; x += gap)
for (double y = min_y; y <= max_y; y += gap)
for (double z = min_z; z <= max_z; z += gap)
{
PointT tmpPoint;
tmpPoint.x = x, tmpPoint.y = y, tmpPoint.z = z, tmpPoint.r = r_color, tmpPoint.g = g_color, tmpPoint.b = b_color;
cloud->points.push_back(tmpPoint);
}
}
void getTriangles(const PointCloudT::Ptr cloud, PolygonMesh &triangles)
{
PointCloudX::Ptr tmpCloud(new PointCloudX);
tmpCloud->clear();
for (int i = 0; i < cloud->points.size(); i++)
{
PointX tmpPointX;
tmpPointX.x = cloud->points[i].x, tmpPointX.y = cloud->points[i].y, tmpPointX.z = cloud->points[i].z;
tmpCloud->points.push_back(tmpPointX);
}
shapeCloud(tmpCloud);
filterCloud(tmpCloud, 0.04);
NormalEstimation<PointX, Normal> normalEstimation;
PointCloud<Normal>::Ptr normalCloud(new PointCloud<Normal>);
search::KdTree<PointX>::Ptr kdTree(new search::KdTree<PointX>);
kdTree->setInputCloud(tmpCloud);
normalEstimation.setInputCloud(tmpCloud);
normalEstimation.setSearchMethod(kdTree);
normalEstimation.setKSearch(20);
normalEstimation.compute(*normalCloud);
PointCloud<PointNormal>::Ptr pointWithNormalCloud(new PointCloud<PointNormal>);
pcl::concatenateFields(*tmpCloud, *normalCloud, *pointWithNormalCloud);
search::KdTree<PointNormal>::Ptr kdTree2(new search::KdTree<PointNormal>);
kdTree2->setInputCloud(pointWithNormalCloud);
GreedyProjectionTriangulation<PointNormal> gp3;
gp3.setSearchRadius(0.24);
gp3.setMu(2.5);
gp3.setMaximumNearestNeighbors(100); //邻近点阈值
gp3.setMaximumSurfaceAngle(M_PI / 4); //45度;两点的法向量角度差大于此值,这两点将不会连接成三角形
gp3.setMinimumAngle(M_PI / 18); //三角形的最小角度
gp3.setMaximumAngle(2 * M_PI / 3);
gp3.setNormalConsistency(false);
gp3.setInputCloud(pointWithNormalCloud);
gp3.setSearchMethod(kdTree2);
gp3.reconstruct(triangles);
// vector<int> partIDs = gp3.getPartIDs();
// vector<int> states = gp3.getPointStates();
}
void getExCloud(const PointCloudT::Ptr cloud, PointCloudT::Ptr exCloud)
{
string op;
puts("\nOwO\ninput:\n 1.ex1: transform ex1;\n 2.ex2: transform ex2.\nOwO\n");
cin >> op;
if (op.compare("ex1") == 0)
{
exCloud->points.clear(), *exCloud += *cloud, shapeCloud(exCloud);
double max_x, min_x, max_y, min_y, max_z, min_z, colorStep_y, tmpColorValue;
max_x = max_y = max_z = -1e9 - 44, min_x = min_y = min_z = 1e9 + 44;
for (int i = 0; i < exCloud->points.size(); i++)
max_y = max(max_y, 1.0*exCloud->points[i].y), min_y = min(min_y, 1.0*exCloud->points[i].y);
colorStep_y = 255.0 / (max_y - min_y);
for (int i = 0; i < exCloud->points.size(); i++)
{
tmpColorValue = (exCloud->points[i].y - min_y)*colorStep_y;
exCloud->points[i].r = tmpColorValue, exCloud->points[i].g = tmpColorValue*2.0 / 3, exCloud->points[i].b = 0;
}
shapeCloud(exCloud);
}
else if (op.compare("ex2") == 0)
{
exCloud->clear(), *exCloud += *cloud, shapeCloud(exCloud);
const int r_color0 = 12, g_color0 = 74, b_color0 = 82;
double max_x, min_x, max_y, min_y, max_z, min_z, colorStep_z, tmpColorValue, y_surface;
max_x = max_y = max_z = -1e9 - 44, min_x = min_y = min_z = 1e9 + 44;
for (int i = 0; i < exCloud->points.size(); i++)
{
max_x = max(max_x, 1.0*exCloud->points[i].x), min_x = min(min_x, 1.0*exCloud->points[i].x);
max_y = max(max_y, 1.0*exCloud->points[i].y), min_y = min(min_y, 1.0*exCloud->points[i].y);
max_z = max(max_z, 1.0*exCloud->points[i].z), min_z = min(min_z, 1.0*exCloud->points[i].z);
}
y_surface = min_y + (max_y - min_y) / 3.0 * 2;
makeWall(exCloud, min_x, min_x, min_y, y_surface, min_z, max_z, r_color0, g_color0, b_color0);
makeWall(exCloud, max_x, max_x, min_y, y_surface, min_z, max_z, r_color0, g_color0, b_color0);
makeWall(exCloud, min_x, max_x, min_y, min_y, min_z, max_z, r_color0, g_color0, b_color0);
makeWall(exCloud, min_x, max_x, min_y, y_surface, min_z, min_z, r_color0, g_color0, b_color0);
makeWall(exCloud, min_x, max_x, min_y, y_surface, max_z, max_z, r_color0, g_color0, b_color0);
Mat imageMat_water = imread("res\\water_surface.jpg");
// showImage(imageMat_water);
double x_image = imageMat_water.rows - 4, z_image = imageMat_water.cols - 4, x_cloud = max_x - min_x, z_cloud = max_z - min_z;
if (z_image / x_image > z_cloud / x_cloud)
z_image = x_image * (z_cloud / x_cloud);
else x_image = z_image / (z_cloud / x_cloud);
double step_x = x_image / x_cloud, step_z = z_image / z_cloud;
for (double x = min_x; x <= max_x; x += GAP_NORMAL)
for (double z = min_z; z <= max_z; z += GAP_NORMAL)
{
PointT tmpPoint;
int x_tmp = (int)(step_x*(x - min_x)), z_tmp = (int)(step_z*(z - min_z));
x_tmp = max(0, x_tmp), x_tmp = min(imageMat_water.rows - 1, x_tmp), z_tmp = max(0, z_tmp), z_tmp = min(imageMat_water.cols - 1, z_tmp);
tmpPoint.x = x, tmpPoint.y = y_surface, tmpPoint.z = z;
tmpPoint.r = imageMat_water.at<Vec3b>(x_tmp, z_tmp)[2];
tmpPoint.g = imageMat_water.at<Vec3b>(x_tmp, z_tmp)[1];
tmpPoint.b = imageMat_water.at<Vec3b>(x_tmp, z_tmp)[0];
exCloud->points.push_back(tmpPoint);
}
shapeCloud(exCloud);
}
else if (op.compare("ex3") == 0)
{
puts("\nOAO\ninvalid input, retry please\nOAO\n");
getExCloud(cloud, exCloud);
/*
srand((int)time(0));
const int r_color0 = 204, g_color0 = 207, b_color0 = 190, r_color1 = 94, g_color1 = 87, b_color1 = 46, r_color2 = 22, g_color2 = 35, b_color2 = 44, r_colorBas = 255, g_colorBas = 223, b_colorBas = 178;
const int rateBound_color0 = 14, rateBound_color1 = 70, rateBound_color2 = 100,rateBound_colorBas=200;
double max_x, min_x, max_y, min_y, max_z, min_z, colorStep_z, tmpColorValue, z_surface;
max_x = max_y = max_z = -1e9 - 44, min_x = min_y = min_z = 1e9 + 44;
for (int i = 0; i < exCloud->points.size(); i++)
{
max_x = max(max_x, 1.0*exCloud->points[i].x), min_x = min(min_x, 1.0*exCloud->points[i].x);
max_y = max(max_y, 1.0*exCloud->points[i].y), min_y = min(min_y, 1.0*exCloud->points[i].y);
max_z = max(max_z, 1.0*exCloud->points[i].z), min_z = min(min_z, 1.0*exCloud->points[i].z);
}
for (int i = 0; i < exCloud->points.size(); i++)
exCloud->points[i].r = r_colorBas, exCloud->points[i].g = g_colorBas, exCloud->points[i].b = b_colorBas;
int tmpSize_exCloud = exCloud->points.size();
for (int i = 0; i < tmpSize_exCloud; i++)
makeBall(exCloud, exCloud->points[i].x, exCloud->points[i].y, exCloud->points[i].z, r_colorBas, g_colorBas, b_colorBas, random(100000) / 100000.0*0.02);
map<double, bool> mp; mp.clear();
const double sed0 = 16123512.0, sed1 = 743243.0, sed2 = 6143134.0;
const double x_sun=0, y_sun=max_y*1.74, z_sun=0;
vector<double> energy; energy.clear();
double k0, k1, k2, ktmp, kdis;
for (int i = 0; i < exCloud->points.size(); i++)
{
k0 = x_sun - exCloud->points[i].x, k1 = y_sun - exCloud->points[i].y, k2 = z_sun - exCloud->points[i].z;
kdis = sqrt(k0*k0 + k1*k1 + k2*k2), k0 /= kdis, k1 /= kdis, k2 /= kdis;
ktmp = sed0*(int)(k0 * 2000) + sed1*(int)(k1 * 2000) + sed2*(int)(k2 * 2000);
if (mp[ktmp]) energy.push_back(0);
else
{
exCloud->points[i].r = r_color0, exCloud->points[i].g = g_color0, exCloud->points[i].b = b_color0;
energy.push_back(1 / (kdis*kdis*kdis));
}
mp[ktmp] = 1;
}
shapeCloud(exCloud);
*/
}
else
{
puts("\nOAO\ninvalid input, retry please\nOAO\n");
getExCloud(cloud, exCloud);
}
}
void filterCloud(PointCloudX::Ptr cloud, double size)
{
VoxelGrid<PointX> voxelGrid;
voxelGrid.setLeafSize(size, size, size);
voxelGrid.setInputCloud(cloud), voxelGrid.filter(*cloud);
printf("cloud size now : %d\n", cloud->size());
}
void filterCloud(PointCloudT::Ptr cloud, double size)
{
VoxelGrid<PointT> voxelGrid;
voxelGrid.setLeafSize(size, size, size);
voxelGrid.setInputCloud(cloud), voxelGrid.filter(*cloud);
printf("cloud size now : %d\n", cloud->size());
}
void showPolygonMesh(PolygonMesh polygonMesh)
{
visualizer->addPolygonMesh(polygonMesh, "PolygonMesh0");
// visualizer->addCoordinateSystem(1.0);
// visualizer->initCameraParameters();
iterationFlag_visualizer = false;
while (!iterationFlag_visualizer) visualizer->spinOnce();
visualizer->removePolygonMesh("PolygonMesh0");
}
void showPointCloudX(PointCloudX::Ptr cloud0)
{
visualizer->addPointCloud(cloud0, "Cloud0");
iterationFlag_visualizer = false;
while (!iterationFlag_visualizer) visualizer->spinOnce();
visualizer->removePointCloud("Cloud0");
}
void showPointCloudT(PointCloudT::Ptr cloud0, PointCloudT::Ptr cloud1)
{
visualizer->addPointCloud(cloud0, "Cloud0");
if (cloud1 != NULL) visualizer->addPointCloud(cloud1, "Cloud1");
iterationFlag_visualizer = false;
while (!iterationFlag_visualizer) visualizer->spinOnce();
visualizer->removePointCloud("Cloud0");
if (cloud1 != NULL) visualizer->removePointCloud("Cloud1");
}
void showTransform(const PointCloudWithNormals::Ptr targetCloud, const PointCloudWithNormals::Ptr sourceCloud)
{
PointCloudColorHandlerGenericField<PointNormal> colorHandler_target(targetCloud, "curvature");
if (!colorHandler_target.isCapable()) PCL_WARN("colorHandler_target error~");
PointCloudColorHandlerGenericField<PointNormal> colorHandler_source(sourceCloud, "curvature");
if (!colorHandler_source.isCapable()) PCL_WARN("colorHandler_source error~");
visualizer->addPointCloud(targetCloud, colorHandler_target, "targetCloud");
visualizer->addPointCloud(sourceCloud, colorHandler_source, "sourceCloud");
iterationFlag_visualizer = false;
while (!iterationFlag_visualizer) visualizer->spinOnce();
visualizer->removePointCloud("targetCloud");
visualizer->removePointCloud("sourceCloud");
}
void keyBoardEventOccurred(const pcl::visualization::KeyboardEvent& event, void *nothing)
{
if (event.getKeySym() == "space" && event.keyDown())
iterationFlag_visualizer = true;
}
void initVisualizer()
{
visualizer->registerKeyboardCallback(&keyBoardEventOccurred, (void*)NULL);
visualizer->setBackgroundColor(246.0 / 255, 175.0 / 255, 245.0 / 255);
// visualizer->setBackgroundColor(255.0 / 255, 255.0 / 255, 255.0 / 255);
}
// cloudRet 为 cloudTgt 反向转到与 cloudSrc 匹配后得到的点云
// transformingMatrix 为 cloudTgt 反向转到与 cloudSrc 匹配的时的矩阵
void cloudMerge(const PointCloudT::Ptr cloudSrc, const PointCloudT::Ptr cloudTgt, PointCloudT::Ptr cloudRet, Eigen::Matrix4f &transformingMatrix, bool flag_slow, bool filterFlag)
{
PointCloudT::Ptr src(new PointCloudT);
PointCloudT::Ptr tgt(new PointCloudT);
src->clear(), tgt->clear();
*src += *cloudSrc, *tgt += *cloudTgt;
if (filterFlag)
filterCloud(src), filterCloud(tgt);
printf("final size: %d %d \n", src->size(), tgt->size());
PointCloudWithNormals::Ptr src_pointsWithNormals(new PointCloudWithNormals);
PointCloudWithNormals::Ptr tgt_pointsWithNormals(new PointCloudWithNormals);
NormalEstimation<PointT, PointNormal> normalEstimation;
search::KdTree<PointT>::Ptr kdtree(new search::KdTree<PointT>());
normalEstimation.setSearchMethod(kdtree);
normalEstimation.setKSearch(30);
normalEstimation.setInputCloud(src), normalEstimation.compute(*src_pointsWithNormals), copyPointCloud(*src, *src_pointsWithNormals);
normalEstimation.setInputCloud(tgt), normalEstimation.compute(*tgt_pointsWithNormals), copyPointCloud(*tgt, *tgt_pointsWithNormals);
//配准
IterativeClosestPointNonLinear<PointNormal, PointNormal> reg;
reg.setTransformationEpsilon(1e-6);
reg.setMaxCorrespondenceDistance(0.1); //对应点最大距离0.1m
float tmpFloatValueArray[4] = { 1.0, 1.0, 1.0, 1.0 };
PointRepresentationT pointRepresentationT;
pointRepresentationT.setRescaleValues(tmpFloatValueArray);
reg.setPointRepresentation(boost::make_shared<const PointRepresentationT>(pointRepresentationT));
reg.setInputCloud(src_pointsWithNormals);
reg.setInputTarget(tgt_pointsWithNormals);
if (flag_slow)
{
string op;
reg.setMaximumIterations(2);
Eigen::Matrix4f fin, prev, inv;
fin = Eigen::Matrix4f::Identity(); //单位矩阵
PointCloudWithNormals::Ptr tmpCloud = src_pointsWithNormals;
for (int i = 0;; i++)
{
PCL_INFO("No. %d\n", i);
src_pointsWithNormals = tmpCloud, reg.setInputCloud(src_pointsWithNormals);
reg.align(*tmpCloud);
fin = reg.getFinalTransformation()*fin;
if (i>0 && fabs((reg.getLastIncrementalTransformation() - prev).sum()) < reg.getTransformationEpsilon())
reg.setMaxCorrespondenceDistance(reg.getMaxCorrespondenceDistance() - 0.001);
prev = reg.getLastIncrementalTransformation();
showTransform(tgt_pointsWithNormals, src_pointsWithNormals);
puts("\nOwO\ninput:\n 1.continue: continue to the next transformation;\n 2.break: stop transformation;\nOwO\n");
cin >> op;
if (op.compare("continue") == 0) continue;
else if (op.compare("break") == 0) break;
else puts("\nOAO\ninvalid input, retry please\nOAO\n");
}
inv = fin.inverse(); //从目标点云到源点云的变换
transformPointCloud(*cloudTgt, *cloudRet, inv);
showPointCloudT(cloudSrc, cloudRet);
transformingMatrix = inv;
}
else
{
int maximumIterations_input = 30;
puts("\nOwO\ninput the maximum iterations (1 ~ 200), please\nOwO\n");
scanf("%d", &maximumIterations_input);
maximumIterations_input = max(maximumIterations_input, 1), maximumIterations_input = min(maximumIterations_input, 30);
reg.setMaximumIterations(maximumIterations_input);
PointCloudWithNormals::Ptr tmpCloud = src_pointsWithNormals;
Eigen::Matrix4f fin, inv;
reg.align(*tmpCloud);
fin = reg.getFinalTransformation();
inv = fin.inverse(); //从目标点云到源点云的变换
transformPointCloud(*cloudTgt, *cloudRet, inv);
showPointCloudT(cloudSrc, cloudRet);
transformingMatrix = inv;
}
}
PointRepresentationT::PointRepresentationT()
{
nr_dimensions_ = 4;
}
void PointRepresentationT::copyToFloatArray(const PointNormal &p, float *out) const
{
out[0] = p.x, out[1] = p.y, out[2] = p.z, out[3] = p.curvature;
}
#define _CRT_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#include <time.h>
#include <stdlib.h>
#include "kinect.h"
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/opencv.hpp>
#include <cv.h>
#include <GLFW\glfw3.h>
#include <gl/glut.h>
#include <thread>
#include <mutex>
#include <queue>
#include <boost/make_shared.hpp> //boost指针相关头文件
#include <pcl/io/io.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/point_types.h> //点类型定义头文件
#include <pcl/point_cloud.h> //点云类定义头文件
#include <pcl/point_representation.h> //点表示相关的头文件
#include <pcl/io/pcd_io.h> //PCD文件打开存储类头文件
#include <pcl/filters/voxel_grid.h> //用于体素网格化的滤波类头文件
#include <pcl/filters/filter.h> //滤波相关头文件
#include <pcl/features/normal_3d.h> //法线特征头文件
#include <pcl/registration/icp.h> //ICP类相关头文件
#include <pcl/registration/icp_nl.h> //非线性ICP 相关头文件
#include <pcl/registration/transforms.h> //变换矩阵类头文件
#include <pcl/visualization/pcl_visualizer.h> //可视化类头文件
#include "OpenCVFxxL.h"
#include "KinectFxxL.h"
#include "PCLFxxL.h"
#define check_hr(x) if(hr<0) return false
#define pause system("pause")
using namespace cv;
using namespace std;
using namespace pcl;
using pcl::visualization::PointCloudColorHandlerGenericField;
using pcl::visualization::PointCloudColorHandlerCustom;
typedef PointXYZRGBA PointT;
typedef PointCloud<PointT> PointCloudT;
typedef PointXYZ PointX;
typedef PointCloud<PointX> PointCloudX;
typedef PointCloud<PointNormal> PointCloudWithNormals;
const int n_depth = 424;
const int m_depth = 512;
const int n_color = 1080;
const int m_color = 1920;
HRESULT hr;
IKinectSensor *pKinectSensor;
ICoordinateMapper *pCoordinateMapper;
IDepthFrameReader *pDepthFrameReader;
IColorFrameReader *pColorFrameReader;
IDepthFrame *pDepthFrame = NULL;
IColorFrame *pColorFrame = NULL;
IFrameDescription *pFrameDescription = NULL;
IDepthFrameSource *pDepthFrameSource = NULL;
IColorFrameSource *pColorFrameSource = NULL;
USHORT depthMinReliableDistance, depthMaxReliableDistance;
UINT bufferSize_depth, bufferSize_color;
UINT16 *pBuffer_depth = NULL;
uchar *pBuffer_color = NULL;
ColorImageFormat imageFormat_color;
int width_depth, height_depth, width_color, height_color;
DepthSpacePoint *pDepthSpace = NULL;
ColorSpacePoint *pColorSpace = NULL;
CameraSpacePoint *pCameraSpace = NULL;
UINT16 *image_depth;
BYTE *image_color;
Mat imageMat_depth, imageMat_color;
PointCloudT::Ptr cloud(new PointCloudT), prevCloud(new PointCloudT), finCloud(new PointCloudT), tmpCloud(new PointCloudT), lastFinCloud(new PointCloudT), lastPrevCloud(new PointCloudT);
int cnt_image;
bool getDepthImage()
{
pDepthFrame = NULL;
while (hr < 0 || pDepthFrame == NULL)
hr = pDepthFrameReader->AcquireLatestFrame(&pDepthFrame);
hr = pDepthFrame->get_FrameDescription(&pFrameDescription); check_hr(hr);
pFrameDescription->get_Width(&width_depth); pFrameDescription->get_Height(&height_depth);
hr = pDepthFrame->get_DepthMinReliableDistance(&depthMinReliableDistance); check_hr(hr);
hr = pDepthFrame->get_DepthMaxReliableDistance(&depthMaxReliableDistance); check_hr(hr);
pDepthFrame->AccessUnderlyingBuffer(&bufferSize_depth, &pBuffer_depth);
imageMat_depth = convertDepthToMat(pBuffer_depth, width_depth, height_depth);
hr = pDepthFrame->CopyFrameDataToArray(bufferSize_depth, image_depth);
pDepthFrame->Release();
// equalizeHist(imageMat_depth, imageMat_depth);
return true;
}
bool getColorImage()
{
pColorFrame = NULL;
while (hr < 0 || pColorFrame == NULL)
hr = pColorFrameReader->AcquireLatestFrame(&pColorFrame);
hr = pColorFrame->get_FrameDescription(&pFrameDescription); check_hr(hr);
pFrameDescription->get_Width(&width_color); pFrameDescription->get_Height(&height_color);
imageMat_color = Mat(height_color, width_color, CV_8UC4);
pBuffer_color = imageMat_color.data; bufferSize_color = width_color * height_color * 4;
hr = pColorFrame->CopyConvertedFrameDataToArray(bufferSize_color, reinterpret_cast<BYTE*>(pBuffer_color), ColorImageFormat::ColorImageFormat_Bgra);
hr = pColorFrame->CopyConvertedFrameDataToArray(bufferSize_color, image_color, ColorImageFormat::ColorImageFormat_Bgra);
pColorFrame->Release();
return true;
}
bool getPoints(bool flag_slow)
{
hr = pCoordinateMapper->MapDepthFrameToColorSpace(n_depth*m_depth, image_depth, n_depth*m_depth, pColorSpace); check_hr(hr);
hr = pCoordinateMapper->MapDepthFrameToCameraSpace(n_depth*m_depth, image_depth, n_depth*m_depth, pCameraSpace); check_hr(hr);
CameraSpacePoint p_camera;
ColorSpacePoint p_color;
PointT p;
int cnt = 0, px_color, py_color;
for (int i = 0; i < n_depth*m_depth; i++)
{
p_camera = pCameraSpace[i];
p_color = pColorSpace[i];
px_color = (int)(p_color.X + 0.5), py_color = (int)(p_color.Y + 0.5);
if (px_color >= 0 && px_color < m_color && py_color >= 0 && py_color < n_color)
{
cnt++;
p.b = image_color[(py_color*m_color + px_color) * 4], p.g = image_color[(py_color*m_color + px_color) * 4 + 1], p.r = image_color[(py_color*m_color + px_color) * 4 + 2];
p.x = p_camera.X, p.y = p_camera.Y, p.z = p_camera.Z;
cloud->points.push_back(p);
}
}
printf("number of points: %d\n", cnt);
shapeCloud(cloud);
showPointCloudT(cloud);
if (cnt_image)
{
Eigen::Matrix4f transformingMatrix;
cloudMerge(prevCloud, cloud, tmpCloud, transformingMatrix, flag_slow);
cloud->clear(), *cloud += *tmpCloud, shapeCloud(cloud);
}
lastPrevCloud->points.clear(), *lastPrevCloud += *prevCloud, shapeCloud(lastPrevCloud);
lastFinCloud->points.clear(), *lastFinCloud += *finCloud, shapeCloud(lastFinCloud);
prevCloud->points.clear(), *prevCloud += *cloud, shapeCloud(prevCloud);
*finCloud += *cloud, shapeCloud(finCloud);
filterCloud(finCloud, 0.002), shapeCloud(finCloud);
cloud->points.clear();
return true;
}
void init()
{
cnt_image = 0;
finCloud->clear();
initVisualizer();
pColorSpace = new ColorSpacePoint[n_depth*m_depth];
pCameraSpace = new CameraSpacePoint[n_depth*m_depth];
image_color = new BYTE[n_color*m_color * 4];
image_depth = new UINT16[n_depth*m_depth];
}
bool start()
{
String op;
hr = GetDefaultKinectSensor(&pKinectSensor); check_hr(hr);
hr = pKinectSensor->Open(); check_hr(hr);
hr = pKinectSensor->get_CoordinateMapper(&pCoordinateMapper); check_hr(hr);
hr = pKinectSensor->get_DepthFrameSource(&pDepthFrameSource); check_hr(hr);
hr = pDepthFrameSource->OpenReader(&pDepthFrameReader); check_hr(hr);
hr = pKinectSensor->get_ColorFrameSource(&pColorFrameSource); check_hr(hr);
hr = pColorFrameSource->OpenReader(&pColorFrameReader); check_hr(hr);
while (1)
{
bool flag_slow;
puts("\nOwO\ninput:\n 1.work_slow: get next cloud and show every step in transform;\n 2.work: get next cloud;\n 3.exit: exit this program;\n 4.show: show final cloud;\n 5.show_ex: show final cloud with some change;\n 6.show_triangles: show the triangles;\n 7.back: back to the cloud.\nOwO\n");
cin >> op;
if (op.compare("exit") == 0) return true;
else if (op.compare("work") == 0 || op.compare("work_slow") == 0)
{
if (op.compare("work_slow") == 0) flag_slow = true; else flag_slow = false;
if (getDepthImage() == false) return false;
if (getColorImage() == false) return false;
imwrite("tmp\\" + convertIntToString(cnt_image) + "_image_depth.jpg", imageMat_depth);
// showImage(imageMat_depth);
imwrite("tmp\\" + convertIntToString(cnt_image) + "_image_color.jpg", imageMat_color);
// showImage(imageMat_color);
if (!getPoints(flag_slow)) return puts("\nOAO\nget points failed\nOAO\n"), false;
cnt_image++;
}
else if (op.compare("show") == 0)
showPointCloudT(finCloud);
else if (op.compare("show_ex") == 0)
{
PointCloudT::Ptr exFinCloud(new PointCloudT);
getExCloud(finCloud, exFinCloud);
showPointCloudT(exFinCloud);
}
else if (op.compare("show_triangles") == 0)
{
PolygonMesh triangles;
getTriangles(finCloud, triangles);
showPolygonMesh(triangles);
}
else if (op.compare("back") == 0)
{
finCloud->clear(), *finCloud += *lastFinCloud, shapeCloud(finCloud);
prevCloud->clear(), *prevCloud += *lastPrevCloud, shapeCloud(prevCloud);
puts("OwO finished");
}
else puts("\nOAO\ninvalid input, retry please\nOAO\n");
}
return true;
}
int main()
{
init();
if (!start()) return puts("\nOAO\ninit failed\nOAO\n"), 0;
puts("\nOwO\nprogram ends\nOwO\n");
pause;
return 0;
}
来源:oschina
链接:https://my.oschina.net/u/4391746/blog/3945684