Search code examples
c++arraysopencvkinectopenni

Retrieving depth by using pointer in OpenCV


The following piece of code works well in retrieving depth value at row 240 and col 320.

    capture.retrieve( rawdepth, CV_CAP_OPENNI_DEPTH_MAP); // Mat rawdepth(Size(640,480), CV_16UC1);
    cout << "rows: " << rawdepth.rows << " cols: " << rawdepth.cols << endl;
    cout << "depth is " << rawdepth.at<unsigned short>(rawdepth.rows/2,rawdepth.cols/2) << endl;

If I stand in front of Kinect at 1m, it gives value approx. 900-1100. But when I added this following code, and I stand in front of kinect camera, both yield different result.

        uint16_t* depthdata = (uint16_t*)rawdepth.data;
        cout << "depthdata is " << depthdata[76800] << endl;

depthdata[76800] always yields 0, even if I move kinect to face other direction.

If I use the following code, and face the Kinect against a flat wall, (rawdepth.rows/2,rawdepth.cols/2) gives same result as depthdata[78600].

        uint16_t* depthdata = (uint16_t*)rawdepth.data;
        cout << "depthdata is " << depthdata[78600] << endl;

My question is, if depthdata at 76800 is not equal to (rawdepth.rows/2, rawdepth.cols/2), I wonder, what is? I obtained 76800 from 240*320.


Solution

  • If a matrix is row aligned, the way to access an element at position (x, y) is by using something like:

        matrix[y*elements_per_row + x]
    

    Matrices in OpenCV are designed to be 32-bit aligned, so there is often some padding at the end of each row. CvMat has a field size_t step which tells you the width of each row in bytes.

    try this, and see if it gives the result you expect:

        uint8_t* depthdata = (uint8_t*)rawdepth.data;
        uint16_t middle_element = *(uint16_t *)(depthdata + rawdepth.step*240 + sizeof(uint16_t)*320);
        cout << "depthdata is " << middle_element << endl;
    

    ref: OpenCV's cv::Mat & CvMat row alignment