我有一组相同场景但使用不同曝光拍摄的图像。这些图像没有 EXIF 数据,因此无法提取有用的信息,例如 f-stop、快门速度等。
我想要做的是确定图像之间的停止差异,即 Image1 是 Image0 的 +1.3 停止。
我目前的方法是首先使用等式从图像的 RGB 值计算亮度
L = 0.2126 * R + 0.7152 * G + 0.0722 * B
我看到方程式中使用了不同的数字,但通常它不会对最终结果 L 产生太大影响。
之后我推导出图像的对数平均亮度。
exp(avg of log(luminance of image))
但不知何故,log-avg 亮度似乎并没有对图像之间的曝光差异给出太多指示。 关于如何确定曝光差异的任何想法?
编辑:在 c/c++ 上
最佳答案
你通常必须解决两个问题:
<强>1。线性化您的图像数据
(如果不是很明显是什么意思:像素收集的光量增加两倍将导致线性化图像中的强度值增加两倍。)
您的图像输入可能已经(充分)线性化 -> 您可以跳到第 2 部分。如果您的内容来自相机并且是 JPEG,那么情况肯定不是这样。
此问题的真正“解决方案”是找到相机响应函数,您要将其反转并应用于图像数据以获得线性强度值。这绝不是一项微不足道的任务。 EMoR模型广泛用于各种软件(Photoshop、PTGui、Photomatix 等)来描述相机响应函数。解决这个问题的一些开源软件(但使用不同的模型 iirc)是 PFScalibrate .
话虽如此,您可以使用简单的反 Gamma 应用程序。可以通过执行以下操作找到正确 Gamma 值的粗略“估计”:
- 使用两次曝光时间 e 和 e/2 捕捉光线均匀的静态场景
- 对两幅图像应用一对反 Gamma 变换(例如,1.8 到 2.4,步长为 0.1)
- 将所有短曝光图像乘以 2.0,然后从相应的长曝光图像中减去它们
- 选择导致最小总体差异的 gamma
<强>2。找出停止照射的实际差异,即 log2(scale factor)
假设场景是静态的(没有移动的物体或相机),这相对容易:
sum1 = sum2 = 0
foreach pixel pair (p1,p2) from the two images:
if p1 or p2 is close to 0 or 255:
skip this pair
sum1 += p1 and sum2 += p2
return log2(sum1 / sum2)
在大图像上,如果对图像进行子采样,这肯定会同样有效,而且速度会快得多。
如果相机是静止的但场景不是(移动的物体),则此方法开始效果不佳。在这种情况下,我通过简单地重复上述过程几次并使用上一次运行的输出作为正确比例因子的估计,然后丢弃商与当前估计相差太远的像素对,得到了可接受的结果。所以基本上用以下内容替换上面的 if
行:
if <see above> or if abs(log2(p1/p2) - estimate) > 0.5:
我会在固定次数的迭代后或如果两个连续的估计彼此足够接近时停止重复。
编辑:关于转换为亮度的注释
您根本不需要这样做(正如 Tony D 已经提到的那样),如果您坚持要这样做,那么在线性化步骤之后再做(正如 Mark Ransom 指出的那样)。在完美的设置(静态场景、无噪声、无去马赛克、无量化)中,每个像素的每个 channel 都将具有相同的比率 p1/p2
(如果两者都不饱和)。因此,不同 channel 的相对权重是无关紧要的。您可以对所有像素/ channel 求和(平均权衡 R、G 和 B)或者只使用绿色 channel 。
关于c++ - 确定没有 EXIF 数据的图像之间的停止差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14433051/