利用Kinect深度图像生成三维点

Kinect实现简单的三维重建  + code (aipiano csdn)

1. 相机针孔模型

首先,我们来介绍一下相机针孔模型 。如下图所示,$ P = (X,Y,Z)^T \in \mathbb{R}^3 $ 是空间中的一个点,$p = (x,y)^T \in \mathbb{R}^2$是其对应图像中的点。为了简化模型,这里图像中心在相机的光学中心上,如图。

利用Kinect深度图像生成三维点_第1张图片

这里有两个坐标系,分别是相机坐标系$XYZ$ 和图像坐标系$ xy $。这里点$ P = (X,Y,Z)^T $$p = (x,y)^T$是随机的(存在映射关系)。

在数学上,简化这个图形,如下:

利用Kinect深度图像生成三维点_第2张图片

f是焦距(光学中心和像平面的距离),由截线定理 可知:


把以上两个公式,写成向量的形式:

2. 齐次坐标系

1.把一个点P映射到齐次坐标系

2.齐次坐标系的等价性:

3. 在齐次坐标系中的一个点P,有如下性质:

以上是齐次坐标系的性质。下面我们会用到。

下面我们利用公式(2),把我们的点映射到齐次坐标系中:
利用Kinect深度图像生成三维点_第3张图片
这里$s \in \mathbb{R} \setminus \{0\}$类似于公式(3)中的参数。我们把这个等式,写成如下形式:
利用Kinect深度图像生成三维点_第4张图片

3. 像点偏移

我们假设图像坐标系的原点在图像的中心,但是通常的情况并非如此,因此我们需要添加一个偏移量。

4. 像素单位

直到现在, $ f, \hat{c}_x $  和  $ \hat{c}_y $用的都是单位长度,但是这并不适合于像素相关的数字图像,因此,我们引入   $ k_x $  和  $ k_y $,这里   $ k_x $  和  $ k_y $是x-和y-方向每单位长度的像素数量 ([pixel/length])。然后我们就可以用像素作为单位:

然后可以重写上面的公式:
利用Kinect深度图像生成三维点_第5张图片
这里 C 为相机内参矩阵:

5. 转换

最后,我们需要考虑不同位置、方向的深度-- 、彩色--  相机。我们利用一个包含旋转和变换的矩阵,来实现两个坐标系的转换,这个矩阵可以写为如下形式:

现在我们可以扩展公式(5):
利用Kinect深度图像生成三维点_第6张图片

6. 总结

利用Kinect深度图像生成三维点_第7张图片

describes the relation between a threedimensional point in space $ P = (X,Y,Z)^T \in \mathbb{R}^3 $ captured by a camera and its equivalent, twodimensional point $p = (x,y)^T \in \mathbb{R}^2$ at the image plane.

The parameters are called:

  • $ \mathbf{C} $intrisic parameters or intrinsics
  • $ \mathbf{T} $extrinsic parameters or extrinsics

It is important to understand, that our model (excepted the transformation) has been derived for one general camera. In context of Kinect you have seperate intrinsics for the depth- and RGB-camera!

In addation, we used the transformation to combine the coordinate systems of the depth- and RGB-camera. That implicates, that we only have got one transformation-matrix.

The application of our model/formula in context of Kinect is explained at class-description.


CODE:

// C++ 标准库
#include 
#include 
using namespace std;

// OpenCV 库
#include 
#include 

// PCL 库
#include 
#include 

// 定义点云类型
typedef pcl::PointXYZRGBA PointT;
typedef pcl::PointCloud PointCloud; 

// 相机内参
const double camera_factor = 1000;
const double camera_cx = 325.5;
const double camera_cy = 253.5;
const double camera_fx = 518.0;
const double camera_fy = 519.0;

// 主函数 
int main( int argc, char** argv )
{
    // 读取./data/rgb.png和./data/depth.png,并转化为点云

    // 图像矩阵
    cv::Mat rgb, depth;
    // 使用cv::imread()来读取图像
    // API: http://docs.opencv.org/modules/highgui/doc/reading_and_writing_images_and_video.html?highlight=imread#cv2.imread
    rgb = cv::imread( "./data/rgb.png" );
    // rgb 图像是8UC3的彩色图像
    // depth 是16UC1的单通道图像,注意flags设置-1,表示读取原始数据不做任何修改
    depth = cv::imread( "./data/depth.png", -1 );

    // 点云变量
    // 使用智能指针,创建一个空点云。这种指针用完会自动释放。
    PointCloud::Ptr cloud ( new PointCloud );
    // 遍历深度图
    for (int m = 0; m < depth.rows; m++)
        for (int n=0; n < depth.cols; n++)
        {
            // 获取深度图中(m,n)处的值
            ushort d = depth.ptr(m)[n];
            // d 可能没有值,若如此,跳过此点
            if (d == 0)
                continue;
            // d 存在值,则向点云增加一个点
            PointT p;

            // 计算这个点的空间坐标
            p.z = double(d) / camera_factor;
            p.x = (n - camera_cx) * p.z / camera_fx;
            p.y = (m - camera_cy) * p.z / camera_fy;
            
            // 从rgb图像中获取它的颜色
            // rgb是三通道的BGR格式图,所以按下面的顺序获取颜色
            p.b = rgb.ptr(m)[n*3];
            p.g = rgb.ptr(m)[n*3+1];
            p.r = rgb.ptr(m)[n*3+2];

            // 把p加入到点云中
            cloud->points.push_back( p );
        }
    // 设置并保存点云
    cloud->height = 1;
    cloud->width = cloud->points.size();
    cout<<"point cloud size = "<points.size()<is_dense = false;
    pcl::io::savePCDFile( "./data/pointcloud.pcd", *cloud );
    // 清除数据并退出
    cloud->points.clear();
    cout<<"Point cloud saved."<

参考文献:

  1. Hartley, Richard and Zisserman, AndresMultiple View Geometry. Slides CVPR-Tutorial, 1999. http://users.cecs.anu.edu.au/~hartley/Papers/CVPR99-tutorial/tutorial.pdf
  2. Kläser, AlexanderKamerakalibrierung und Stereo Vision. Written report MIBI-Seminar, FH Bonn-Rhein-Sieg, 2005. http://www2.inf.fh-bonn-rhein-sieg.de/mi/lv/smibi/ss05/stud/klaeser/klaeser_ausarbeitung.pdf
  3. Wikipedia (engl.)Pinhole camera modelhttp://en.wikipedia.org/wiki/Pinhole_camera_model 
  4. http://www.comp.nus.edu.sg/~cs4243/lecture/camera.pdf 
  5. http://pille.iwr.uni-heidelberg.de/~kinect01/doc/reconstruction.html
  6. http://pille.iwr.uni-heidelberg.de/~kinect01/doc/classdescription.html#kinectcloud-section

你可能感兴趣的:(利用Kinect深度图像生成三维点)