1

I am currently working on a program which should take an LDR images and multiply certain pixel in the image, so that their pixel value would exceed the normal 0-255 (0-1) pixel value boundary. The program i have written can do so, but I am not able to write the image file, as the imwrite() in OpenCV clambs the values back in the range of 0-255 (0-1) if they are bigger than 255.

Is there anybody there who knows how to write a floating point image with pixel values bigger than 255 (1)

My code looks like this

Mat ApplySunValue(Mat InputImg)
{
 Mat Image1 = imread("/****/.jpg",CV_LOAD_IMAGE_COLOR);

Mat outPutImage;

Image1.convertTo(Image1, CV_32FC3);

for(int x = 0; x < InputImg.cols; x++){
    for(int y = 0; y < InputImg.rows; y++){

        float blue  = Image1.at<Vec3f>(y,x)[0] /255.0f;
        float green = Image1.at<Vec3f>(y,x)[1] /255.0f;
        float red = Image1.at<Vec3f>(y,x)[2] /255.0f ;

        Image1.at<Vec3f>(y,x)[0] = blue;
        Image1.at<Vec3f>(y,x)[1] = green;
        Image1.at<Vec3f>(y,x)[2] = red;

        int pixelValue = InputImg.at<uchar>(y,x);

        if(pixelValue > 254){


            Image1.at<Vec3f>(y,x)[0] = blue * SunMultiplyer;
            Image1.at<Vec3f>(y,x)[1] = green * SunMultiplyer;
            Image1.at<Vec3f>(y,x)[2] = red * SunMultiplyer;    
        }

    }

}

imwrite("/****/Nice.TIFF", Image1 * 255);

namedWindow("Hej",CV_WINDOW_AUTOSIZE);
imshow("hej", Image1);



return InputImg;
}
tshepang
  • 12,111
  • 21
  • 91
  • 136
  • Have you considered using OpenEXR? http://www.openexr.com http://stackoverflow.com/questions/2119099/using-exr-images-in-opencv – Mark Setchell Mar 27 '14 at 13:04
  • 1
    Thank's for you response. Yes, i have considered using openexr, but i keep getting this error message: ibc++abi.dylib: terminating with uncaught exception of type Iex::EnosysExc: Cannot initialize semaphore (Function not implemented). when trying to write a exr format. – Kristian Moesgaard Mar 27 '14 at 13:17
  • You want to save the file for visualization or just for storage purposes ? – BConic Mar 27 '14 at 13:30
  • I want to save the file for visualization purposes. – Kristian Moesgaard Mar 31 '14 at 11:11

2 Answers2

2

As far as I know, when opencv writes using imwrite, it writes in the format supported by the image container, and this by default is 255. However, if you just want to save the data, you might consider writing the Mat object to an xml/yaml file.

//Writing
cv::FileStorage fs;
fs.open(filename, cv::FileStorage::WRITE);
fs<<"Nice"<<Image1;

//Reading
fs.open(filename, cv::FileStorage::READ);
fs["Nice"]>>Image1;

fs.release(); //Very Important
The Nomadic Coder
  • 580
  • 1
  • 4
  • 16
2

For storage purposes, the following is more memory efficient than the XML / YAML alternative (due to the use of a binary format):

// Save the image data in binary format
std::ofstream os(<filepath>,std::ios::out|std::ios::trunc|std::ios::binary);
os << (int)image.rows << " " << (int)image.cols << " " << (int)image.type() << " ";
os.write((char*)image.data,image.step.p[0]*image.rows);
os.close();

You can then load the image as follows:

// Load the image data from binary format
std::ifstream is(<filepath>,std::ios::in|std::ios::binary);
if(!is.is_open())
    return false;
int rows,cols,type;
is >> rows; is.ignore(1);
is >> cols; is.ignore(1);
is >> type; is.ignore(1);
cv::Mat image;
image.create(rows,cols,type);
is.read((char*)image.data,image.step.p[0]*image.rows);
is.close();

For instance, without compression, a 1920x1200 floating-point three-channel image takes 26 MB when stored in binary format, whereas it takes 129 MB when stored in YML format. This size difference also has an impact on runtime since the number of accesses to the hard drive are very different.

Now, if what you want is to visualize your HDR image, you have no choice but to convert it to LDR. This is called "tone-mapping" (Wikipedia entry).

BConic
  • 8,750
  • 2
  • 29
  • 55
  • Thanks for your reply. Unfortunately I do need to visualize the HDR image. I will try to figure out how to tone map the image file. – Kristian Moesgaard Mar 27 '14 at 15:03
  • @KristianMoesgaard The simplest way to visualize an HDR image is to use "linear tone mapping", i.e. just divide by the maximum possible value (in your case `SunMultiplyer`) and multiply by 255. However, in your case, this will just give you back the input image ... – BConic Mar 27 '14 at 15:11