Ask Your Question

Gamma, Tonemapping, - basics hdr

asked 2019-11-16 02:15:38 -0500

Daz gravatar image

updated 2019-11-16 11:10:34 -0500


Fairly new here, going over the docs currently. But before I start climbing the wall... can any1 clear up some things for me?

  1. I have a HDR 32 bit per channel, 3 channels. As far as I can tell that is "CV_32FC3" ?
  2. How can I print-text stuff like mat.type() ? I get a number, but I don't know where to look at to figure out what it is.
  3. How can I control gamma, is there dedicated function or do I just get bits and run a loop function over the array? - feels a bit slow if I have to do it on cpu... does openCV offer any openGL/etc option for it?
  4. I've created a Mat using this command > cv::Mat img(FreeImage_GetHeight(hdrImage), FreeImage_GetWidth(hdrImage), CV_32FC4, FreeImage_GetBits(hdrImage), FreeImage_GetPitch(hdrImage));

    Now when I do qDebug() << "Type type ? : " << CV_32FC4; I get a number 29, but when I do qDebug()<<img.type() I get something like 21. - what did I miss understand here? - I messed up conversion cvtColor(img, img, COLOR_BGRA2RGBA); I'm now getting proper type!

    And then when trying to do img.convertTo(img, CV_8SC4/CV_8UC4); I get lots of bad stuff/crashes. I want to convert here from 32 bit per channel image rgba to 8 bit or uchar per channel. How can I accomplish it properly?

Am I even calling the things I want to do correctly?

So far thats it, I'll update the topic as I solve the issues. So far its exciting stuff :- )


Got stuck with more conversions.. I have the given CV_32FC4 image that come from freeImage that is EXR. I then want to convert it to 8 bit for QImage but all I get is zip. I tried convertTo(CV8/16/U/S/C4)etc/etc but no luck.

raw9 = QImage((const uchar *), img.cols, img.rows, img.step, QImage::Format_RGBA8888); // no luck

raw9 = QImage((const uchar *), img.cols, img.rows, img.step, QImage::Format_RGBA64); // no luck

Any helps would be amazing, I'm getting lost with these bits/bytes/channels... :- C

I had some luck via accessing directly and converting to what I need... like :

        auto imgData = reinterpret_cast<float *>(;
        for (int a = 0; a < data.size(); a = a + img.channels()) {
            data[a] = imgData[a] * 255;
            data[a + 1] = imgData[a + 1] * 255;
            data[a + 2] = imgData[a + 2] * 255;
            data[a + 3] = imgData[a + 3] * 255;

But I get some bad red/yellow pixels > Bad Pixels - How to bite/solve it?

Above issues got solved magically by img.convertTo(img,CV_8U,255) < the 255 "scale factor" does something magical! Thank you barek for help!

Ok moving on... we solved the bit depth conversion... Now.. gamma! :D

As far as I can tell this "works"

cv::pow(img, 1.0f / 2.2f, img);
img.convertTo(img, CV_8U, 255);

But as I have RGBA the alpha gets also gamma corrected which is not desired...

Does ... (more)

edit retag flag offensive close merge delete


I have the given CV_32FC4 image that come from freeImage that is EXR.

are you really sure it has 4 channels, not 3 ? (exr images rarely have an alpha channel, it would not make much sense)

berak gravatar imageberak ( 2019-11-16 04:37:21 -0500 )edit

I have multiple HDR/EXR images, with 3-4 channels. Some exr are multi-layered and I didn't even start looking into them yet. So yep I'm "for now" sure I have 4 channels available in the file.

Daz gravatar imageDaz ( 2019-11-16 08:23:07 -0500 )edit

imho, your gamma correction workflow above is correct.

berak gravatar imageberak ( 2019-11-16 09:05:24 -0500 )edit

I have follow up question :- ) does extractChannel produce a deepCopy or shallow one? / same goes for Split ?

Daz gravatar imageDaz ( 2019-11-16 09:36:28 -0500 )edit

deep copy, think of it, the internal Mat representation is BGRABGRABGRA... and youwant a specific channel extracted.

berak gravatar imageberak ( 2019-11-16 14:26:29 -0500 )edit

1 answer

Sort by ยป oldest newest most voted

answered 2019-11-16 04:25:56 -0500

berak gravatar image

updated 2019-11-16 04:36:21 -0500

  1. YES ;)
  2. cv::typeToString()
  3. there is a cuda gamma corrrection, but afaik, no cpu version
  4. convertTo() changes the Mat's depth, e.g. from float to uchar, NOT the channels or the colorspace, that's what cvtColor() is for.
  5. please DON'T write loops for this. there will always be a builtin function, that does the job faster, less error prone , etc. (you probably would have neded a saturate_cast<uchar>() to avoid the overflow).

long story short, it needs 2 steps to go from CV_32FC4 to CV_8U:

Mat hdr(FreeImage_GetHeight(hdrImage), FreeImage_GetWidth(hdrImage), CV_32FC4, FreeImage_GetBits(hdrImage), FreeImage_GetPitch(hdrImage));

Mat bgr;
hdr.convertTo(bgr, CV_8U, 255);
Mat gray;
edit flag offensive delete link more


This is unbelievable. I tried it soo many time with no luck! Ok so you have passed 255 as alpha. - it appear to be the thing that fixed it. Why does openCV not take alpha from EXR? The format is RGBA, I should have alpha from CV_32FC4 to CV_8UC4, but it apparently is black... Why what? - it say its "optional scale factor" what does that mean O_O Looks like for 16U I need 16 bit max val! :D img.convertTo(img, CV_16U, 65535);

Daz gravatar imageDaz ( 2019-11-16 08:21:40 -0500 )edit

Looks like for 16U I need 16 bit max val! :D img.convertTo(img, CV_16U, 65535);

you got it ;)

berak gravatar imageberak ( 2019-11-16 08:59:17 -0500 )edit
Login/Signup to Answer

Question Tools

1 follower


Asked: 2019-11-16 02:09:30 -0500

Seen: 39 times

Last updated: Nov 16