[Python] Why does RawPy/Libraw increase the brightness range when postprocessing?

Discussão em 'Python' iniciado por Stack, Fevereiro 28, 2025.

  1. Stack

    Stack Membro Participativo

    I'm processing a raw photo1 with RawPy as follows:

    import numpy as np
    import rawpy

    with rawpy.imread('my_picture.nef') as rpy:
    raw = rpy.raw_image
    print('Raw:', raw.shape, np.min(raw), np.max(raw))

    image = rpy.postprocess(
    output_bps=16,
    no_auto_bright=True,
    no_auto_scale=True,
    user_wb=(1, 1, 1, 1),
    gamma=(1, 1),
    user_black=0,
    user_sat=65535
    )

    print('Processed:', image.shape, np.min(image), np.max(image))


    Which produces this output:

    Raw: (4016, 6016) 157 4087
    Processed: (4016, 6016, 3) 0 5589


    My understanding is that the call to rpy.postprocess() is configured to not adjust the brightness at all, except as a side effect of demosaicing.2 So I have two questions:


    1. Why did the min/max values widen from 157–4087 to 0–5589?


    2. Is there any way to predict the min/max values after postprocessing? Ideally, I want a formula like "if your black/saturation levels are ___ and ___, then the widest possible range after postprocessing is ___ to ___."
    Other Attempts and Demosaicing


    I understand that 4087 is the max value of the Bayer-patterned pixels in the raw image, while 5589 is the maximum R, G, or B value of some pixel. Thus, I tried adding the color channels together:

    >>> image = np.sum(image, axis=-1)
    >>> np.min(image), np.max(image)
    452 10743


    This didn't help much, as I don't see a clear relationship between 157–4087 and 452–10743. But maybe that's because there's nothing solid white or black in the image? Thus, I also tried things like this:

    with rawpy.imread('my_picture.nef') as rpy:
    rpy.raw_image[:] = 4095 # Or 0, or some other integer
    # OR
    rpy.raw_image[:] = np.random.randint(157, 4088, size=(4016, 6016))

    # Postprocessing like before ...


    Interestingly, when the raw image is all the same pixel value (1000, 4095, etc.) the output values aren't scaled. The min/max stay about the same. But using random numbers is basically equivalent to the real photo. I don't understand this phenomenon either.


    1 From a Nikon D3400, if that matters.

    2 There's also the adjust_maximum_thr parameter, which I don't fully understand, but messing with it didn't seem to change anything here.

    Continue reading...

Compartilhe esta Página