c++opencvdepthopenexr

Loading OpenEXR single channel depth map image


I am trying to load a depth image in OpenEXR format with one channel, however, I couldn't figure out the format that I need to use based on this documentation: http://www.openexr.com/documentation/ReadingAndWritingImageFiles.pdf

EDIT: I managed to read the file, but when I try to check the values, they are rounded to the closest integer but I don't understand why that happens.

    Imf::InputFile file (filename.c_str());
    Imath::Box2i dw = file.header().dataWindow();
    int width = dw.max.x - dw.min.x + 1;
    int height = dw.max.y - dw.min.y + 1;

    cv::Mat inputImage = cv::Mat::zeros(cv::Size(width,height), CV_32F );

    Imf::FrameBuffer frameBuffer;
    frameBuffer.insert ("Z", // name
    Imf::Slice (Imf::FLOAT, // type
        (char *) (inputImage.data), // base pointer
        sizeof(CV_32F)*1,         // xStride
        sizeof(CV_32F) * width, // yStride
        1, 1,      // x/y sampling
        0.0));     // fillValue

    file.setFrameBuffer (frameBuffer);
    file.readPixels (dw.min.y, dw.max.y);
    cout << inputImage.at<float>(285,562) << endl;

EDIT2: The exr file can be accessed from here: https://drive.google.com/file/d/1q_AmJgzJjs3bOCCpmcC-X-iAH88PY9dG/view?usp=sharing


Solution

  • I think I see two issues, both in the same function call:

    Imf::FrameBuffer frameBuffer;
    frameBuffer.insert ("Z", // name
    Imf::Slice (Imf::FLOAT, // type
        (char *) (inputImage.data  -  dw.min.x - dw.min.y * width), // base pointer
        sizeof(CV_32F)*1,         // xStride
        sizeof(CV_32F) * width, // yStride
        1, 1,      // x/y sampling
        0.0));     // fillValue
    

    Firstly, you OpenCV Mat is sized to the exact width and height of the OpenEXR image, which means you will have problems if you put it at any other place than at the very start of the Mat buffer. So, change this line:

    (char *) (inputImage.data  -  dw.min.x - dw.min.y * width), // base pointer
    

    to

    (char *) (inputImage.data), // base pointer
    

    Secondly, you use sizeof(CV_32F). The thing is though, that CV_32F is not a type, it is an element in an enumeration of types, so I think you should prefer sizeof(float) since your elements are floats.