0

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

user3178756
  • 555
  • 1
  • 5
  • 17
  • 1
    Please provide a proper **Minimum, Complete and Verifiable Example**. – Mark Setchell Nov 15 '18 at 19:21
  • Please also share the troublesome file. – Mark Setchell Nov 15 '18 at 21:12
  • As you have sized your OpenCV Mat to the exact width and height of the image in the EXR buffer, surely you better set the base pointer exactly at the start of the Mat? So I am suggesting you change to `(char*)(inputImage.data), // base pointer` – Mark Setchell Nov 15 '18 at 21:27
  • @MarkSetchell Thanks for your suggestion. I fixed the code with your suggestion but the problem of rounding is still there. I've uploaded the exr file that I'm trying to read. – user3178756 Nov 16 '18 at 09:26
  • 1
    I think `sizeof(CV_32F)*1` and `sizeof(CV_32F)*width` are wrong and you should use `sizeof(float)` and `sizeof(float)*width` because `CV_32F` is an enumeration in a list of types rather than an actual type. – Mark Setchell Nov 16 '18 at 09:59
  • I make your image to be 960x540 pixels but have trouble doing much with it. – Mark Setchell Nov 16 '18 at 10:00
  • I have managed to open your image in **Photoshop**, **ImageMagick** and **CImg** but they all show nothing but black pixels. Is that file correct? – Mark Setchell Nov 16 '18 at 11:26
  • @MarkSetchell thanks for your help! with the fixes that you suggested it works now. I don't know why but it happens when one tries to open it like that it shows all the values to be black. I've opened it in matlab with tinyEXR and it is correct. – user3178756 Nov 16 '18 at 11:56
  • Cool - I may summarise the couple of issues into an answer later that you could consider accepting then other folk can see more easily what the correct code is without having to ramble through the comments. Glad it's working now :-) – Mark Setchell Nov 16 '18 at 12:10

1 Answers1

2

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.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432