Domanda

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;
}
È stato utile?

Soluzione

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).

Altri suggerimenti

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
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top