代码之家  ›  专栏  ›  技术社区  ›  JoeVictor

根据EV值调整原始图像的曝光

  •  2
  • JoeVictor  · 技术社区  · 6 年前

    我正在尝试编写一个程序,它接收一个满是12位原始传感器值的矩阵(范围在[512-4096]之间)(512是拜耳传感器的黑色级别-->即纯黑色定义为什么),并调整每个像素的EV,非常类似于Adobe Camera Raw(ACR)“Exposure”滑块。我想知道基本上是怎么做到的。我已经查阅了几十个博客,解释了电动汽车是如何计算的,看起来是:

    This link 似乎给出了以下公式:像素调整=像素*2^ev

    这似乎是非常错误的,因为5 EV的调整使图片WayYY失去了比例。我在网上找不到其他资源。维基百科在 Exposure Value 但它似乎也没有我要找的东西…有什么帮助吗?

    谢谢!

    以下是我的一个例子:

    ACR中EV为0的原始文件: Before

    EV 5: After

    我现在有这个公式:

    black_level = 512
    bit_depth = 2**12
    normalized = max((raw_pixel - black_level),0) / (bit_depth) ## normalize to [0,1]
    exposed = normalized * (2**EV)    ## expose by desired EV value
    
    ## scale back to normal level:
    raw_pixel_new = exposed * bit_depth  
    

    但这对任何非5的ev值都是失败的,所以公式是不正确的。我也知道这个公式是错误的,因为如果 EV = 0 . 我发现了几十个网站解释了这个公式 new_pixel = pixel * 2^exposure 但这似乎不适用于原始照片…我错过什么了吗?

    有什么想法吗?

    下面是我用来测试的一些python代码和文件:

    代码:
    import rawpy
    import numpy as np
    
    from PIL import Image
    
    bit_depth = 12
    black_level = 512
    exposure = 4
    
    
    path = "/001_ev0.DNG"
    raw = rawpy.imread(path)
    
    im = raw.raw_image_visible
    im = np.maximum(im - black_level, 0)
    im *= 2**exposure
    # im = im + black_level # for some reason commenting this out makes it slightly better
    im = np.minimum(im,2**12 - 1)
    raw.raw_image[:,:] = im
    im = raw.postprocess(use_camera_wb=True,no_auto_bright=True)
    img = Image.fromarray(im, 'RGB')
    img.show() #This should look like the file: 001_ev4.tif
    
    图像:

    https://drive.google.com/open?id=1T0ru_Vid8ctM3fDdbx1hvxNojOXOzXxg

    我为此花了14个小时…我不知道我做错了什么,因为我不知道该怎么做。 一贯地 工作(多个电动汽车)总是有一个绿色或洋红色调。我认为这是一张原始照片搞糟了绿色通道…

    1 回复  |  直到 6 年前
        1
  •  1
  •   Cris Luengo    6 年前

    假设你从一个原始图像开始,你就处在一个线性空间中。在这种情况下,改变曝光量是一个乘法运算。

    增加的 曝光值 (ev)乘以1相当于曝光量翻倍。 暴露 是达到每个像素的光量的线性度量。曝光量加倍,光照量加倍。因为在摄影中,人们通常会考虑当前曝光的分数,所以谈论“增加EV 1”,而不是“将曝光乘以2”是有意义的。

    因此,实际上,增加暴露值 n ,将像素值乘以2 n .

    如果输入的图像是一个jpeg或tiff文件,那么它很可能在sRGB颜色空间中。这是一个非线性颜色空间,用于增加8位图像文件的外观范围。在修改曝光之前,必须先将sRGB转换为线性RGB。这可以通过将每个像素值提高到2.2的幂来实现, Wikipedia has the exact formulation .


    操作中的问题是由不精确的黑色水平引起的。 raw.black_level_per_channel 对于给定的图像,返回528(每个通道的值相同,但我猜其他相机型号不一定如此),而不是512。此外,代码写入 raw.raw_image_visible 回到 raw.raw_image ,这是不正确的。

    以下代码产生正确的结果:

    import rawpy
    import numpy as np
    from PIL import Image
    
    bit_depth = 12
    exposure = 5
    
    path = "/001_ev0.DNG"
    raw = rawpy.imread(path)
    black_level = raw.black_level_per_channel[0] # assume they're all the same
    
    im = raw.raw_image
    im = np.maximum(im, black_level) - black_level # changed order of computation
    im *= 2**exposure
    im = im + black_level
    im = np.minimum(im, 2**12 - 1)
    raw.raw_image[:,:] = im
    im = raw.postprocess(use_camera_wb=True, no_auto_bright=True)
    img = Image.fromarray(im, 'RGB')
    img.show()
    
    推荐文章