Search code examples
c++opencvkinectopenni

Convert cv::Mat to openni::VideoFrameRef


I have a kinect streaming data into a cv::Mat. I am trying to get some example code running that uses OpenNI.

Can I convert my Mat into an OpenNI format image somehow?

I just need the depth image, and after fighting with OpenNI for a long time, have given up on installing it.

I am using OpenCV 3, Visual Studio 2013, Kinect v2 for Windows.

The relevant code is:

void CDifodoCamera::loadFrame()
{
    //Read the newest frame
    openni::VideoFrameRef framed; //I assume I need to replace this with my Mat...
    depth_ch.readFrame(&framed);

    const int height = framed.getHeight();
    const int width = framed.getWidth();

    //Store the depth values
    const openni::DepthPixel* pDepthRow = (const openni::DepthPixel*)framed.getData();
    int rowSize = framed.getStrideInBytes() / sizeof(openni::DepthPixel);

    for (int yc = height-1; yc >= 0; --yc)
    {
        const openni::DepthPixel* pDepth = pDepthRow;
        for (int xc = width-1; xc >= 0; --xc, ++pDepth)
        {
            if (*pDepth < 4500.f)
                depth_wf(yc,xc) = 0.001f*(*pDepth);

            else
                depth_wf(yc,xc) = 0.f;
        }

        pDepthRow += rowSize;
    }
}

Solution

  • First you need to understand how your data is coming... If it is already in cv::Mat you should be receiving two images, one for the RGB information that usually is a 3 channel uchar cv::Mat and another image for the depth information that usually it is saved in a 16 bit representation in milimeters (you can not save float mat as images, but you can as yml/xml files using opencv).

    Assuming you want to read and process the image that contains the depth information, you can change your code to:

    void CDifodoCamera::loadFrame()
    {
        //Read the newest frame
        //the depth image should be png since it is the one which supports 16 bits and it must have the ANYDEPTH flag
        cv::Mat depth_im = cv::imread("img_name.png",CV_LOAD_IMAGE_ANYDEPTH); 
    
        const int height = depth_im.rows;
        const int width = depth_im.cols;
    
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                if (depth_im<unsigned short>(y,x) < 4500)
                    depth_wf(y,x) = 0.001f * (float)depth_im<unsigned short>(y,x);
    
                else
                    depth_wf(y,x) = 0.f;
            }
        }
    }
    

    I hope this helps you. If you have any question just ask :)