letmaik / rawpy

📷 RAW image processing for Python, a wrapper for libraw
https://pypi.python.org/pypi/rawpy
MIT License
613 stars 68 forks source link

14-bit image has higher pixel values than 14-bit (with no_auto_scale=True) #101

Closed jocampo2 closed 4 years ago

jocampo2 commented 4 years ago

Hello,

I'm loading a 14-bit .CR2 file and after post processing the image has a max value of 24587. It should have a max of 16384. Do you know why this would be the case?

rawImg = rawpy.imread('image.CR2')
rawImg14 = rawImg.postprocess(gamma=(1,1), 
                              no_auto_bright=True, 
                              output_bps=16, 
                              median_filter_passes=0,
                              no_auto_scale=True)

after this rawImg14.max() = 24587 but with no_auto_scale=False, rawImg14.max() = 65535 it's saturated

there were only 50 pixels with values actually over 2^14

rawpy version is '0.14.0' python 3.7 Camera used is Canon eos 1100d ISO 200 shutter speed 30s

Cheers,

Jeremy

kmilos commented 4 years ago

White balance is applied, with 1.0 for green, red/blue then have >1.0

jocampo2 commented 4 years ago

White balance is applied, with 1.0 for green, red/blue then have >1.0

I've tried setting user_wb=[1,1,1,1] but the max is still the same, I think theres some other postprocessing step I haven't considered yet.

However if I do rawImg.raw_image.max() , I get 16316 which is about right

kmilos commented 4 years ago

You might also want to try output_color=rawpy.ColorSpace.raw since the color conversion matrix also has coeffs >1.0 typically...

Also, don't forget the black level is subtracted first, and for your camera it seems you want to check against raw_image_visible...

But in any case, there seems to be something not so intuitive going on w/ no_auto_scale=True, as any white balance setting doesn't have any effect...

kmilos commented 4 years ago

After cross-checking w/ dcraw, I found this clue in the output:

"Scaling with darkness 2047, saturation 13584"

which means the values will be scaled to 0-65535 range by factor of 65535/(13584-2047) and that's why you saw a higher number than expected. 2047 is of course the black level of your camera model you can also check w/ rawpy.black_level_per_channel, but the white/saturation level 13584 is camera model specific and hard-coded inside dcraw/LibRaw (somewhat below the 14-bit max in your case), and not reported by rawpy.

There is no equivalent of no_auto_scale=True in dcraw, so I'm not sure what LibRaw really does with it. I find it strange that this option renders e.g. user_wb, use_camera_wb, or use_auto_wb useless. This is probably a question for the LibRaw forum rather than here.

The current workaround I found to preserve the photometric values is to fake the no scaling by e.g. setting user_black=2047 and user_sat=67582 (65535+2047) so the range after black level removal is 0-65535 and scaling factor evaluates to 1.0

@letmaik Maybe this is an argument to expose the white level info alongside the black level so advanced users can check it and manipulate their raw data accordingly? My guess is rawdata.colordata.maximum or some evaluation together w/ linear_max[4] like it's done for the black level...

letmaik commented 4 years ago

@kmilos I'm happy to expose more metadata as long as it's meaningful. Please open a new issue for this with the required new metadata if you think that's the right way to go.

kmilos commented 4 years ago

@letmaik I've opened PR https://github.com/letmaik/rawpy/pull/102

letmaik commented 4 years ago

Since #102 is merged, is there anything left to do here? It seems there is a way for pro-users to work-around the issue now (after the next rawpy release), and anything else should be a change to LibRaw I assume. I think this trick should be documented though. @jocampo2 Do you think it makes sense to have a jupyter notebook on this in https://github.com/letmaik/rawpy-notebooks ?

jocampo2 commented 4 years ago

Since #102 is merged, is there anything left to do here? It seems there is a way for pro-users to work-around the issue now (after the next rawpy release), and anything else should be a change to LibRaw I assume. I think this trick should be documented though. @jocampo2 Do you think it makes sense to have a jupyter notebook on this in https://github.com/letmaik/rawpy-notebooks ?

I don't think this problem was significant enough for a whole notebook, maybe a section of a notebook

letmaik commented 4 years ago

Closing this now. There's a new rawpy pre-release that contains the white level data. See the README on how to install pre-releases. If there's anything left to do here, feel free to comment, but for now I'm closing this.