Kinect学习(5)——深度图与彩色图配准(学习版1)

目前找到了几个Kinect配准程序,都跑通了,先学习一下他们的想法,代码都添加了注释。
我的环境:Win 10 + Kinect 2.0+VS 2013 + OpenCV 2.4.13

1、Kinect深度图与彩色图的坐标校准

作者:Michael__Shi
作者环境:Windows 8.1 + Kinect 2.0 + VS 2012 + OpenCV2.4.8

先用规则的长方体来测一下在深度图和彩色图中的同一边长的比例,为了测量更加准确,就把深度图同一时间的深度图和彩色图给截图下来,然后通过matlab来实现坐标显示,来得到同一位置长方体的同一边长,通过求几组数据的平均得到深度图和彩色图的比例,这样,在使用OpenCV的resize函数便将深度图和彩色图的比例调整为1:1了。最后通过将同一点在深度图和彩色图中的坐标关系来将两种图的坐标关系对应好,这样便实现了坐标的对应,通过opencv的ROI来将两幅图重合的部分裁剪下来,并且在同一幅画面中显示。

核心代码:
1)深度图处理

    // 之前已经把深度数据转换为8位RGB像素,下面把深度像素转存到8位4通道的Mat内  
    Mat DepthImage(nHeight, nWidth, CV_8UC4, m_pDepthRGBX);  
    Mat show = DepthImage.clone();  

    // 用resize函数把宽、高分辨率都扩大到原来的1.437倍,存储到showImageDepth内  
    resize(DepthImage, show, Size(cDepthWidth*1.437 , cDepthHeight*1.437));  
    showImageDepth = show.clone();  

    // 显示的仍然是原始分辨率           
    imshow("DepthImage", show);  

2)彩色图处理和配准

    // 之前已经获取了彩色图的8位RGB像素,下面把彩色图像素转存到8位4通道Mat内
    Mat ColorImage(nHeight, nWidth, CV_8UC4, pBuffer);

    // 用resize函数把宽、高分辨率都缩小为原来的1/2 
    Mat showImage = ColorImage.clone();
    resize(ColorImage, showImage, Size(nWidth / 2, nHeight / 2));

    // 矩形Rect,函数原型是 Rect_(_Tp _x, _Tp _y, _Tp _width, _Tp _height); 
    // 前两个参数表示矩形左上角的坐标,后两个参数表示矩形的宽和高 
    Rect rect(145, 0, 702, 538);

    // 偏移量为(33,-145),即彩色(i,j)对应深度(i+33,j-145)
    // opencv坐标对应关系是(x,y)对应(列号col,行号row)
    // 对应坐标的深度与彩色像素按照 0.6:0.4 比例相加混合到新的Mat showImage内
    int x = 33, y = -145;
    for (int i = 0; i <540; i++)
        for (int j = 145; j < 960 - 114; j++)
            showImage.at<Vec4b>(i, j) = showImageDepth.at<Vec4b>(i + x, j + y)*0.6 + showImage.at<Vec4b>(i, j)*0.4;

    // 用矩形指定showImage的感兴趣区域(不感兴趣区域应该是配准效果不好的区域)
    Mat image_roi = showImage(rect);
    // 显示感兴趣区域,也是配准后的结果 
    imshow("Image_Roi", image_roi);

总结起来就是,先测量了深度图和彩色图上同一边长的比例,测量结果是1.437x2=2.874;然后在Opencv里按这个比例把两幅图调整成同样大小,深度图尺寸放大1.437倍,彩色图尺寸缩小一半;最后考虑到边缘的配准效果不好,因此只保留和显示中间配准好的矩形区域。

这个方法相当于只做了尺寸变换,还真是简单粗暴啊。。。另外2.874的比例应该是图内物体长度的比例,而不是图片的比例吧

2、通过Kinect v2.0+ VS2012+openCV2.4.9将彩色帧映射到深度空间

作者:xx__hu
这段程序是基于MapColorFrameToDepthSpace实现配准的。

核心代码:

    //Color Frame 获取彩色图,为了避免尺寸太大显示不便,用resize把彩色图的宽、高都缩小为原来的一半,存在CV_8UC4的colorMat内
    ... ...
    resize(colorBufferMat, colorMat, Size(), 0.5, 0.5);

    //Depth Frame 获取彩色图,convertTo函数的作用是转换数据类型不同的Mat,这里的意义是把深度数据转化为像素值
    ... ...
    depthBufferMat.convertTo(depthMat, CV_8U, -255.0f / 8000.0f, 255.0f);

    // Mapping ( Depth to Color ) 配准
    if (SUCCEEDED(hResult))
    {
        // 深度空间坐标点集
        vector<DepthSpacePoint> depthSpacePoints(colorWidth *colorHeight);

        // 实际的配准语句,这里就用了MapColorFrameToDepthSpace函数,函数说明在下面
        hResult = pCoordinateMapper->MapColorFrameToDepthSpace(depthWidth * depthHeight,
            reinterpret_cast<UINT16*>(depthBufferMat.data), colorWidth *colorHeight,
                &depthSpacePoints[0]);

        if (SUCCEEDED(hResult))
        {
            CoordinateMapperMat = Scalar(0, 0, 0, 0); // 定义为Mat(colorHeight, colorWidth, CV_8UC4)
            // 遍历彩色图所有的点
            for (int y = 0; y < colorHeight; y++)
            {
                for (int x = 0; x < colorWidth; x++)
                {
                    // 按照彩色图像素坐标生成深度坐标点集的索引index,根据索引得到对应深度点
                    unsigned int index = y * colorWidth + x;
                    DepthSpacePoint p = depthSpacePoints[index];
                    // 如果对应深度点坐标没有超限,就把对应彩色点赋给新Mat CoordinateMapperMat(?)
                    if (p.X != -std::numeric_limits<float>::infinity() && p.Y != -std::numeric_limits<float>::infinity())
                    {
                        int depthX = static_cast<int>(p.X + 0.2f);
                        int depthY = static_cast<int>(p.Y + 0.2f);

                        if ((depthX >= 0) && (depthX < depthWidth) && (depthY >= 0) && (depthY < depthHeight))
                        {
                            CoordinateMapperMat.at<Vec4b>(y, x) = colorBufferMat.at<Vec4b>(y, x);                               
                        }
                    }
                }
            }
        }
    }
    imshow("depth", depthMat);
    imshow("color", colorMat);
    // CoordinateMapperMat就是要显示的配准结果
    imshow("CoordinateMapper", CoordinateMapperMat); 
ICoordinateMapper::MapColorFrameToDepthSpace Method

根据官网上MapColorFrameToDepthSpace的函数说明:
Uses the depth frame data to map the entire frame from color space to depth space.
使用深度帧数据,从彩色空间向深度空间映射整个帧。

public:
HRESULT MapColorFrameToDepthSpace(
         UINT depthDataPointCount,
         const UINT16 *depthFrameData,
         UINT depthPointCount,
         DepthSpacePoint *depthSpacePoints
)
  • depthDataPointCount:深度数据点的数量,就是深度图的宽x高
  • depthFrameData:深度帧数据
  • depthPointCount:深度点的数量,实际上是指要匹配的深度点的数量,也就是彩色点的数量,彩色图的宽x高
  • depthSpacePoints:要存放深度空间点坐标的集合

函数运行后,depthSpacePoints内按彩色图像素的顺序存放对应的深度点坐标。之后按彩色图像素逐行扫描的顺序遍历坐标集合,如果配准正确(坐标有效),就把该点的彩色像素值赋给一个和彩色图同样大小类型的Mat,并显示出来。所以,所谓的配准结果其实是残缺的彩色图的样子,正常显示的地方表示配准成功,没有像素的地方(黑色)表示配准失败。

实际运行结果还可以,残缺区域主要来源于深度图的残缺。但帧率很慢,大约也就1fps左右吧。另外,我觉得应该按上一个例子那样把深度图和彩色图叠加起来显示,这样才能更直观的看出配准结果。

另外,还有一些Kinect配准的例子和教程,还没有实践和详细研究,记录如下:

其他:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容