I am trying to save a disparity map I got from stereo matching using cv::StereoSGBM in PFM format with this code from github.
But the output has the same image repeated 4 times over horizontally instead.
Same disparity saved in .jpg format for reference -
Why is this happening and how do I fix this?
Code:
PFMReadWrite.cpp
bool savePFM(const cv::Mat image, const std::string filePath)
{
//Open the file as binary!
ofstream imageFile(filePath.c_str(), ios::out | ios::trunc | ios::binary);
if(imageFile)
{
int width(image.cols), height(image.rows);
int numberOfComponents(image.channels());
//Write the type of the PFM file and ends by a line return
char type[3];
type[0] = 'P';
type[2] = 0x0a;
if(numberOfComponents == 3)
{
type[1] = 'F';
}
else if(numberOfComponents == 1)
{
type[1] = 'f';
}
imageFile << type[0] << type[1] << type[2];
//Write the width and height and ends by a line return
imageFile << width << " " << height << type[2];
//Assumes little endian storage and ends with a line return 0x0a
//Stores the type
char byteOrder[10];
byteOrder[0] = '-'; byteOrder[1] = '1'; byteOrder[2] = '.'; byteOrder[3] = '0';
byteOrder[4] = '0'; byteOrder[5] = '0'; byteOrder[6] = '0'; byteOrder[7] = '0';
byteOrder[8] = '0'; byteOrder[9] = 0x0a;
for(int i = 0 ; i<10 ; ++i)
{
imageFile << byteOrder[i];
}
//Store the floating points RGB color upside down, left to right
float* buffer = new float[numberOfComponents];
for(int i = 0 ; i<height ; ++i)
{
for(int j = 0 ; j<width ; ++j)
{
if(numberOfComponents == 1)
{
buffer[0] = image.at<float>(height-1-i,j);
}
else
{
Vec3f color = image.at<Vec3f>(height-1-i,j);
//OpenCV stores as BGR
buffer[0] = color.val[2];
buffer[1] = color.val[1];
buffer[2] = color.val[0];
}
//Write the values
imageFile.write((char *) buffer, numberOfComponents*sizeof(float));
}
}
delete[] buffer;
imageFile.close();
}
else
{
cerr << "Could not open the file : " << filePath << endl;
return false;
}
return true;
}
main.cpp
// Creating Disp map
stereomatching.computeDisparity(left, right, imgsize, disp);
// Writing PFM
cv::imwrite(outputpath + ".jpg", disp);
bool r = savePFM(disp, outputpath + ".pfm");
The code for writing output PFM file in principle looks OK. However, you are accessing individual pixels with assumption that they are encoded as 3-channel 32-bit floating point values and that might not always be the case (usually they are 3-channel unsigned 8-bit integers, and the weird image in your question hints that there was some invalid out of bounds read). You can either check the
image.type()
and adjust your code accordingly, or convert your input matrix to desiredCV_32FC3
(3-channel 32-bit floating point pixels) type. To convert, you can either use the built-in opencv functionor if that doesn't work good enough (e.g. you would like to apply your custom 8bit -> 32bit mapping), just access the elements of the original image by
and then apply some conversion from 8bit [0,255] to 32bit [0,1].
That's my best guess, because you didn't provide complete reproducible example.