Kinect for Windows v2深度到彩色图像不对齐 [英] Kinect for Windows v2 depth to color image misalignment

查看:3201
本文介绍了Kinect for Windows v2深度到彩色图像不对齐的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

目前我正在为Kinect for Windows v2开发一个工具(类似于XBOX ONE中的工具)。我试着跟随一些例子,并有一个工作示例,显示相机图像,深度图像,以及使用opencv将深度映射到rgb的图像。但是我看到它在映射时复制了我的手,我认为这是由于坐标映射器部分出错了。



这里是一个例子:



这里是创建图像的代码片段(示例中为rgbd图像)

  void KinectViewer :: create_rgbd(cv :: Mat& cv :: Mat& rgb_im,cv :: Mat& rgbd_im){
HRESULT hr = m_pCoordinateMapper-> MapDepthFrameToColorSpace(cDepthWidth * cDepthHeight,(UINT16 *)depth_im.data,cDepthWidth * cDepthHeight,m_pColorCoordinates);
rgbd_im = cv :: Mat :: zeros(depth_im.rows,depth_im.cols,CV_8UC3);
double minVal,maxVal;
cv :: minMaxLoc(depth_im,& minVal,& maxVal);
for(int i = 0; i for(int j = 0; j if(depth_im.at (i,j)>(i,j)> 0&&& depth_im.at< UINT16>(i,j)< maxVal *(max_z / 100)& * min_z / 100){
double a = i * cDepthWidth + j;
ColorSpacePoint colorPoint = m_pColorCoordinates [i * cDepthWidth + j];
int colorX =(int)(floor(colorPoint.X + 0.5));
int colorY =(int)(floor(colorPoint.Y + 0.5));
if((colorX> = 0)&&(colorX< cColorWidth)&&(colorY> = 0)&&(colorY< cColorHeight))
{
rgbd_im.at< cv :: Vec3b>(i,j)= rgb_im.at< cv :: Vec3b>(colorY,colorX)
}
}

}
}
}

有没有人有一个如何解决这个问题的线索?如何防止此重复?



提前感谢



更新: p>

如果我做一个简单的深度图像阈值,我得到下面的图像:



这或多或少是我期望发生的,并且在后台没有重复的手。有没有办法在后台阻止这个重复的手?

解决方案

我建议你使用BodyIndexFrame来识别一个特定的值属于玩家。这样,您可以拒绝不属于播放器的任何RGB像素,并保留其余的。我不认为CoordinateMapper在说谎。



一些注释:





  • 使用MapColorFrameToDepthSpace代替MapDepthFrameToColorSpace;

  • 找到相应的DepthSpacePoint和depthX,depthY,而不是ColorSpacePoint和colorX,colorY

  • ul>

    这是我的方法,当一个框架到达(它在C#):

      depthFrame.CopyFrameDataToArray(_depthData); 
    colorFrame.CopyConvertedFrameDataToArray(_colorData,ColorImageFormat.Bgra);
    bodyIndexFrame.CopyFrameDataToArray(_bodyData);

    _coordinateMapper.MapColorFrameToDepthSpace(_depthData,_depthPoints);

    Array.Clear(_displayPixels,0,_displayPixels.Length);

    for(int colorIndex = 0; colorIndex< _depthPoints.Length; ++ colorIndex)
    {
    DepthSpacePoint depthPoint = _depthPoints [colorIndex];

    if(!float.IsNegativeInfinity(depthPoint.X)&&!float.IsNegativeInfinity(depthPoint.Y))
    {
    int depthX =(int) .X + 0.5f);
    int depthY =(int)(depthPoint.Y + 0.5f);

    if((depthX> = 0)&&(depthX< _depthWidth)&&(depthY> = 0)& b $ b {
    int depthIndex =(depthY * _depthWidth)+ depthX;
    byte player = _bodyData [depthIndex];

    //确定该点是否属于玩家
    if(player!= 0xff)
    {
    int sourceIndex = colorIndex * BYTES_PER_PIXEL;

    _displayPixels [sourceIndex] = _colorData [sourceIndex ++]; // B
    _displayPixels [sourceIndex] = _colorData [sourceIndex ++]; // G
    _displayPixels [sourceIndex] = _colorData [sourceIndex ++]; // R
    _displayPixels [sourceIndex] = 0xff; // A
    }
    }
    }
    } b $ b

    这里是数组的初始化:

      BYTES_PER_PIXEL =(PixelFormats.Bgr32.BitsPerPixel + 7)/ 8; 

    _colorWidth = colorFrame.FrameDescription.Width;
    _colorHeight = colorFrame.FrameDescription.Height;
    _depthWidth = depthFrame.FrameDescription.Width;
    _depthHeight = depthFrame.FrameDescription.Height;
    _bodyIndexWidth = bodyIndexFrame.FrameDescription.Width;
    _bodyIndexHeight =bodyIndexFrame.FrameDescription.Height;
    _depthData = new ushort [_depthWidth * _depthHeight];
    _bodyData = new byte [_depthWidth * _depthHeight];
    _colorData = new byte [_colorWidth * _colorHeight * BYTES_PER_PIXEL];
    _displayPixels =新字节[_colorWidth * _colorHeight * BYTES_PER_PIXEL];
    _depthPoints = new DepthSpacePoint [_colorWidth * _colorHeight];

    请注意,_depthPoints数组的大小为1920x1080。



    同样,最重要的是使用BodyIndexFrame源。


    currently I am developing a tool for the Kinect for Windows v2 (similar to the one in XBOX ONE). I tried to follow some examples, and have a working example that shows the camera image, the depth image, and an image that maps the depth to the rgb using opencv. But I see that it duplicates my hand when doing the mapping, and I think it is due to something wrong in the coordinate mapper part.

    here is an example of it:

    And here is the code snippet that creates the image (rgbd image in the example)

    void KinectViewer::create_rgbd(cv::Mat& depth_im, cv::Mat& rgb_im, cv::Mat& rgbd_im){
        HRESULT hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(cDepthWidth * cDepthHeight, (UINT16*)depth_im.data, cDepthWidth * cDepthHeight, m_pColorCoordinates);
        rgbd_im = cv::Mat::zeros(depth_im.rows, depth_im.cols, CV_8UC3);
        double minVal, maxVal;
        cv::minMaxLoc(depth_im, &minVal, &maxVal);
        for (int i=0; i < cDepthHeight; i++){
            for (int j=0; j < cDepthWidth; j++){
                if (depth_im.at<UINT16>(i, j) > 0 && depth_im.at<UINT16>(i, j) < maxVal * (max_z / 100) && depth_im.at<UINT16>(i, j) > maxVal * min_z /100){
                    double a = i * cDepthWidth + j;
                    ColorSpacePoint colorPoint = m_pColorCoordinates[i*cDepthWidth+j];
                    int colorX = (int)(floor(colorPoint.X + 0.5));
                    int colorY = (int)(floor(colorPoint.Y + 0.5));
                    if ((colorX >= 0) && (colorX < cColorWidth) && (colorY >= 0) && (colorY < cColorHeight))
                    {
                        rgbd_im.at<cv::Vec3b>(i, j) = rgb_im.at<cv::Vec3b>(colorY, colorX);
                    }
                }
    
            }
        }
    }
    

    Does anyone have a clue of how to solve this? How to prevent this duplication?

    Thanks in advance

    UPDATE:

    If I do a simple depth image thresholding I obtain the following image:

    This is what more or less I expected to happen, and not having a duplicate hand in the background. Is there a way to prevent this duplicate hand in the background?

    解决方案

    I suggest you use the BodyIndexFrame to identify whether a specific value belongs to a player or not. This way, you can reject any RGB pixel that does not belong to a player and keep the rest of them. I do not think that CoordinateMapper is lying.

    A few notes:

    • Include the BodyIndexFrame source to your frame reader
    • Use MapColorFrameToDepthSpace instead of MapDepthFrameToColorSpace; this way, you'll get the HD image for the foreground
    • Find the corresponding DepthSpacePoint and depthX, depthY, instead of ColorSpacePoint and colorX, colorY

    Here is my approach when a frame arrives (it's in C#):

    depthFrame.CopyFrameDataToArray(_depthData);
    colorFrame.CopyConvertedFrameDataToArray(_colorData, ColorImageFormat.Bgra);
    bodyIndexFrame.CopyFrameDataToArray(_bodyData);
    
    _coordinateMapper.MapColorFrameToDepthSpace(_depthData, _depthPoints);
    
    Array.Clear(_displayPixels, 0, _displayPixels.Length);
    
    for (int colorIndex = 0; colorIndex < _depthPoints.Length; ++colorIndex)
    {
        DepthSpacePoint depthPoint = _depthPoints[colorIndex];
    
        if (!float.IsNegativeInfinity(depthPoint.X) && !float.IsNegativeInfinity(depthPoint.Y))
        {
            int depthX = (int)(depthPoint.X + 0.5f);
            int depthY = (int)(depthPoint.Y + 0.5f);
    
            if ((depthX >= 0) && (depthX < _depthWidth) && (depthY >= 0) && (depthY < _depthHeight))
            {
                int depthIndex = (depthY * _depthWidth) + depthX;
                byte player = _bodyData[depthIndex];
    
                // Identify whether the point belongs to a player
                if (player != 0xff)
                {
                    int sourceIndex = colorIndex * BYTES_PER_PIXEL;
    
                    _displayPixels[sourceIndex] = _colorData[sourceIndex++];    // B
                    _displayPixels[sourceIndex] = _colorData[sourceIndex++];    // G
                    _displayPixels[sourceIndex] = _colorData[sourceIndex++];    // R
                    _displayPixels[sourceIndex] = 0xff;                         // A
                }
            }
        }
    }
    

    Here is the initialization of the arrays:

    BYTES_PER_PIXEL = (PixelFormats.Bgr32.BitsPerPixel + 7) / 8;
    
    _colorWidth = colorFrame.FrameDescription.Width;
    _colorHeight = colorFrame.FrameDescription.Height;
    _depthWidth = depthFrame.FrameDescription.Width;
    _depthHeight = depthFrame.FrameDescription.Height;
    _bodyIndexWidth = bodyIndexFrame.FrameDescription.Width;
    _bodyIndexHeight = bodyIndexFrame.FrameDescription.Height;
    _depthData = new ushort[_depthWidth * _depthHeight];
    _bodyData = new byte[_depthWidth * _depthHeight];
    _colorData = new byte[_colorWidth * _colorHeight * BYTES_PER_PIXEL];
    _displayPixels = new byte[_colorWidth * _colorHeight * BYTES_PER_PIXEL];
    _depthPoints = new DepthSpacePoint[_colorWidth * _colorHeight];
    

    Notice that the _depthPoints array has a 1920x1080 size.

    Once again, the most important thing is to use the BodyIndexFrame source.

    这篇关于Kinect for Windows v2深度到彩色图像不对齐的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆