刚今天验收的实验,记录一下。
是比较基础的三维重建内容。
算是三维重建入门。
系统: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.第三种是三角网格化
详情见代码
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#ifndef KINECT_FXXL_H #define KINECT_FXXL_H #include <Kinect.h> #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#include <Kinect.h> #include "KinectFxxL.h"
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#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
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#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; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
#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, in